現在我們來看看實際初始化地圖的randomCreateMap方法:
//在空白地圖上根據當前關卡數據隨機創建一個關卡地圖
//地圖總共瓦塊為30x10 = 300塊,拋去不能移動的Wall(48塊)還剩252塊空格.
//還要減去player和敵人占去的空格.玩家出現在每一關的(0,0)瓦格上.
//為了保證player不至於卡死,(0,0),(0,1)和(1,0)三個空格不能放磚
//敵人位置也是不可以放磚的,所以
//最後可以放磚數量為 252 - 3 = 249 -> 249 - _gd.curLevelEnemyCount
-(void)randomCreateMap{
NSInteger rndIdx;
NSInteger brickCount = _gd.curLevelBrickCount;
CGPoint tmpTilePos;
NSAssert((brickCount <= 249-(_gd.curLevelFSCount+_gd.curLevelFSGhostCount)), @"too many bricks!!!");
//刪除對象層(0,0)位置的占位磚
[self removeObjectAtTileCoord:ccp(0, 0)];
NSMutableArray *bricksAry = [NSMutableArray array];
//隨機擺放磚塊
for (int i = 0; i < brickCount; i++){
rndIdx = arc4random_uniform(_notWallTiles.count);
tmpTilePos = [_notWallTiles[rndIdx] CGPointValue];
[_objectLayer setTileGID:4 at:tmpTilePos];
[bricksAry addObject:[NSValue valueWithCGPoint:tmpTilePos]];
[_notWallTiles removeObjectAtIndex:rndIdx];
}
//隨機擺放游戲道具
GameProperty *gp = [GameProperty sharedInstance];
GamePropertyType gpType;
for (int i = 0; i < _gd.curLevelGPCount; i++) {
gpType = [gp randomGP];
NSAssert(bricksAry.count != 0, @"剩下的磚塊數目太少不足以放置剩余的道具");
rndIdx = arc4random_uniform(bricksAry.count);
tmpTilePos = [bricksAry[rndIdx] CGPointValue];
//隨機擺放一個道具
[gp putGPAt:tmpTilePos InLayer:_propertiesLayer type:gpType];
//該磚塊下已有道具,所以將其從bricksAry中排除出去
[bricksAry removeObjectAtIndex:rndIdx];
}
//將_propertiesLayer (0,0)位置的占位瓦塊刪掉
[gp removeGPAt:ccp(0, 0) InLayer:_propertiesLayer];
NSInteger exitTileID = [_underObjectsLayer tileGIDAt:ccp(0, 0)];
rndIdx = arc4random_uniform(bricksAry.count);
tmpTilePos = [bricksAry[rndIdx] CGPointValue];
//隨機擺放出口
[_underObjectsLayer setTileGID:exitTileID at:tmpTilePos];
[bricksAry removeObjectAtIndex:rndIdx];
_exitTilePos = tmpTilePos;
//將_underObjectsLayer (0,0)位置的占位瓦塊刪掉
[_underObjectsLayer removeTileAt:ccp(0, 0)];
}
額…為了不造成困惑,我特意做了比較詳細的注釋,我們還是依次來看看代碼吧.
首先一個斷言確保有足夠數量的磚塊可供使用,因為磚塊下面要放置道具和出口,如果磚塊太少就不能完全覆蓋住底下的道具了.
然後將地圖對象層的(0,0)位置的瓦塊刪除掉.為什麼要在地圖層中放置一塊用不到的瓦塊呢?因為Tiled工具有點小問題,我前面的博文裡也講過了.如果在某一層中開始什麼瓦塊都不放,而希望運行時動態增加瓦塊是不可行的.
我也曾試驗過,雖然Cocos2D中自帶的瓦塊地圖方法裡有像某一層關聯一個地圖集的方法,但實際操作卻不成功,總是失敗.
所以這裡我們先在Tiled裡放置一塊瓦塊,這樣等於關聯了一個地圖集,接下來在運行的時候就可以隨意增減其他瓦塊了.
回到代碼流中,接下來根據當前關卡中指定磚塊的數目隨機初始化磚塊.
同樣的,後面是隨機擺放道具的代碼,根據指定道具的數量來擺放.這裡可以再”真實”一些,根據道具的稀有程度的概率產生道具,否則一些通關道具隨便一大堆,會使游戲平衡性大打折扣.
最後是出口的擺放,並將生成好的出口坐標保存到_exitTilePos實例變量中,便於以後操作.
游戲初始化內容大致就是這些了,很多童鞋可能會想游戲的數據是從哪裡來的,這個實際是放在plist文件中的,在下一篇我們來討論.