flex 联机游戏开发 - 五子棋游戏:(一)游戏核心

刚看到flex做的东西的时候,一下子很怀念当年用applet编程的日子,applet真的算是互联网的美好时光之一,可惜在主流浏览器的绞杀下最终烟消云散,过了10年,adobe又把这东西拾起来做成了flex,而我,在羡慕adobe flash 98%的用户装机量的同时,也不得不选择了用flex来开发一些自己的应用,能信任silverlight吗,连微软都要风传收购adobe的时候?你能信任javafx吗,他自己历时10年都掌握不了主流的互联网浏览器,很意外oracle为什么不把firefox一起收购了。这样,。。这样。

Hello,wolrd是所有程序员的开始,五子棋游戏应该也算是所有联机游戏开发的开始吧,我今天用这个游戏来练练手,了解一下flex的主要功能,换肤技术等,力求用最真实的开发过程来展示开发中的问题与思考。

1) 巧妇难为无米之炊,先画一个棋盘吧,,我斩时希望这个棋盘基本素质是,横,竖 一些线条,另外,在每个线杀的交叉点上有一个默认的棋子。额外的素质是,1,棋盘的线条多少是可变的,2)棋子的点击半径是可变的。棋子的颜色是可变的。

好了。画棋盘。。

1) 五子棋棋盘

//棋子直径 

   private var radios:int=22; 

   //边间隔 

   private var padding:int=20; 

   //线条的多少,代表了五子棋的难度 

   private var totalsize:int=15; 

   //棋子的数组 

   private var boardArray:Array; 

   //默认的颜色,与背景色同, 

   private const DEFAULT_COLOR:SolidColor=new SolidColor(0xeeeeee,0); 

   //黑棋 

   private const BLACK_COLOR:SolidColor=new SolidColor(0x000000,1); 

   //白棋 

   private const WHITE_COLOR:SolidColor=new SolidColor(0xffffff,1); 

   //玩家一 

   private const PLAYER_RONE_TURN:int=0; 

   //玩家二 

   private const PLAYER_TWO_TURN:int=1; 

   //当前玩家 

   private var turn:int;



//y 轴的线条 

    for (var i:int=0;i<=totalsize;i++) 

    { 

     var line:Line=new Line(); 

     line.xFrom=0+padding; 

     line.xTo=board.width-padding; 

     line.y=i*(board.height-2*padding)/totalsize+padding; 

     line.stroke=new SolidColorStroke(0x000000,1,1,false); 

     board.addElement(line); 

    } 

    //x 轴的线条 

    for (var j:int=0;j<=totalsize;j++) 

    { 

     var line2:Line=new Line(); 

     line2.yFrom=0+padding; 

     line2.yTo=board.height-padding; 

     line2.x=j*(board.width-2*padding)/totalsize+padding; 

     line2.stroke=new SolidColorStroke(0x000000,1,1,false); 

     board.addElement(line2); 

    } 

    //默认的棋子, 

    for (var x:int=0;x<=totalsize;x++) 

    { 

     for (var y:int=0;y<=totalsize;y++) 

     { 

      var ellipse:Ellipse=new Ellipse(); 

      ellipse.width=radios; 

      ellipse.height=radios; 

      ellipse.x=x*(board.width-2*padding)/totalsize-radios/2+padding; 

      ellipse.y=y*(board.height-2*padding)/totalsize-radios/2+padding; 

      ellipse.fill=DEFAULT_COLOR; 

      board.addElement(ellipse); 

      boardArray[x][y]=ellipse; 

     } 

    }

棋盘的mxml文件中

<s:BorderContainer backgroundColor="#eeeeee" id="board" borderVisible="false"  verticalCenter="0" horizontalCenter="0" click="boardClick(event)" width="400" height="400"> 

</s:BorderContainer>

画出来的效果如图

2 五子棋事件

现在已经有锅了,开始上米,给棋盘添加点击事件,逻辑就是当用户点中上面的黑色的圆框时,我们就让这个圆框根据用户的角色变颜色。形成自己的棋子。点击后就将游戏当前玩家交给另一方。将上面那个棋盘的测试黑棋换成背景色就可以开始了。

protected function boardClick(event:MouseEvent):void{ 

    var posx:int=event.localX; 

    var posy:int=event.localY; 

    var clickEllipse:Ellipse; 

    for (var x:int=0;x<=totalsize;x++) 

    { 

     for (var y:int=0;y<=totalsize;y++) 

     { 

      var ellipse:Ellipse=boardArray[x][y] as Ellipse; 

      if (posx>=ellipse.x && posx<=(ellipse.x+radios)&&posy>=ellipse.y &&posy<=(ellipse.y+radios)) 

       { 

        clickEllipse=ellipse; 

        break; 

       } 

     } 

    } 

    if (clickEllipse==null) return; 

    if (clickEllipse.fill!=DEFAULT_COLOR) return; 

    if (turn==PLAYER_RONE_TURN) 

    { 

     clickEllipse.fill=BLACK_COLOR; 

     turn=PLAYER_TWO_TURN; 

    } 

    else 

    { 

     clickEllipse.fill=WHITE_COLOR; 

     turn=PLAYER_RONE_TURN; 

    } 

   }

