在這篇文章,將會學習到如何製作一個塔防遊戲。在這當中,學習如何在設定的時間內出現一波波的敵人,使這些敵人沿著指定的路點前進,如何在地圖上指定的位置建立炮塔,如何使炮塔射擊敵人,如何可視化調試路點和炮塔的攻擊範圍。
對於初學者來說,這個例子是非常適合的,對於熟悉cocos2d有很好的協助,希望初學cocos的博友們仔細搞搞, 本人剛開始做這個 諮詢了原文作者好幾次,祝大家成功!
1.建立Cocos2d-win32工程,工程名為"TowerDefense",去除"Box2D"選項,勾選"Simple Audio Engine in Cocos Denshion"選項;
2.下載本遊戲所需的資源,將資源放置"Resources"目錄下;
資源中包括原始碼:http://download.csdn.net/detail/yangshuo528/7426007
3.為情境添加背景圖片。開啟HelloWorldScene.cpp檔案,修改init函數,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
|
bool HelloWorld::init() { bool bRet = false; do { CC_BREAK_IF(! CCLayer::init()); this->setTouchEnabled(true); CCSize wins = CCDirector::sharedDirector()->getWinSize(); CCSprite *background = CCSprite::create("Bg.png"); this->addChild(background); background->setPosition(ccp(wins.width / 2, wins.height / 2));
bRet = true; } while (0); return bRet; } |
通過放置的背景圖片,可以直觀的看出哪些地方允許玩家放置炮塔。編譯運行,如所示:
4.接著,需要沿路設定一些點,在這些點上能夠讓玩家觸摸和建立炮塔。為了方便管理,使用.plist檔案來儲存炮塔的放置點,這樣就可以很容易的改變它們。TowersPosition.plist已經在資源檔夾中,其中已經有了一些炮塔的位置。查看這個檔案,可以看到一個字典數組,字典只包含兩個鍵"x"和"y"。每個字典條目代表一個炮塔位置的x和y座標。現在需要讀取這個檔案,並且放置塔基到地圖上。開啟HelloWorldScene.h檔案,添加以下變數:
1
|
|
cocos2d::CCArray* towerBases; |
開啟HelloWorldScene.cpp檔案,添加如下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
|
void HelloWorld::loadTowerPositions() { CCArray* towerPositions = CCArray::createWithContentsOfFile("TowersPosition.plist"); towerBases = CCArray::createWithCapacity(10); towerBases->retain();
CCObject *pObject = NULL; CCARRAY_FOREACH(towerPositions, pObject) { CCDictionary* towerPos = (CCDictionary*)pObject; CCSprite* towerBase = CCSprite::create("open_spot.png"); this->addChild(towerBase); towerBase->setPosition(ccp(((CCString*)towerPos->objectForKey("x"))->intValue(), ((CCString*)towerPos->objectForKey("y"))->intValue())); towerBases->addObject(towerBase); } } |
在init函數裡面,添加背景圖片代碼之後,添加如下代碼:
1
|
|
this->loadTowerPositions(); |
在解構函式裡面,添加如下代碼:
編譯運行,就可以看到道路兩側的方塊,這些是做為玩家炮塔的基座。如所示:
5.開始建立炮塔。開啟HelloWorldScene.h檔案,添加如下代碼:
1
|
|
CC_SYNTHESIZE_RETAIN(cocos2d::CCArray*, _towers, Towers); |
添加Tower類,派生自CCNode類,Tower.h檔案代碼如下:
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
|
|
#ifndef __TOWER_H__ #define __TOWER_H__
#include "cocos2d.h" #include "HelloWorldScene.h"
#define kTOWER_COST 300
class Tower : public cocos2d::CCNode { public: Tower(void); ~Tower(void);
static Tower* nodeWithTheGame(HelloWorld* game, cocos2d::CCPoint location); bool initWithTheGame(HelloWorld* game, cocos2d::CCPoint location);
void update(float dt); void draw(void);
CC_SYNTHESIZE(HelloWorld*, _theGame, TheGame); CC_SYNTHESIZE(cocos2d::CCSprite*, _mySprite, MySprite);
private: int attackRange; int damage; float fireRate; };
#endif // __TOWER_H__ |
開啟Tower.cpp檔案,代碼如下:
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
|
|
#include "Tower.h" using namespace cocos2d;
Tower::Tower(void) { }
Tower::~Tower(void) { }
Tower* Tower::nodeWithTheGame(HelloWorld* game, CCPoint location) { Tower *pRet = new Tower(); if (pRet && pRet->initWithTheGame(game, location)) { return pRet; } else { delete pRet; pRet = NULL; return NULL; } }
bool Tower::initWithTheGame(HelloWorld* game, CCPoint location) { bool bRet = false; do { attackRange = 70; damage = 10; fireRate = 1; _mySprite = CCSprite::create("tower.png"); this->addChild(_mySprite); _mySprite->setPosition(location); _theGame = game; _theGame->addChild(this);
this->scheduleUpdate();
bRet = true; } while (0);
return bRet; }
void Tower::update(float dt) {
}
void Tower::draw(void) { #ifdef COCOS2D_DEBUG ccDrawColor4F(255, 255, 255, 255); ccDrawCircle(_mySprite->getPosition(), attackRange, 360, 30, false); #endif CCNode::draw(); } |
這個Tower類包含幾個屬性:一個精靈對象,這是炮塔的可視化表現;一個父層的引用,方便訪問父層;還有三個變數:
- attackRange: 炮塔可以攻擊敵人的距離。
- damage: 炮塔對敵人造成的傷害值。
- fireRate: 炮塔再次攻擊敵人的時間間隔。
有了這三個變數,就可以建立各種不同攻擊屬性的炮塔,比如需要很長時間來重新載入的遠程重擊,或者範圍有限的快速攻擊。最後,代碼中的draw方法,用於在炮塔周圍繪製一個圓,以顯示出它的攻擊範圍,這將方便調試。
6.讓玩家添加炮塔。開啟HelloWorldScene.cpp檔案,加入以下標頭檔聲明:
在解構函式中添加如下代碼:
在init函數,添加如下代碼:
1 2
|
|
_towers = CCArray::create(); _towers->retain(); |
添加如下兩個方法,代碼如下(在 HelloWorldScene.h別忘了添加函式宣告 ):
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
|
|
bool HelloWorld::canBuyTower() { return true; }
void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) { CCSetIterator iter = pTouches->begin(); for (; iter != pTouches->end(); iter++) { CCTouch* pTouch = (CCTouch*)(*iter); CCPoint location = pTouch->getLocation();
CCObject *pObject = NULL; CCARRAY_FOREACH(towerBases, pObject) { CCSprite *tb = (CCSprite*)pObject; if (this->canBuyTower() && tb->boundingBox().containsPoint(location) && !tb->getUserData()) { //We will spend our gold later.
Tower* tower = Tower::nodeWithTheGame(this, tb->getPosition()); _towers->addObject(tower); tb->setUserData(tower); } } } } |
方法ccTouchesBegan檢測當使用者觸控螢幕幕上任何點時,遍曆towerBases數組,檢查觸摸點是否包含在任何一個塔基上。不過在建立炮塔前,還有兩件事需要檢查:
①玩家是否買得起炮塔?canBuyTower方法用來檢查玩家是否有足夠的金幣來購買炮塔。在這裡先假設玩家有很多金幣,方法返回true。
②玩家是否違法了建築規則?如果tb的UserData已經設定了,那麼這個塔基已經有了炮塔,不能再添加一個新的了。
如果一切檢查都通過,那麼就建立一個新的炮塔,放置在塔基上,並將它添加到炮塔數組中。編譯運行,觸摸塔基,就可以看到炮塔放置上去了,並且它的周圍還有白色的圓圈顯示攻擊範圍,如所示:
參考資料:1.How To Make a Tower Defense Game http://www.raywenderlich.com/15730/how-to-make-a-tower-defense-game
如何製作一個塔防遊戲:http://blog.csdn.net/akof1314/article/details/8674186