flex 联机游戏开发 - 四国军棋游戏:(三) 核心类
通过前面的练习 flex 联机游戏开发 - 四国军棋游戏:(二)棋盘棋子 我们已经成功地用不到200行的代码绘制出了一个漂亮的棋盘,现在,我们开始进入游戏的核心类设计阶段。四国军棋的游戏逻辑还是比较复杂的,棋子在布局,游戏阶段有不同的可移动位置,棋子的位置也有自己的可移动位置,工并可以到处飞,还有铁道等,当然,设计者通过不同的渠道都可以达到相同的设计目标,主要看你设计的目标及对性能的要求。在开始设计之前,我先来说说flex的坏话
一)利用flex设计的利与弊
1.1)坏处
1)flex暂时还很难在没有fms支持的情况下实现双工通讯,这与silverlight成熟的双工通讯机制比还是有点不足,当然,也并不全是坏事,在下棋的时候加上聊天,双工通讯的开销也是挺吓人的。 在没有双工通讯的基础上,我们只能通过定时期不断的获得服务器端的数据进行更新
2) flex暂时还没有比较完善的集合类,它仅提供了一个arraycollection及xmlcollection类供开发者使用,我们不得不使用一些第三方或自己开发的集合类来完善功能,比如hashmap,这总是应该有的一个集合类吧。当然,作为一个plug in ,adobe也是挺痛苦的,类库太大方便了开发者,就苦了消费者。当年的java swing 直接将 java applet 送入了死亡通道,前车之鉴嘛,我估计最终仍旧是消费者战胜开发者。
3)图形绘制中没有drawsting的功能,而且就算将来有,对中文字体的支持估计也够呛,所以,你只能自己写一个类似于label的uid类或者直接用label类来显示中文文本。这无疑增大系统的开销。
1.2)好处
1)良好的ui设计,通过flex绘制出来的图形本身已经比较漂亮,当你加入一些简单的组件的效果,滤镜时就更漂亮了,而所有这些,开销并不算太大。在讲究用户体验的今天,这些还是相当诱人的。
这是设计的一个全局位置图。仅在棋盘中绑定一些label,label加上一些效果就行了,几行代码。
2)flex简单易学,我从java,c#转头来做这个游戏似乎只看了一本书,书名叫“flex 4-一学就会”,所以,如果你是一位java,c#程序员,不要有太多的顾虑。另外,flex类似于silverlight的绑定机制,事件冒泡模式使设计开发变得更有想象力(当然,想象力太好也可能把事情越弄越复杂)s
3)所有好处好象最终只围绕这个好处,那就是 flash player拥有全世界无人能敌的98%的装机量,而且,直接延伸到android,iphone。还有什么比这更让一个游戏开发者羡慕。。。
好了,聊完了上面的这些内容,让我们来干些实事
二)全局设计考虑
1) 你可以从任何一个方向来开始这个程序,对老练的程序员来算,只要你有头脑,似乎并不需要太多的经验,但是你首先得确定方向,本程序里,我开发的首先是一个联机,然后才是游戏,对于联机游戏,有必引入adobe的一种设计模式 cairngoarm,似乎可以将事情变得简单一点。
2)作为联机游戏,你得时时考虑服务器的开销,在本程序里,服务器需要什么,他只需要一个数组标识三个内容(位置,玩家,棋子),算起来一共只要6个字节,加上129个位置,最多也不超过1k的传输内容,真是令人惊讶。没开发的时候,我以为要传输的内容很多呐。所以,我决定从自顶向下的开发这个游戏。就是先设计与服务器交互的内容 GameEngine,然后再回头来设计每个类。
3)需要设计什么类,首先是位置需要有个类 PositionVO,然后棋子应该是最主要的类QizhiVO,位置应该是棋子的成员,为什么棋子不是位置的成员?(原因:(有没有没有位置的棋子?当然没有;有没有没有棋子的位置?当然有),还要设计一个玩家的类,玩家在一张桌子上有一个位置,我们就按顺时针方向设计为(0,1,2,3)吧。这也是棋子的成员。似乎就没什么要考虑了的吧。
好了,现在我们来做四国军棋游戏的逻辑部分,一些轻松的工作,设计自己的第一个类,常量助辅类 Enum,类里的元素相信你一看就明白;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | package com.boyiju.game.siguo.util { /** * 四国军模可能用到的常量值 * @author Administrator * */ public class Enum { //棋局状态 public static const GAME_LAYOUT: int =0; //布局 public static const GAME_WAIT: int =1; //完成布局,等待棋它玩家 public static const GAME_PLAYING: int =2; //游戏中 public static const GAME_END: int =3; //游戏结束 //玩家颜色 public static const COLOR_PLAYER_BOTTOM: int =0X34699d; //下 public static const COLOR_PLAYER_RIGHT: int =0Xd86c00; //右 public static const COLOR_PLAYER_TOP: int =0X8f449f; //上 public static const COLOR_PLAYER_LEFT: int =0X709c00; //左 //棋子 public static const QIZHI_SINING: int =40; //司令 public static const QIZHI_JUNZHANG: int =39; public static const QIZHI_SHIZHANG: int =38; public static const QIZHI_LVZHANG: int =37; public static const QIZHI_TUANZHANG: int =36; public static const QIZHI_YINGZHANG: int =35; public static const QIZHI_LIANGZHANG: int =34; public static const QIZHI_PAIZHANG: int =33; public static const QIZHI_GONGBING: int =32; public static const QIZHI_DILEI: int =31; public static const QIZHI_JUQI: int =30; //最小为军棋,谁都可以吃 public static const QIZHI_ZHADAN: int =100; //可视 public static const QIZHI_STATE_NONE: int =-1; //不可见 public static const QIZHI_STATE_SELF: int =0; //自己可见 public static const QIZHI_STATE_TEAM: int =1; //队友可见 public static const QIZHI_STATE_ALL: int =2; //全部可见 //位置类型 public static const POSITION_NORAML: int =0; public static const POSITION_YING: int =1; //行营 public static const POSITION_DABENYING: int =2; //大本营 //布局移动 public static const LAYOUT_MOVE_ALL: int =0; public static const LAYOUT_MOVE_LAST_TWO: int =1; //地雷只能在后两排 public static const LAYOUT_MOVE_NOT_FRONT: int =2; //炸弹不能在前排铁道上 public static const LAYOUT_MOVE_JUNQI: int =3; //军棋只能在大本营内 } } |
三,核心类设计
3.1 Position类
棋盘由4个layout与一个centerarea组成,每个layout有30个位置,包括25个棋子位置与5个行营位置,centerarea包括9个行棋位置,棋盘共129个位置。位置的标识如上图所示,当用户进入棋局时,他的布局的索引就是 (30*玩家位置+具体位置)。这个逻辑就相当清楚了。
下面看类的具体内容,我将解释直接写到了类内部。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | package com.boyiju.game.siguo.vo { import com.boyiju.game.siguo.util.Enum; import mx.collections.ArrayCollection; /** * 位置类,每个棋盘共129个位置,每个位置有不同的可移动目标,类型,编号等 * 每个位置将对应一个棋子类 */ [Bindable] public class PositionVO { /** *常量:可以直接移动的位置的集合,共30个 */ public static const MOVE_ONE_STEP:Array=[ new Array(1,6,7), new Array(0,2,7), new Array(1,3,7,8,9), new Array(2,4,9), new Array(3,5,9,10), new Array(4,11), new Array(0,12,7), new Array(0,1,2,6,8,12,13,14), new Array(2,7,9,14), new Array(2,3,4,8,10,14,15,16), new Array(4,9,11,16), null , new Array(6,7,13,18,19), new Array(7,12,14,19), new Array(7,8,9,13,15,19,20,21), new Array(9,14,16,21), new Array(9,10,15,17,21,22), new Array(11,16,23), new Array(12,19,24), new Array(12,13,14,18,20,24,25,26), new Array(14,19,21,26), new Array(14,15,16,20,22,26,27,28), new Array(16,21,23,28), null , new Array(18,19,25), new Array(19,24,26), new Array(19,20,21,25,27), new Array(21,26,28), new Array(21,22,27,29), new Array(23,28)]; /** *常量:铁道线上的位置集合,横7条,竖七条,外加拐弯的4条,共18条 */ public static const MOVE_RAIL:Array=[ new Array(118,112,106,100,94), new Array(114,108,102,96,90), new Array(4,3,2,1,0,122,121,120,84,85,86,87,88), new Array(12,125,124,123,72), new Array(28,27,26,25,24,128,127,126,60,61,62,63,64), new Array(30,36,42,48,54), new Array(34,40,46,52,58), new Array(28,22,16,10,4), new Array(24,18,12,6,0), new Array(34,33,32,31,30,128,125,122,114,115,116,117,118), new Array(42,127,124,121,102), new Array(2,7,9,14), new Array(58,57,56,55,54,126,123,120,90,91,92,93,94), new Array(4,9,11,16), new Array(60,66,72,78,84), new Array(64,70,76,82,88)]; private var _index: int =-1; /** *棋子位置的类型 如营或大本营 */ public var type: int ; /** *棋子绘制的开始位置 */ public var startX: int ; public var startY: int ; /** *可移动位置的索引 */ public var moveAC:ArrayCollection= new ArrayCollection(); public var moveRailAC:ArrayCollection= new ArrayCollection(); public function get index(): int { return _index; } /** *位置的索引,作为一个联机游戏,用户在桌子上的位置就是索引的,在进入游戏时,索引已经固定(0-129)。 * 通过索引可以得到可以移动的全部目标子位,棋子的类型,布局的位置索引(0-30) * @param value * */ public function set index(value: int ): void { _index = value; var layoutindex: int = value%30; if (_index<120) { startX=Math.floor(layoutindex/6)*37.5+5; startY=Math.floor(layoutindex%6)*30+10; } else { startX=Math.floor(layoutindex/3)*75+7.5; startY=Math.floor(layoutindex%3)*75+7.5; } type=getType(layoutindex); initMoveAC(layoutindex); initMoveRoad(index); } /** *可以直接移动的子位,不需要判断中间是否有间隔 * @param layoutindex * */ private function initMoveAC(layoutindex: int ): void { moveAC.removeAll(); var tempAC:ArrayCollection= new ArrayCollection(MOVE_ONE_STEP[layoutindex]); moveAC.addAll(tempAC); var basecount: int =_index-layoutindex; if (moveAC.length>0) { for ( var i2: int =0;i2<moveAC.length;i2++) { moveAC[i2]=moveAC[i2]+basecount; } } } /** *铁道线上的位置索引,如果该子包括在线路中,则将铁路放到索引中。 * @param index * */ private function initMoveRoad(index: int ): void { moveRailAC.removeAll(); for ( var i: int =0;i<MOVE_RAIL.length;i++) { if (MOVE_RAIL[i].indexOf(index)>=0) { var tempAC:ArrayCollection= new ArrayCollection(MOVE_RAIL[i]); if (tempAC.contains(_index)) { moveRailAC.addItem(tempAC); } } } } /** *获得当前位置的类型,如棋,大本营,行营等。 * @param layoutindex * @return * */ private function getType(layoutindex: int ): int { var type: int ; if (layoutindex==7||layoutindex==9||layoutindex==14||layoutindex==19||layoutindex==21) { type=Enum.POSITION_YING; } else if (layoutindex==11||layoutindex==23) { type=Enum.POSITION_DABENYING; } else { type=Enum.POSITION_NORAML; } return type; } } } |
3.2 QizhiVO类
棋子是棋局的基本组成部分,在布局阶段,我们会为用户在除行营外的位置上放置一些默认的棋子作为初始值,一共25个,也就是说,一个棋局只可能有100个棋子,并且会慢慢减小。现在,我们就来描述具体的棋子类。棋子的核实属性,也就是与服务器进行交互的只有3个,位置,值,与玩家,扩展显示的有一些,如名称,背景,位置的起始值等。棋子的方法包括 与其它棋子比较大小,移动到目标位置,与目标位置的棋子碰撞等。现在,我们围绕这个设计棋子类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | package com.boyiju.game.siguo.vo { import asds.map.HashMap; import com.boyiju.game.siguo.components.Qizhi; import com.boyiju.game.siguo.util.Enum; import mx.collections.ArrayCollection; /** *棋子类,每个棋子核心数值仅包括棋子的值,棋子的位置,棋子是否显示与棋子的玩家, * 其它的辅助值主要用于交互与显示,将通过核心值获得并可进行绑定显示 */ [Bindable] public class QizhiVO { private var _value: int =-1; private var _deskpos: int =-1; private var _display: int =-1; public var positionVO:PositionVO; public var name:String; public var bgColor: int ; public var layoutMoveType: int ; public function get display(): int { return _display; } public function set display(value: int ): void { _display = value; } public function get deskpos(): int { return _deskpos; } public function set deskpos(value: int ): void { _deskpos = value; this .bgColor=getColor(value); } public function get value(): int { return _value; } public function set value(value: int ): void { _value = value; this .name=getQizhiName(value); this .layoutMoveType=getLayoutMoveType(value); } private function isTeam(deskpos: int ):Boolean { var teamdeskpos: int =( this .deskpos+2)%4; return deskpos==teamdeskpos; } /** *获得棋子的显示名称,与棋子的显示类进行绑定 * @param value * @return * */ private function getQizhiName(value: int ):String{ if (value==40) return "司令" ; if (value==39) return "军长" ; if (value==38) return "师长" ; if (value==37) return "旅长" ; if (value==36) return "团长" ; if (value==35) return "营长" ; if (value==34) return "连长" ; if (value==33) return "排长" ; if (value==32) return "工兵" ; if (value==31) return "地雷" ; if (value==30) return "军棋" ; if (value==100) return "炸弹" ; return "" ; } /** *棋子的颜色,通过棋子的玩家获得 * @param player * 玩家 * @return * 颜色值 * */ private function getColor(player: int ): int { if (player==0) return Enum.COLOR_PLAYER_BOTTOM; else if (player==1) return Enum.COLOR_PLAYER_RIGHT; else if (player==2) return Enum.COLOR_PLAYER_TOP; else if (player==3) return Enum.COLOR_PLAYER_LEFT; return 0x000000; } /** * 棋子本身在布局阶段的移动限制 * @param value 棋子的值 * @return * */ private function getLayoutMoveType(value: int ): int { if (value==Enum.QIZHI_GONGBING) return Enum.LAYOUT_MOVE_LAST_TWO; if (value==Enum.QIZHI_ZHADAN) return Enum.LAYOUT_MOVE_NOT_FRONT; if (value==Enum.QIZHI_DILEI) return Enum.LAYOUT_MOVE_JUNQI; return Enum.LAYOUT_MOVE_ALL; } /** * 与目标棋子比较大小 * @param target * @return * */ public function Compare(target:QizhiVO): int { if ( this .value==Enum.QIZHI_ZHADAN||target.value==Enum.QIZHI_ZHADAN|| this .value==target.value) { trace( "很壮烈,您的 " + this .name+ " 与敌人的 " +target.name+ " 同归于尽" ); return 0; } if (target.value==Enum.QIZHI_DILEI&& this .value!=Enum.QIZHI_GONGBING|| this .value<target.value) { trace( "很悲剧,您的 " + this .name+ " 被敌人的 " +target.name+ " 吃掉了" ); return -1; } if ( this .value>target.value) { trace( "很爽,您的 " + this .name+ " 吃掉了敌人的 " +target.name); return 1; } return 1; } /** *布局阶段与目标棋子交换 * @param target * */ public function exchange(target:QizhiVO): void { if (target== null ) return ; if (target.value==-1) return ; if (target.deskpos!= this .deskpos) return ; //军棋只能放大本营 if ( this .layoutMoveType==Enum.LAYOUT_MOVE_JUNQI) { if (target.positionVO.index==11) { } else if (target.positionVO.index==23) { } else return ; } if (target.layoutMoveType==Enum.LAYOUT_MOVE_JUNQI) { if ( this .positionVO.index==11) { } else if ( this .positionVO.index==23) { } else return ; } //地雷只能放在后两排 if ( this .layoutMoveType==Enum.LAYOUT_MOVE_LAST_TWO) { if (target.positionVO.index%6<4) return ; } if (target.layoutMoveType==Enum.LAYOUT_MOVE_LAST_TWO) { if ( this .positionVO.index%6<4) return ; } //炸弹不能放在第一排三个位置 if ( this .layoutMoveType==Enum.LAYOUT_MOVE_NOT_FRONT) { if (target.positionVO.index==0||target.positionVO.index==12||target.positionVO.index==24) return ; } if (target.layoutMoveType==Enum.LAYOUT_MOVE_NOT_FRONT) { if ( this .positionVO.index==0|| this .positionVO.index==12|| this .positionVO.index==24) return ; } var temp: int =target.value; target.value= this .value; this .value=temp; } /** * 可否移动到目标位置,主要包括棋子的可移动性,棋子的移动目标值,目标位置的内容等。 * @param targetPos * @param qizhiMap * @return * */ public function canMoveTo(targetPos:PositionVO,qizhiMap:HashMap):Boolean{ //位置无法移动 if ( this .positionVO.moveAC.length==0|| this .value==Enum.QIZHI_DILEI|| this .value==Enum.QIZHI_JUQI) { trace( "该位置无法移动:" + this .positionVO.index); return false ; } //目标位置不在可移动区内 if (! this .positionVO.moveAC.contains(targetPos.index)) { if ( this .positionVO.moveRailAC.length==0){ trace(targetPos.index+ " 不在该位置的可移动路径内:" + this .positionVO.index); return false ; } for each ( var railAC:ArrayCollection in this .positionVO.moveRailAC) { var targetindex: int =railAC.getItemIndex(targetPos.index); //目标棋子不在铁路中 if (targetindex==-1) continue ; //目标棋子在铁路中.再找原始棋子的位置 var sourceindex: int =railAC.getItemIndex( this .positionVO.index); //从原始棋子到目标棋子的通路中没有其它子 if (sourceindex>targetindex) { for ( var i: int =targetindex+1;i<sourceindex;i++) { //到达目标区的通路有其它的棋子 var qizhiVO:QizhiVO=qizhiMap. get (railAC.getItemAt(i)) as QizhiVO; if (qizhiVO.value!=-1) { trace( "路径不通:" +qizhiVO.positionVO.index+ " 有子 " +qizhiVO.name); return false ; } trace( "经过:" +qizhiVO.positionVO.index); } } else { for ( var j: int =sourceindex+1;j<targetindex;j++) { //到达目标区的通路有其它的棋子 var qizhiVO2:QizhiVO=qizhiMap. get (railAC.getItemAt(j)) as QizhiVO; if (qizhiVO2.value!=-1) { trace( "路径不通:" +qizhiVO2.positionVO.index+ " 有子 " +qizhiVO2.name); return false ; } trace( "经过:" +qizhiVO2.positionVO.index); } } trace( this .name+ " 从 " + this .positionVO.index+ " 移动至:" +targetPos.index); return true ; } } trace( this .name+ " 从 " + this .positionVO.index+ " 移动至:" +targetPos.index); return true ; } /** * 与目标棋子碰撞 * @param target * @return * */ public function eat(target:QizhiVO,qizhiMap:HashMap): int { //不能吃自己的子 if (target== null ) { return -6; } if (target.value==-1) { trace( "目标位置无棋子" ); return -5; } if (target.deskpos== this .deskpos) { trace( "不能吃自己的子" ); return -4; } //不能吃队友的子 if (isTeam(target.deskpos)) { trace( "位于" +target.positionVO.index+ " 的棋子是您的队友的 " +target.name); return -3; } if (!canMoveTo(target.positionVO,qizhiMap)) { return -2; } //比较大小 return this .Compare(target); } } } |
3.3 GameEngine 游戏控制类
游戏控制类用于对游戏进行调试,设计为一个全局类,包括了游戏进行必需的一些内容,如桌主,等待时间,游戏状态,游戏棋子集合,当前玩家,当前布局,当前选中棋子等内容。充分利用flex的绑定机制,将显示部分与控制部分结合。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163package com.boyiju.game.siguo.model
{
import asds.map.HashMap;
import com.adobe.cairngorm.model.IModelLocator;
import com.boyiju.game.siguo.components.LayoutSelect;
import com.boyiju.game.siguo.components.Qizhi;
import com.boyiju.game.siguo.util.Enum;
import com.boyiju.game.siguo.vo.LayoutVO;
import com.boyiju.game.siguo.vo.PositionVO;
import com.boyiju.game.siguo.vo.QizhiVO;
import com.boyiju.game.siguo.vo.UserVO;
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
/**
*四国军棋游戏的全局控制类,使用了cairngoarm类设计
*/
[Bindable]
public
class
GameEngine implements IModelLocator
{
private
static
var
_model:GameEngine;
public
var
gameOwner:
int
;
//游戏桌主
public
var
gameWaitTime:
int
=30;
//等待时间 秒
public
var
gameStatus:
int
;
//游戏状态
public
var
currentPlayer:UserVO;
//当前玩家
public
var
currentTurn:
int
;
//当前回合玩家
public
var
currentSelectedQZ:Qizhi;
//选中的棋子
public
var
sourceQZ:Qizhi;
//源棋子,用于棋子之间产鲜红用
public
var
layoutAC:ArrayCollection;
//布局文件组合
public
var
currentLayout:LayoutVO;
//当前布局文件
public
var
playerAC:HashMap;
//玩家组合
public
var
qizhiMap:HashMap;
//所有棋子有组合,与服务器交互的主要类
/**
*初始化四国军棋棋局
* @param enforcer
*
*/
public
function GameEngine(enforcer:SingletonEnforcer) {
gameStatus=Enum.GAME_LAYOUT;
layoutAC=
new
ArrayCollection();
layoutAC.addItem(
new
LayoutVO(
"守型"
,LayoutSelect.LAYOUT_COOL,
"偏防守"
));
layoutAC.addItem(
new
LayoutVO(
"攻型"
,LayoutSelect.LAYOUT_HOT,
"偏进攻"
));
layoutAC.addItem(
new
LayoutVO(
"基本"
,LayoutSelect.LAYOUT_NORMAL,
"攻守平衡"
));
currentLayout=layoutAC.getItemAt(0)
as
LayoutVO;
qizhiMap=
new
HashMap();
playerAC =
new
HashMap();
createAndInitUser();
currentPlayer=playerAC.
get
(0)
as
UserVO;
}
/**
*将布局文件添加到全局布局列表中
* @param layout
*
*/
public
function addLayout(layout:LayoutVO,deskpos:
int
):
void
{
for
(
var
i:
int
=0;i<layout.lyAC.length;i++)
{
if
(layout.lyAC[i]!=-1)
{
var
positionVO:PositionVO=
new
PositionVO();
positionVO.index=30*deskpos+i;
var
qizhiVO:QizhiVO=
new
QizhiVO();
qizhiVO.value=(layout.lyAC[i]);
qizhiVO.deskpos=deskpos;
qizhiVO.positionVO=positionVO;
qizhiMap.put(qizhiVO.positionVO.index,qizhiVO);
}
}
}
public
static
function
get
intance():GameEngine
{
if
(_model ==
null
) {
_model=
new
GameEngine(
new
SingletonEnforcer());
}
return
_model;
}
/**
*测试用,加入一些用户
*
*/
private
function createAndInitUser():
void
{
var
user:UserVO=
new
UserVO();
user.name=
"张柏枝"
;
user.picture=
"assets/images/zbz.jpg"
;
user.score=0;
user.win=0;
user.lost=0;
user.points=2100;
user.deskpos=0;
playerAC.put(user.deskpos,user);
user=
new
UserVO();
user.name=
"王菲"
;
user.picture=
"assets/images/wf.jpg"
;
user.score=0;
user.win=0;
user.lost=0;
user.points=500;
user.deskpos=1;
playerAC.put(user.deskpos,user);
user=
new
UserVO();
user.name=
"林志玲"
;
user.picture=
"assets/images/lzl.jpg"
;
user.score=0;
user.win=0;
user.lost=0;
user.points=2250;
user.deskpos=2;
playerAC.put(user.deskpos,user);
user=
new
UserVO();
user.name=
"阿娇"
;
user.picture=
"assets/images/aj.jpg"
;
user.score=0;
user.win=0;
user.lost=0;
user.points=350;
user.deskpos=3;
playerAC.put(user.deskpos,user);
}
/**
*获得下一位玩家,
* @param num
* @return
*
*/
public
function getNextUser(num:
int
):UserVO{
var
nextid:
int
=(currentPlayer.deskpos+num)%4;
return
playerAC.
get
(nextid)
as
UserVO;
}
}
}
class
SingletonEnforcer
{
}
3.4 LayoutVO 类 布局文件类
布局文件类是个更简单的类,他包括一个名称,目录,及30个棋子位置的子的集合,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [Bindable] public class LayoutVO { public var name:String; public var lyAC:ArrayCollection; public var catalog:String; public function LayoutVO(name:String,lyAC:Array,catalog:String) { this .name=name; this .lyAC= new ArrayCollection(lyAC); this .catalog=catalog; } } |
一个典型的博命型的划攻布局可以描述如下。够简单了吧,看看我们下QQ游戏的布局文件,几个K,我汗。。
public static const LAYOUT_HOT:Array=[40,39,38,38,37,37,36,-1,100,-1,36,30,35,35,-1,34,34,34,33,-1,33,-1,33,32,32,32,31,31,31,100];
四)下一节可能做的工作
核心部分基本就包括在这四个类内,应该来讲够简单吧,最终完成的效果如图
下一节我来设计显示的部分及游戏进行中的逻辑部分,显示的部分就是把控件拉来拉去,加上绑定机制。你会觉得更简单的:),同时,下节打算做出第一个测试版本swf文件供大家测试一下。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)