效果如图。

3)五子棋胜负判断

现在,你如果跟你朋友下这个棋盘的话,把子填满也是分出胜负的,我们得加上一些判断胜负的条件,对于一个联机游戏,不涉及人工智能是比较简单的,当用户投子后我们只要判断用户的横,竖,斜4个方向是否有五个子连成一条线,有的话就表示用户胜利了。

在click事件的后部加上

if (isWinner()) 

    { 

     mx.controls.Alert.show("玩家"+turn+"记得比赛"); 

     initBoard(); 

    }

然后专心做isWinner()函数。我们可以通过暴力的方式获得当前ellipse的坐标值,但显然,代码就不容易让人理解,为了把视图与逻辑进行分离,我们需要引入另一个数组来定位用户下的棋的一个点,这个点包括四个值,x丝标,y坐标,棋子所属的玩家,还有一个圆。就命名为Qizhi吧。

public class Qizhi 

{ 

  public var x:int; 

  public var y:int; 

  public var turn:int; 

  public var ellipse:Ellipse; 

  public function Qizhi(x:int,y:int,turn:int,ellipse:Ellipse) 

  { 

   this.x=x; 

   this.y=y; 

   this.turn=turn; 

   this.ellipse=ellipse; 

  } 

}

click后的函数的第一次重构

protected function boardClick(event:MouseEvent):void{ 

    var posx:int=event.localX; 

    var posy:int=event.localY; 

    var clickQizhi:Qizhi; 

    for (var x:int=0;x<=totalsize;x++) 

    { 

     for (var y:int=0;y<=totalsize;y++) 

     { 

      var qizhi:Qizhi=boardArray[x][y] as Qizhi; 

      var ellipse:Ellipse=qizhi.ellipse as Ellipse; 

      if (posx>=ellipse.x && posx<=(ellipse.x+radios)&&posy>=ellipse.y &&posy<=(ellipse.y+radios)) 

       { 

        clickQizhi=qizhi; 

        break; 

       } 

     } 

    } 

    if (clickQizhi==null) return; 

    var clickEllipse:Ellipse=clickQizhi.ellipse as Ellipse; 

    if (clickQizhi.turn!=PLAYER_NONE) return; 

    if (turn==PLAYER_ONE_TURN) 

    { 

     clickQizhi.turn=PLAYER_ONE_TURN; 

     clickEllipse.fill=BLACK_COLOR; 

    } 

    else 

    { 

     clickQizhi.turn=PLAYER_TWO_TURN; 

     clickEllipse.fill=WHITE_COLOR; 

    } 

    if (isWinner(clickQizhi)) 

    { 

     mx.controls.Alert.show("玩家 "+turn+" 赢得比赛","恭喜你!"); 

     if (winArray.length>0) 

     { 

      for each(var item:Qizhi in winArray) 

      { 

       item.ellipse.fill=RED_COLOR; 

      } 

     } 

     board.removeEventListener(MouseEvent.CLICK,boardClick); 

     btnstart.enabled=true; 

     btnlose.enabled=false; 

     return; 

    } 

    if (turn==PLAYER_ONE_TURN) 

    { 

     turn=PLAYER_TWO_TURN; 

    } 

    else 

    { 

     turn=PLAYER_ONE_TURN; 

    } 

   }



判断胜负的寒素



