cocos2d x遊戲開發系列教程 坦克大戰遊戲之敵方坦克AI的編寫
阿新 • • 發佈:2018-11-08
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
在上篇我們完成了子彈和地圖碰撞的檢測,在這篇我們將完成敵方坦克AI的編寫。
具體思路是螢幕中保持有四個敵方坦克,然後坦克隨機方向運動,並且子彈消失後1秒發射一次
1.我們新建一個敵方坦克的AI類來控制地方坦克AI行為:
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存放了所有的坦克,
mTank存放了玩家坦克,最後mTileMapInfo存放了地圖資訊。
bornPoint存放了敵方坦克出身的三個位置。
2.先實現void EnemyAI::initEnemyAIWithTank(Tank* tank)來初始化我們的EnemyAI類:
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類指標:
EnemyAI* EnemyAI::createEnemyAIWithTank(Tank* tank){ EnemyAI* enemyTank = new EnemyAI(); enemyTank->initEnemyAIWithTank(tank); return enemyTank;}
4.實現void EnemyAI::addTank(float delta):
其中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); } }}
可以看到deltaTimes累加時間,超過2秒就開始新增坦克,初始三個坦克從固定位置新增,
然後第四個坦克隨機位置新增。
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);}
到這裡基本的坦克AI構建完成,我們執行下看看效果:
完整程式碼下載地址:
http://download.csdn.net/detail/yincheng01/6764095