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. package com.boyiju.game.siguo.util  
  2. {  
  3.     /**  
  4.      * 四國軍模可能用到的常量值   
  5.      * @author Administrator  
  6.      *   
  7.      */   
  8.     public class Enum  
  9.     {  
  10.         //棋局狀態  
  11.         public static const GAME_LAYOUT:int=0;//佈局  
  12.         public static const GAME_WAIT:int=1;//完成佈局,等待棋它玩家  
  13.         public static const GAME_PLAYING:int=2;//遊戲中  
  14.         public static const GAME_END:int=3;//遊戲結束  
  15.           
  16.         //玩家顏色  
  17.         public static const COLOR_PLAYER_BOTTOM:int=0X34699d;//下  
  18.         public static const COLOR_PLAYER_RIGHT:int=0Xd86c00;//右  
  19.         public static const COLOR_PLAYER_TOP:int=0X8f449f;//上  
  20.         public static const COLOR_PLAYER_LEFT:int=0X709c00;//左  
  21.           
  22.         //棋子  
  23.         public static const QIZHI_SINING:int=40;//司令  
  24.         public static const QIZHI_JUNZHANG:int=39;  
  25.         public static const QIZHI_SHIZHANG:int=38;  
  26.         public static const QIZHI_LVZHANG:int=37;  
  27.         public static const QIZHI_TUANZHANG:int=36;  
  28.         public static const QIZHI_YINGZHANG:int=35;  
  29.         public static const QIZHI_LIANGZHANG:int=34;  
  30.         public static const QIZHI_PAIZHANG:int=33;  
  31.         public static const QIZHI_GONGBING:int=32;  
  32.         public static const QIZHI_DILEI:int=31;  
  33.         public static const QIZHI_JUQI:int=30; //最小爲軍棋,誰都可以吃  
  34.         public static const QIZHI_ZHADAN:int=100;  
  35.           
  36.           
  37.         //可視  
  38.         public static const QIZHI_STATE_NONE:int=-1;//不可見  
  39.         public static const QIZHI_STATE_SELF:int=0; //自己可見  
  40.         public static const QIZHI_STATE_TEAM:int=1;//隊友可見  
  41.         public static const QIZHI_STATE_ALL:int=2;//全部可見  
  42.           
  43.         //位置類型        
  44.         public static const POSITION_NORAML:int=0;  
  45.         public static const POSITION_YING:int=1; //行營  
  46.         public static const POSITION_DABENYING:int=2; //大本營  
  47.           
  48.         //佈局移動  
  49.         public static const LAYOUT_MOVE_ALL:int=0;  
  50.         public static const LAYOUT_MOVE_LAST_TWO:int=1;//地雷只能在後兩排  
  51.         public static const LAYOUT_MOVE_NOT_FRONT:int=2;//炸彈不能在前排鐵道上  
  52.         public static const LAYOUT_MOVE_JUNQI:int=3;//軍棋只能在大本營內  
  53.           
  54.           
  55.           
  56.     }  

三,核心類設計

3.1 Position類

棋盤由4個layout與一個centerarea組成,每個layout有30個位置,包括25個棋子位置與5個行營位置,centerarea包括9個行棋位置,棋盤共129個位置。位置的標識如上圖所示,當用戶進入棋局時,他的佈局的索引就是 (30*玩家位置+具體位置)。這個邏輯就相當清楚了。

下面看類的具體內容,我將解釋直接寫到了類內部。

 

  1. package com.boyiju.game.siguo.vo  
  2. {  
  3.  
  4.     import com.boyiju.game.siguo.util.Enum;  
  5.       
  6.     import mx.collections.ArrayCollection;  
  7.     /**  
  8.      * 位置類,每個棋盤共129個位置,每個位置有不同的可移動目標,類型,編號等   
  9.      * 每個位置將對應一個棋子類  
  10.      */   
  11.     [Bindable]  
  12.     public class PositionVO  
  13.     {  
  14.         /**  
  15.          *常量:可以直接移動的位置的集合,共30個   
  16.          */       
  17.         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)];  
  18.           
  19.         /**  
  20.          *常量:鐵道線上的位置集合,橫7條,豎七條,外加拐彎的4條,共18條   
  21.          */       
  22.         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)];  
  23.  
  24.           
  25.         private var _index:int=-1;  
  26.         /**  
  27.          *棋子位置的類型 如營或大本營   
  28.          */       
  29.         public var type:int;  
  30.           
  31.         /**  
  32.          *棋子繪製的開始位置   
  33.          */       
  34.         public var startX:int;  
  35.         public var startY:int;  
  36.           
  37.           
  38.         /**  
  39.          *可移動位置的索引   
  40.          */       
  41.         public var moveAC:ArrayCollection=new ArrayCollection();  
  42.         public var moveRailAC:ArrayCollection=new ArrayCollection();  
  43.           
  44.         public function get index():int 
  45.         {  
  46.             return _index;  
  47.         }  
  48.         /**  
  49.          *位置的索引,作爲一個聯機遊戲,用戶在桌子上的位置就是索引的,在進入遊戲時,索引已經固定(0-129)。   
  50.          * 通過索引可以得到可以移動的全部目標子位,棋子的類型,佈局的位置索引(0-30)  
  51.          * @param value  
  52.          *   
  53.          */ 
  54.         public function set index(value:int):void 
  55.         {  
  56.             _index = value;  
  57.             var layoutindex:int = value%30;  
  58.             if (_index<120)  
  59.             {  
  60.                 startX=Math.floor(layoutindex/6)*37.5+5;  
  61.                 startY=Math.floor(layoutindex%6)*30+10;   
  62.             }  
  63.             else 
  64.             {  
  65.                 startX=Math.floor(layoutindex/3)*75+7.5;  
  66.                 startY=Math.floor(layoutindex%3)*75+7.5;      
  67.             }  
  68.             type=getType(layoutindex);  
  69.             initMoveAC(layoutindex);  
  70.             initMoveRoad(index);  
  71.         }  
  72.         /**  
  73.          *可以直接移動的子位,不需要判斷中間是否有間隔   
  74.          * @param layoutindex  
  75.          *   
  76.          */       
  77.         private function initMoveAC(layoutindex:int):void 
  78.         {  
  79.             moveAC.removeAll();  
  80.             var tempAC:ArrayCollection=new ArrayCollection(MOVE_ONE_STEP[layoutindex]);  
  81.             moveAC.addAll(tempAC);  
  82.             var basecount:int=_index-layoutindex;  
  83.             if (moveAC.length>0)  
  84.             {  
  85.                 for (var i2:int=0;i2<moveAC.length;i2++)  
  86.                 {  
  87.                     moveAC[i2]=moveAC[i2]+basecount;  
  88.                 }  
  89.             }  
  90.               
  91.         }  
  92.         /**  
  93.          *鐵道線上的位置索引,如果該子包括在線路中,則將鐵路放到索引中。   
  94.          * @param index  
  95.          *   
  96.          */       
  97.         private function initMoveRoad(index:int):void{  
  98.             moveRailAC.removeAll();  
  99.             for (var i:int=0;i<MOVE_RAIL.length;i++)  
  100.             {  
  101.                 if (MOVE_RAIL[i].indexOf(index)>=0)  
  102.                 {  
  103.                     var tempAC:ArrayCollection=new ArrayCollection(MOVE_RAIL[i]);  
  104.                     if (tempAC.contains(_index))  
  105.                     {  
  106.                         moveRailAC.addItem(tempAC);  
  107.                     }  
  108.                 }  
  109.             }  
  110.         }  
  111.         /**  
  112.          *獲得當前位置的類型,如棋,大本營,行營等。  
  113.          * @param layoutindex  
  114.          * @return   
  115.          *   
  116.          */ 
  117.         private function getType(layoutindex:int):int{  
  118.             var type:int;  
  119.             if (layoutindex==7||layoutindex==9||layoutindex==14||layoutindex==19||layoutindex==21)  
  120.             {  
  121.                 type=Enum.POSITION_YING;  
  122.             }  
  123.             else if (layoutindex==11||layoutindex==23)  
  124.             {  
  125.                 type=Enum.POSITION_DABENYING;  
  126.             }  
  127.             else 
  128.             {  
  129.                 type=Enum.POSITION_NORAML;  
  130.             }  
  131.             return type;  
  132.         }  
  133.  
  134.     }  

3.2 QizhiVO類

棋子是棋局的基本組成部分,在佈局階段,我們會爲用戶在除行營外的位置上放置一些默認的棋子作爲初始值,一共25個,也就是說,一個棋局只可能有100個棋子,並且會慢慢減小。現在,我們就來描述具體的棋子類。棋子的核實屬性,也就是與服務器進行交互的只有3個,位置,值,與玩家,擴展顯示的有一些,如名稱,背景,位置的起始值等。棋子的方法包括 與其它棋子比較大小,移動到目標位置,與目標位置的棋子碰撞等。現在,我們圍繞這個設計棋子類。

 

  1. package com.boyiju.game.siguo.vo  
  2. {  
  3.     import asds.map.HashMap;  
  4.       
  5.     import com.boyiju.game.siguo.components.Qizhi;  
  6.     import com.boyiju.game.siguo.util.Enum;  
  7.       
  8.     import mx.collections.ArrayCollection;  
  9.       
  10.     /**  
  11.      *棋子類,每個棋子核心數值僅包括棋子的值,棋子的位置,棋子是否顯示與棋子的玩家,  
  12.      * 其它的輔助值主要用於交互與顯示,將通過核心值獲得並可進行綁定顯示   
  13.      */   
  14.     [Bindable]  
  15.     public class QizhiVO  
  16.     {  
  17.         private var _value:int=-1;  
  18.         private var _deskpos:int=-1;              
  19.         private var _display:int=-1;  
  20.       
  21.         public var positionVO:PositionVO;  
  22.         public var name:String;  
  23.         public var bgColor:int;  
  24.         public var layoutMoveType:int;  
  25.           
  26.           
  27.         public function get display():int 
  28.         {  
  29.             return _display;  
  30.         }  
  31.           
  32.         public function set display(value:int):void 
  33.         {  
  34.             _display = value;  
  35.         }  
  36.           
  37.         public function get deskpos():int 
  38.         {  
  39.             return _deskpos;  
  40.         }  
  41.           
  42.           
  43.         public function set deskpos(value:int):void 
  44.         {  
  45.             _deskpos = value;  
  46.             this.bgColor=getColor(value);  
  47.         }  
  48.           
  49.         public function get value():int 
  50.         {  
  51.             return _value;  
  52.         }  
  53.           
  54.         public function set value(value:int):void 
  55.         {  
  56.             _value = value;  
  57.             this.name=getQizhiName(value);  
  58.             this.layoutMoveType=getLayoutMoveType(value);  
  59.         }  
  60.  
  61.         private function isTeam(deskpos:int):Boolean  
  62.         {  
  63.             var teamdeskpos:int=(this.deskpos+2)%4;  
  64.             return deskpos==teamdeskpos;  
  65.         }  
  66.         /**  
  67.          *獲得棋子的顯示名稱,與棋子的顯示類進行綁定   
  68.          * @param value  
  69.          * @return   
  70.          *   
  71.          */       
  72.         private function getQizhiName(value:int):String{  
  73.             if (value==40) return "司令";  
  74.             if (value==39) return "軍長";  
  75.             if (value==38) return "師長";  
  76.             if (value==37) return "旅長";  
  77.             if (value==36) return "團長";  
  78.             if (value==35) return "營長";  
  79.             if (value==34) return "連長";  
  80.             if (value==33) return "排長";  
  81.             if (value==32) return "工兵";  
  82.             if (value==31) return "地雷";  
  83.             if (value==30) return "軍棋";  
  84.             if (value==100) return "炸彈";  
  85.             return "";  
  86.         }  
  87.         /**  
  88.          *棋子的顏色,通過棋子的玩家獲得   
  89.          * @param player  
  90.          * 玩家  
  91.          * @return   
  92.          * 顏色值  
  93.          *   
  94.          */       
  95.         private function getColor(player:int):int{  
  96.             if (player==0) return Enum.COLOR_PLAYER_BOTTOM;  
  97.             else if(player==1) return Enum.COLOR_PLAYER_RIGHT;  
  98.             else if (player==2) return Enum.COLOR_PLAYER_TOP;  
  99.             else if (player==3) return Enum.COLOR_PLAYER_LEFT;  
  100.             return 0x000000;  
  101.         }  
  102.         /**  
  103.          * 棋子本身在佈局階段的移動限制   
  104.          * @param value 棋子的值  
  105.          * @return   
  106.          *   
  107.          */       
  108.         private function getLayoutMoveType(value:int):int{  
  109.               
  110.             if (value==Enum.QIZHI_GONGBING) return Enum.LAYOUT_MOVE_LAST_TWO;  
  111.             if (value==Enum.QIZHI_ZHADAN) return Enum.LAYOUT_MOVE_NOT_FRONT;  
  112.             if (value==Enum.QIZHI_DILEI) return Enum.LAYOUT_MOVE_JUNQI;  
  113.             return Enum.LAYOUT_MOVE_ALL;  
  114.         }  
  115.           
  116.         /**  
  117.          * 與目標棋子比較大小   
  118.          * @param target  
  119.          * @return   
  120.          *   
  121.          */       
  122.         public function Compare(target:QizhiVO):int 
  123.         {  
  124.             if (this.value==Enum.QIZHI_ZHADAN||target.value==Enum.QIZHI_ZHADAN||this.value==target.value)   
  125.             {  
  126.                 trace("很壯烈,您的 "+this.name+" 與敵人的 "+target.name+" 同歸於盡");  
  127.                 return 0;  
  128.             }  
  129.             if (target.value==Enum.QIZHI_DILEI&&this.value!=Enum.QIZHI_GONGBING||this.value<target.value)  
  130.             {  
  131.                 trace("很悲劇,您的 "+this.name+" 被敵人的 "+target.name+" 吃掉了");  
  132.                   
  133.                 return -1;  
  134.             }  
  135.             if (this.value>target.value)   
  136.             {  
  137.                 trace("很爽,您的 "+this.name+" 吃掉了敵人的 "+target.name);  
  138.                 return 1;  
  139.             }  
  140.             return 1;  
  141.         }  
  142.           
  143.         /**  
  144.          *佈局階段與目標棋子交換   
  145.          * @param target  
  146.          *   
  147.          */       
  148.         public function exchange(target:QizhiVO):void 
  149.         {  
  150.             if (target==nullreturn;  
  151.             if (target.value==-1) return;  
  152.             if (target.deskpos!=this.deskpos) return;  
  153.               
  154.             //軍棋只能放大本營  
  155.             if (this.layoutMoveType==Enum.LAYOUT_MOVE_JUNQI)  
  156.             {  
  157.                 if (target.positionVO.index==11)  
  158.                 {  
  159.                       
  160.                 }else if (target.positionVO.index==23)  
  161.                 {  
  162.                       
  163.                 }  
  164.                 else 
  165.                     return;  
  166.             }  
  167.             if (target.layoutMoveType==Enum.LAYOUT_MOVE_JUNQI)  
  168.             {  
  169.                 if (this.positionVO.index==11)  
  170.                 {  
  171.                       
  172.                 }else if (this.positionVO.index==23)  
  173.                 {  
  174.                       
  175.                 }  
  176.                 else 
  177.                     return;  
  178.             }  
  179.             //地雷只能放在後兩排  
  180.             if (this.layoutMoveType==Enum.LAYOUT_MOVE_LAST_TWO)  
  181.             {  
  182.                 if (target.positionVO.index%6<4) return;  
  183.             }  
  184.             if (target.layoutMoveType==Enum.LAYOUT_MOVE_LAST_TWO)  
  185.             {  
  186.                 if (this.positionVO.index%6<4) return;  
  187.             }  
  188.             //炸彈不能放在第一排三個位置  
  189.             if (this.layoutMoveType==Enum.LAYOUT_MOVE_NOT_FRONT)  
  190.             {  
  191.                 if (target.positionVO.index==0||target.positionVO.index==12||target.positionVO.index==24) return;  
  192.             }  
  193.             if (target.layoutMoveType==Enum.LAYOUT_MOVE_NOT_FRONT)  
  194.             {  
  195.                 if (this.positionVO.index==0||this.positionVO.index==12||this.positionVO.index==24) return;  
  196.             }  
  197.             var temp:int=target.value;  
  198.             target.value=this.value;  
  199.             this.value=temp;  
  200.         }  
  201.           
  202.         /**  
  203.          * 可否移動到目標位置,主要包括棋子的可移動性,棋子的移動目標值,目標位置的內容等。  
  204.          * @param targetPos  
  205.          * @param qizhiMap  
  206.          * @return   
  207.          *   
  208.          */       
  209.         public function canMoveTo(targetPos:PositionVO,qizhiMap:HashMap):Boolean{  
  210.               
  211.             //位置無法移動  
  212.             if (this.positionVO.moveAC.length==0||this.value==Enum.QIZHI_DILEI||this.value==Enum.QIZHI_JUQI)   
  213.             {  
  214.                 trace("該位置無法移動:"+this.positionVO.index);  
  215.                 return false;  
  216.             }  
  217.             //目標位置不在可移動區內  
  218.             if (!this.positionVO.moveAC.contains(targetPos.index))   
  219.             {  
  220.                 if (this.positionVO.moveRailAC.length==0){  
  221.                     trace(targetPos.index+" 不在該位置的可移動路徑內:"+this.positionVO.index);  
  222.                     return false;  
  223.                       
  224.                 }  
  225.                 for each (var railAC:ArrayCollection in this.positionVO.moveRailAC)  
  226.                 {  
  227.                           
  228.                         var targetindex:int=railAC.getItemIndex(targetPos.index);  
  229.                         //目標棋子不在鐵路中  
  230.                         if (targetindex==-1) continue;  
  231.                         //目標棋子在鐵路中.再找原始棋子的位置  
  232.                         var sourceindex:int=railAC.getItemIndex(this.positionVO.index);  
  233.                         //從原始棋子到目標棋子的通路中沒有其它子  
  234.                           
  235.                         if (sourceindex>targetindex)  
  236.                         {  
  237.                             for(var i:int=targetindex+1;i<sourceindex;i++)  
  238.                             {  
  239.                                 //到達目標區的通路有其它的棋子  
  240.                                 var qizhiVO:QizhiVO=qizhiMap.get(railAC.getItemAt(i)) as QizhiVO;  
  241.                                 if (qizhiVO.value!=-1)  
  242.                                 {  
  243.                                     trace("路徑不通:"+qizhiVO.positionVO.index+" 有子 "+qizhiVO.name);                    return false;  
  244.                                 }  
  245.                                 trace("經過:"+qizhiVO.positionVO.index);  
  246.                                   
  247.                                   
  248.                             }  
  249.                               
  250.                         }  
  251.                         else 
  252.                         {  
  253.                             for(var j:int=sourceindex+1;j<targetindex;j++)  
  254.                             {  
  255.                                 //到達目標區的通路有其它的棋子  
  256.                                 var qizhiVO2:QizhiVO=qizhiMap.get(railAC.getItemAt(j)) as QizhiVO;  
  257.                                 if (qizhiVO2.value!=-1)  
  258.                                 {  
  259.                                     trace("路徑不通:"+qizhiVO2.positionVO.index+" 有子 "+qizhiVO2.name);  
  260.                                     return false;  
  261.                                 }  
  262.                                 trace("經過:"+qizhiVO2.positionVO.index);  
  263.                                   
  264.                             }  
  265.                               
  266.                         }  
  267.                         trace(this.name+" 從 "+this.positionVO.index+ " 移動至:"+targetPos.index);  
  268.                         return true;  
  269.                           
  270.                 }  
  271.                       
  272.             }  
  273.               
  274.             trace(this.name+" 從 "+this.positionVO.index+ " 移動至:"+targetPos.index);  
  275.             return true;  
  276.               
  277.         }  
  278.           
  279.         /**  
  280.          * 與目標棋子碰撞   
  281.          * @param target  
  282.          * @return   
  283.          *   
  284.          */       
  285.         public function eat(target:QizhiVO,qizhiMap:HashMap):int{  
  286.             //不能吃自己的子  
  287.             if (target==null)  
  288.             {  
  289.                 return -6;  
  290.             }  
  291.             if (target.value==-1)  
  292.             {  
  293.                 trace( "目標位置無棋子");  
  294.                 return -5;  
  295.             }  
  296.             if (target.deskpos==this.deskpos)  
  297.             {  
  298.                 trace( "不能吃自己的子");  
  299.                   
  300.                 return -4;  
  301.             }  
  302.             //不能吃隊友的子  
  303.             if (isTeam(target.deskpos))  
  304.             {  
  305.                 trace( "位於"+target.positionVO.index+" 的棋子是您的隊友的 "+target.name);  
  306.                   
  307.                 return -3;  
  308.             }  
  309.             if (!canMoveTo(target.positionVO,qizhiMap))  
  310.             {  
  311.                 return -2;  
  312.             }  
  313.             //比較大小  
  314.             return this.Compare(target);  
  315.               
  316.         }  
  317.           
  318.     }  

3.3 GameEngine 遊戲控制類

遊戲控制類用於對遊戲進行調試,設計爲一個全局類,包括了遊戲進行必需的一些內容,如桌主,等待時間,遊戲狀態,遊戲棋子集合,當前玩家,當前佈局,當前選中棋子等內容。充分利用flex的綁定機制,將顯示部分與控制部分結合。

 

  1. package com.boyiju.game.siguo.model  
  2. {  
  3.  
  4.     import asds.map.HashMap;  
  5.       
  6.     import com.adobe.cairngorm.model.IModelLocator;  
  7.     import com.boyiju.game.siguo.components.LayoutSelect;  
  8.     import com.boyiju.game.siguo.components.Qizhi;  
  9.     import com.boyiju.game.siguo.util.Enum;  
  10.     import com.boyiju.game.siguo.vo.LayoutVO;  
  11.     import com.boyiju.game.siguo.vo.PositionVO;  
  12.     import com.boyiju.game.siguo.vo.QizhiVO;  
  13.     import com.boyiju.game.siguo.vo.UserVO;  
  14.       
  15.     import mx.collections.ArrayCollection;  
  16.     import mx.core.FlexGlobals;  
  17.       
  18.     /**  
  19.      *四國軍棋遊戲的全局控制類,使用了cairngoarm類設計  
  20.      */   
  21.       
  22.     [Bindable]  
  23.     public class GameEngine implements IModelLocator  
  24.     {  
  25.         private static var _model:GameEngine;  
  26.               
  27.           
  28.           
  29.         public var gameOwner:int;//遊戲桌主  
  30.                   
  31.         public var gameWaitTime:int=30;//等待時間 秒       
  32.           
  33.         public var gameStatus:int;//遊戲狀態  
  34.           
  35.           
  36.         public var currentPlayer:UserVO;//當前玩家  
  37.         public var currentTurn:int;//當前回合玩家  
  38.         public var currentSelectedQZ:Qizhi; //選中的棋子  
  39.           
  40.           
  41.         public var sourceQZ:Qizhi;   //源棋子,用於棋子之間產鮮紅用  
  42.           
  43.           
  44.         public var layoutAC:ArrayCollection;//佈局文件組合  
  45.         public var currentLayout:LayoutVO;//當前佈局文件  
  46.           
  47.         public var playerAC:HashMap; //玩家組合  
  48.           
  49.           
  50.         public var qizhiMap:HashMap; //所有棋子有組合,與服務器交互的主要類  
  51.           
  52.           
  53.           
  54.         /**  
  55.          *初始化四國軍棋棋局   
  56.          * @param enforcer  
  57.          *   
  58.          */       
  59.         public function GameEngine(enforcer:SingletonEnforcer) {      
  60.               
  61.             gameStatus=Enum.GAME_LAYOUT;  
  62.               
  63.             layoutAC=new ArrayCollection();  
  64.             layoutAC.addItem(new LayoutVO("守型",LayoutSelect.LAYOUT_COOL,"偏防守"));  
  65.             layoutAC.addItem(new LayoutVO("攻型",LayoutSelect.LAYOUT_HOT,"偏進攻"));  
  66.             layoutAC.addItem(new LayoutVO("基本",LayoutSelect.LAYOUT_NORMAL,"攻守平衡"));  
  67.             currentLayout=layoutAC.getItemAt(0) as LayoutVO;  
  68.               
  69.             qizhiMap=new HashMap();  
  70.             playerAC =new HashMap();  
  71.               
  72.             createAndInitUser();  
  73.             currentPlayer=playerAC.get(0) as UserVO;  
  74.         }  
  75.         /**  
  76.          *將佈局文件添加到全局佈局列表中   
  77.          * @param layout  
  78.          *   
  79.          */       
  80.         public function addLayout(layout:LayoutVO,deskpos:int):void{  
  81.               
  82.             for (var i:int=0;i<layout.lyAC.length;i++)  
  83.             {  
  84.                 if (layout.lyAC[i]!=-1)  
  85.                 {  
  86.                     var positionVO:PositionVO=new PositionVO();  
  87.                     positionVO.index=30*deskpos+i;  
  88.                     var qizhiVO:QizhiVO=new QizhiVO();  
  89.                     qizhiVO.value=(layout.lyAC[i]);  
  90.                     qizhiVO.deskpos=deskpos;  
  91.                     qizhiVO.positionVO=positionVO;  
  92.                     qizhiMap.put(qizhiVO.positionVO.index,qizhiVO);  
  93.                 }  
  94.             }  
  95.         }  
  96.           
  97.         public static function get intance():GameEngine  
  98.         {  
  99.             if (_model ==null) {  
  100.                 _model=new GameEngine(new SingletonEnforcer());  
  101.             }  
  102.             return _model;  
  103.         }  
  104.         /**  
  105.          *測試用,加入一些用戶   
  106.          *   
  107.          */       
  108.         private function createAndInitUser():void {  
  109.             var user:UserVO=new UserVO();  
  110.             user.name="張柏枝";  
  111.             user.picture="assets/images/zbz.jpg";  
  112.             user.score=0;  
  113.             user.win=0;  
  114.             user.lost=0;  
  115.             user.points=2100;  
  116.             user.deskpos=0;  
  117.             playerAC.put(user.deskpos,user);  
  118.             user=new UserVO();  
  119.             user.name="王菲";  
  120.             user.picture="assets/images/wf.jpg";  
  121.             user.score=0;  
  122.             user.win=0;  
  123.             user.lost=0;  
  124.             user.points=500;  
  125.             user.deskpos=1;  
  126.             playerAC.put(user.deskpos,user);  
  127.             user=new UserVO();  
  128.             user.name="林志玲";  
  129.             user.picture="assets/images/lzl.jpg";  
  130.             user.score=0;  
  131.             user.win=0;  
  132.             user.lost=0;  
  133.             user.points=2250;  
  134.             user.deskpos=2;  
  135.             playerAC.put(user.deskpos,user);  
  136.             user=new UserVO();  
  137.             user.name="阿嬌";  
  138.             user.picture="assets/images/aj.jpg";  
  139.             user.score=0;  
  140.             user.win=0;  
  141.             user.lost=0;  
  142.             user.points=350;  
  143.             user.deskpos=3;  
  144.             playerAC.put(user.deskpos,user);  
  145.         }  
  146.         /**  
  147.          *獲得下一位玩家,   
  148.          * @param num  
  149.          * @return   
  150.          *   
  151.          */       
  152.         public function getNextUser(num:int):UserVO{  
  153.             var nextid:int=(currentPlayer.deskpos+num)%4;  
  154.             return playerAC.get(nextid) as UserVO;  
  155.         }   
  156.           
  157.     }  
  158.       
  159. }  
  160. class SingletonEnforcer  
  161. {  
  162.       

3.4 LayoutVO 類 佈局文件類

 

  1. package com.boyiju.game.siguo.vo  
  2. {  
  3.     import mx.collections.ArrayCollection;  
  4.  
  5.     [Bindable]  
  6.     public class LayoutVO  
  7.     {  
  8.         public var name:String;  
  9.         public var lyAC:ArrayCollection;  
  10.         public var catalog:String;  
  11.           
  12.         public function LayoutVO(name:String,lyAC:Array,catalog:String)  
  13.         {  
  14.             this.name=name;  
  15.             this.lyAC=new ArrayCollection(lyAC);  
  16.             this.catalog=catalog;  
  17.         }  
  18.     }  

一個典型的博命型的劃攻佈局可以描述如下。夠簡單了吧,看看我們下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文件供大家測試一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章