private function isWinner(clickQizhi:Qizhi):Boolean { 

    //判断横向 

    if (xWinner(clickQizhi)) return true; 

    //判断横向 

    if (yWinner(clickQizhi)) return true; 

    //判断斜向 

    if (xy13Winner(clickQizhi)) return true; 

    if (xy24Winner(clickQizhi)) return true; 

    return false; 

   } 

   private function xWinner(clickQizhi:Qizhi):Boolean{ 

    winArray=new ArrayCollection(); 

    for (var xRight:int=clickQizhi.x+1;(xRight<=totalsize&&xRight<clickQizhi.x+5);xRight++) 

    { 

     var qizhiRight:Qizhi=boardArray[xRight][clickQizhi.y] as Qizhi; 

     if (qizhiRight.turn==clickQizhi.turn) 

     { 

      winArray.addItem(qizhiRight); 

     } 

     else 

     { 

      break; 

     } 

    } 

    for (var xLeft:int=clickQizhi.x-1;(xLeft>=0&&xLeft>clickQizhi.x-5);xLeft--) 

    { 

     var qizhiLeft:Qizhi=boardArray[xLeft][clickQizhi.y] as Qizhi; 

     if (qizhiLeft.turn==clickQizhi.turn) 

     { 

      winArray.addItem(qizhiLeft); 

     } 

     else 

     { 

      break; 

     } 

    } 

    if (winArray.length>=4) 

    { 

     winArray.addItem(clickQizhi); 

     return true; 

    } 

    return false; 

   } 

   private function yWinner(clickQizhi:Qizhi):Boolean{ 

    winArray=new ArrayCollection(); 

    var length:int=1; 

    for (var yRight:int=clickQizhi.y+1;(yRight<=totalsize&&yRight<clickQizhi.y+5);yRight++) 

    { 

     var qizhiBottom:Qizhi=boardArray[clickQizhi.x][yRight] as Qizhi; 

     if (qizhiBottom.turn==clickQizhi.turn) 

     { 

      winArray.addItem(qizhiBottom); 

     } 

     else 

     { 

      break; 

     } 

    } 

    for (var yLeft:int=clickQizhi.y-1;(yLeft>=0&&yLeft>clickQizhi.y-5);yLeft--) 

    { 

     var qizhiTop:Qizhi=boardArray[clickQizhi.x][yLeft] as Qizhi; 

     if (qizhiTop.turn==clickQizhi.turn) 

     { 

      winArray.addItem(qizhiTop); 

     } 

     else 

     { 

      break; 

     } 

    } 

    if (winArray.length>=4) 

    { 

     winArray.addItem(clickQizhi); 

     return true; 

    } 

    return false; 

   } 

   private function xy24Winner(clickQizhi:Qizhi):Boolean{ 

    winArray=new ArrayCollection(); 

    //第四象限 

    for (var yRight:int=clickQizhi.y+1;(yRight<=totalsize&&yRight<clickQizhi.y+5);yRight++) 

    { 

     if (clickQizhi.x+(yRight-clickQizhi.y)<=totalsize) 

     { 

      var qizhiRight:Qizhi=boardArray[clickQizhi.x+(yRight-clickQizhi.y)][yRight] as Qizhi; 

      if (qizhiRight.turn==clickQizhi.turn) 

      { 

       winArray.addItem(qizhiRight); 

      } 

      else 

      { 

       break; 

      } 

     } 

     else 

     { 

      break; 

     } 

    } 

    //第二象限 

    for (var yLeft:int=clickQizhi.y-1;(yLeft>=0&&yLeft>clickQizhi.y-5);yLeft--) 

    { 

     if (clickQizhi.x-yLeft>=0) 

     { 

      var qizhiLeft:Qizhi=boardArray[clickQizhi.x-(clickQizhi.x-yLeft)][yLeft] as Qizhi; 

      if (qizhiLeft.turn==clickQizhi.turn) 

      { 

       winArray.addItem(qizhiLeft); 

      } 

      else 

      { 

       break; 

      } 

     } 

     else 

     { 

      break; 

     } 

    } 

    if (winArray.length>=4) 

    { 

     winArray.addItem(clickQizhi); 

     return true; 

    } 

    return false; 

   } 

   private function xy13Winner(clickQizhi:Qizhi):Boolean{ 

    winArray=new ArrayCollection(); 

    //第三象限 

    for (var yRight:int=clickQizhi.y+1;(yRight<=totalsize&&yRight<clickQizhi.y+5);yRight++) 

    { 

     if (clickQizhi.x-(yRight-clickQizhi.y)>=0) 

     { 

      var qizhiBottom:Qizhi=boardArray[clickQizhi.x-(yRight-clickQizhi.y)][yRight] as Qizhi; 

      if (qizhiBottom.turn==clickQizhi.turn) 

      { 

       winArray.addItem(qizhiBottom); 

      } 

      else 

      { 

       break; 

      } 

     } 

     else 

     { 

      break; 

     } 

    } 

    //第一象限 

    for (var yLeft:int=clickQizhi.y-1;(yLeft>=0&&yLeft>clickQizhi.y-5);yLeft--) 

    { 

     if (clickQizhi.x+(clickQizhi.y-yLeft)<=totalsize) 

     { 

      var qizhiTop:Qizhi=boardArray[clickQizhi.x+(clickQizhi.y-yLeft)][yLeft] as Qizhi; 

      if (qizhiTop.turn==clickQizhi.turn) 

      { 

       winArray.addItem(qizhiTop); 

      } 

      else 

      { 

       break; 

      } 

     } 

     else 

     { 

      break; 

     } 

    } 

    if (winArray.length>=4) 

    { 

     winArray.addItem(clickQizhi); 

     return true; 

    } 

    return false; 

   }

你可能感兴趣的:(Flex)