在上篇咱們完成了子彈和地圖碰撞的檢測,在這篇咱們將完成敵方坦克AI的編寫。數組
具體思路是屏幕中保持有四個敵方坦克,而後坦克隨機方向運動,而且子彈消失後1秒發射一次函數
1.咱們新建一個敵方坦克的AI類來控制地方坦克AI行爲:this
static const char* enemyTankType[] = { "normalU.png", "speedU.png", "armor1U.png" }; class EnemyAI { public: EnemyAI(); ~EnemyAI(); static EnemyAI* createEnemyAIWithTank(Tank* tank); void initEnemyAIWithTank(Tank* tank); void update(float delta); private: void addTank(float delta); void tankAction(float delta); private: CCArray* mEnemyTanks; Tank* mTank; TileMapInfo* mTileMapInfo; //出現地點 CCPoint bornPoint[3]; };上面目前只添加三種類型的敵方坦克,
在成員變量中,mEnemyTanks存放了全部的坦克,spa
mTank存放了玩家坦克,最後mTileMapInfo存放了地圖信息。.net
bornPoint存放了敵方坦克出身的三個位置。指針
2.先實現void EnemyAI::initEnemyAIWithTank(Tank* tank)來初始化咱們的EnemyAI類:code
void EnemyAI::initEnemyAIWithTank(Tank* tank) { mTank = tank; mTileMapInfo = tank->getTileMapInfo(); mEnemyTanks = CCArray::createWithCapacity(4); mEnemyTanks->retain(); //初始化出現地點 CCSize mapSize = mTileMapInfo->getTileMap()->getContentSize(); CCSize tileSize = mTileMapInfo->getTileMap()->layerNamed("layer_0")->getMapTileSize(); bornPoint[0] = ccp(tileSize.width, mapSize.height - tileSize.height); bornPoint[1] = ccp(mapSize.width / 2, mapSize.height - tileSize.height); bornPoint[2] = ccp(mapSize.width - tileSize.width, mapSize.height - tileSize.height); }在上面咱們初始化了敵方坦克出身的三個地點,而後建立了一個容量爲4的數組mEnemyTanks來存放敵方坦克對象。
3.再實現靜態方法返回EnmeyAI類指針:orm
EnemyAI* EnemyAI::createEnemyAIWithTank(Tank* tank) { EnemyAI* enemyTank = new EnemyAI(); enemyTank->initEnemyAIWithTank(tank); return enemyTank; }
其中delta是每一幀調用之間的事件間隔對象
void EnemyAI::addTank(float delta) { static float deltaTimes = 0.0f; deltaTimes += delta; if (deltaTimes >= 2.0f) { deltaTimes = 0.0f; int count = mEnemyTanks->count(); if (count < 3) //先從固定位置添加三個坦克 { Tank* enemyTank = Tank::createTankWithTankType(enemyTankType[count], mTileMapInfo); enemyTank->setPosition(bornPoint[count]); enemyTank->setRotation(180.0f); mEnemyTanks->addObject(enemyTank); } else if (count == 3) //第四個坦克隨機添加 { int tankTypeIndex = (int)(CCRANDOM_0_1() * 4) % 3; Tank* enemyTank = Tank::createTankWithTankType(enemyTankType[tankTypeIndex], mTileMapInfo); enemyTank->setPosition(bornPoint[tankTypeIndex]); enemyTank->setRotation(180.0f); mEnemyTanks->addObject(enemyTank); } } }
而後第四個坦克隨機位置添加。blog
5.實現void EnemyAI::tankAction(float delta),來控制坦克行爲:
void EnemyAI::tankAction(float delta) { CCObject* pObj; CCARRAY_FOREACH(mEnemyTanks, pObj) { Tank* tank = (Tank*)pObj; //坦克自動移動,碰到牆壁自動換方向 int Rotation = tank->getRotation(); if (!tank->command((enumOrder)(Rotation / 90 + 1))) { int n = (int)(CCRANDOM_0_1() * 5) % 5; if (n != 0) tank->command((enumOrder)n); } //每隔一秒開一次火 tank->setBulletDelta(tank->getBulletDelta() + delta); if (tank->getBulletDelta() > 0.5) { //開火後,若是子彈在飛行中,歸零計時 if (tank->command(cmdFire)) { tank->setBulletDelta(0.0); } } } }從mEnemyTanks中遍歷坦克對象,而後向固定方向移動,遇到牆壁則隨機換方向移動。
在下面,子彈消失後,隔0.5秒再次發射子彈。
6.最後實現咱們的void EnemyAI::update(float delta),它會在每一幀切換的時候被調用。
void EnemyAI::update(float delta) { //坦克不足4個,補充坦克 addTank(delta); //坦克行爲控制 tankAction(delta); }
7.下面咱們把敵人的AI類整合到CityScene場景中:
bool CityScene::init() { CCLayer::init(); //初始化地圖信息 char szRound[260]; sprintf(szRound, "Round%d.tmx", mRound); TileMapInfo* tileMapInfo = TileMapInfo::createMapInfoWithFile(szRound); CCTMXTiledMap* tmxTileMap = tileMapInfo->getTileMap(); this->addChild(tmxTileMap); //在已有的地圖上,建立玩家坦克 mPlayerTank[0] = Tank::createTankWithTankType("player2U.png", tileMapInfo); //放到地圖中初始化位置 CCSize tileSize = tmxTileMap->getTileSize(); CCSize mapSize = tmxTileMap->getContentSize(); mPlayerTank[0]->setPosition(ccp(mapSize.width / 2 - tileSize.width * 3, tileSize.height)); //添加虛擬手柄的顯示 mLayerPanel = Panel::create(); addChild(mLayerPanel, 3); //建立敵人坦克的AI mEnemyAI = EnemyAI::createEnemyAIWithTank(mPlayerTank[0]); return true; }
//建立敵人坦克的AI
mEnemyAI = EnemyAI::createEnemyAIWithTank(mPlayerTank[0]);
8.咱們在場景的update中調用AI的update函數
void CityScene::update(float delta) { CCLayer::update(delta); //將控制面板中的mLayerPanel獲取的命令傳給坦克 if (mPlayerTank[0] != NULL) mPlayerTank[0]->command(mLayerPanel->getOrder()); //調用敵人AI的update mEnemyAI->update(delta); }
完整代碼下載地址: