Cocos2d-x《雷電大戰》(6) 智能敵機AI來襲--飛行路徑算法設計與實現(下)
來源:程序員人生 發布時間:2015-05-06 09:06:59 閱讀次數:4397次
林炳文Evankaka原創作品。轉載請注明出處http://blog.csdn.net/evankaka
筆者近來比較忙,所以游戲更新都很慢,有此網友也1直在催,但是確切是沒辦法。今天5.1有時間,再來把游戲更新下。
此文接上文Cocos2d-x《雷電大戰》(6) 智能敵機AI來襲--飛行路徑算法設計與實現(上) ,還是對游戲中的敵機路徑進行1個設計和實現。這里筆者又實現了兩種敵機線路。分別以下:
(1)敵機朝著英雄飛機的位置飛去
(2)左右兩群飛機穿過,其實就是1大群飛機從左到右和從右到左的飛行。
本文效果:

Cocos2d-x版本:3.4
工程環境:VS30213
1、敵機朝英雄飛機飛行
首先來說講敵機朝著英雄飛機的位置飛去,這里就比較簡單,只要獲得了英雄飛機的位置,再加了設置好敵機的初始位置,那末敵機的飛行路徑就出來了。下面筆者畫了張圖,具體可以看以下圖:

或以下

其中英雄飛機的位置我們可以知道,就能夠計算a和b的值,并且能得到角度mDegree。這里的mDegree主要是用來旋轉敵機的,如果不旋轉敵機的話,看起來效果就不怎樣好。
現在知道原理了,就開始寫代碼來實現吧:
void GameMain::enemyBuild3(float dt){
Size winSize = Director::getInstance()->getWinSize();
auto spritePlane = Sprite::create("air2.png");
//得到精靈寬和高
float height = spritePlane->getContentSize().height;
float width = spritePlane->getContentSize().width;
//設置敵機位于右上角
spritePlane->setPosition(Vec2(winSize.width + width / 2, winSize.height + height/2));
spritePlane->setScale(0.25);
this->addChild(spritePlane);
//計算英雄飛機和對角點連起的線與邊界的角度
float x = HeroPlane::getInstance()->getPlane()->getPosition().x;
float y = HeroPlane::getInstance()->getPlane()->getPosition().y;
float a = winSize.width - x;
float b = winSize.height - y;
// 弧度轉角度
float radians = atanf(a / b);
float mDegree = CC_RADIANS_TO_DEGREES(radians);
spritePlane->setRotation(180+mDegree);
//計算敵機的終究位置
float endX = winSize.width-(a / b)*winSize.height;
float endY = 0;
//計算飛行時間
float flyVelocity = 200;//運行速度,可以自己控制,每秒所走的像素
float flyLen = sqrt((winSize.width - endX)*(winSize.width - endX)+(winSize.height - endY)*(winSize.height - endY));
float realFlyDuration = flyLen / flyVelocity;//實際飛行的時間
//子彈運行的距離和時間,從飛機處開始運行到屏幕底部
auto actionMove = MoveTo::create(realFlyDuration, Point(endX, endY));
//子彈履行完動作落后行函數回調,調用移除子彈函數
auto actionDone = CallFuncN::create(
CC_CALLBACK_1(GameMain::enemyRemove, this));
//連續動作
Sequence* sequence = Sequence::create(actionMove, actionDone, NULL);
//飛機開始跑動
spritePlane->runAction(sequence);
}
注意,這里圖片還是沒有優化過的,敵機類也還沒有單獨寫1個類,這里只是簡單實現了下。然后開1個定時器定時履行這個操作
//每隔0.5S調用1次
schedule(schedule_selector(GameMain::enemyBuild3), 0.5f);
好了,現在來看看結果:
敵性能朝著英雄飛機撞去,并能實時改變自己的角度,固然。這個角度是1來就計算好了的。
2、左右群飛的敵機
左右群飛就是左側和右側都有1排飛機,然后同時向左或向右運動。飛機路徑不是問題,最主要的是設置好它們的起始位置,讓它們都能并排1起。原理圖以下:

這里要注意的地方就是設置敵機的位置時記得要加上敵機圖片的偏移量,Coco2dx中設置精靈位置時默許是以圖片中心點為原點,所以得加上這個偏移量。并且它們移動的距離都是1樣的,所以可以用MoveBy來實現,Y軸方向運動為0,X軸方向運動量為屏幕寬+敵機寬度。左右敵機X軸方向運動量不1樣。記得!并且,這里的 MoveBy的動作只能給1個敵機來使用,如果另外一個敵機是相同的動作,那末就能夠用clone()函數,而不用再重新創建1個MoveBy動作。
整體代碼以下:
void GameMain::enemyBuild4(float dt){
Size winSize = Director::getInstance()->getWinSize();
Point origin = Director::getInstance()->getVisibleOrigin();
//生成左側敵機
auto spritePlane1 = Sprite::create("air5.png");
auto spritePlane2 = Sprite::create("air5.png");
auto spritePlane3 = Sprite::create("air5.png");
//生成邊敵機
auto spritePlane4 = Sprite::create("air5.png");
auto spritePlane5 = Sprite::create("air5.png");
auto spritePlane6 = Sprite::create("air5.png");
//旋轉的角度
spritePlane1->setRotation(90);
spritePlane2->setRotation(90);
spritePlane3->setRotation(90);
spritePlane4->setRotation(⑼0);
spritePlane5->setRotation(⑼0);
spritePlane6->setRotation(⑼0);
//設置縮放
//spritePlane1->setScale(0.3);
//spritePlane2->setScale(0.3);
// spritePlane3->setScale(0.3);
//得到精靈寬和高
float height = spritePlane1->getContentSize().height;
float width = spritePlane1->getContentSize().width;
//放置敵機位置
spritePlane1->setPosition(Vec2(-width / 2, winSize.height - height / 2⑴0));
spritePlane2->setPosition(Vec2(-width / 2, spritePlane1->getPosition().y - 2 * height - 10));
spritePlane3->setPosition(Vec2(-width / 2, spritePlane2->getPosition().y - 2 * height - 10));
spritePlane4->setPosition(Vec2(winSize.width + width / 2, spritePlane1->getPosition().y - height - 10));
spritePlane5->setPosition(Vec2(winSize.width + width / 2, spritePlane4->getPosition().y - 2 * height - 10));
spritePlane6->setPosition(Vec2(winSize.width + width / 2, spritePlane5->getPosition().y - 2 * height - 10));
//層中加入精靈
this->addChild(spritePlane1);
this->addChild(spritePlane2);
this->addChild(spritePlane3);
this->addChild(spritePlane4);
this->addChild(spritePlane5);
//計算飛行時間
float flyVelocity = 200;//運行速度,可以自己控制,每秒所走的像素
float flyLen = winSize.width+width;
float realFlyDuration = flyLen / flyVelocity;//實際飛行的時間
//子彈運行的距離和時間,從飛機處開始運行到屏幕底部
auto actionMove1 = MoveBy::create(realFlyDuration, Point(flyLen,0));
auto actionMove2 = MoveBy::create(realFlyDuration, Point(-flyLen, 0));
//子彈履行完動作落后行函數回調,調用移除子彈函數
auto actionDone = CallFuncN::create(
CC_CALLBACK_1(GameMain::enemyRemove, this));
//連續動作
Sequence* sequence1 = Sequence::create(actionMove1, actionDone, NULL);
Sequence* sequence2 = Sequence::create(actionMove1->clone(), actionDone, NULL);
Sequence* sequence3 = Sequence::create(actionMove1->clone(), actionDone, NULL);
Sequence* sequence4 = Sequence::create(actionMove2, actionDone, NULL);
Sequence* sequence5 = Sequence::create(actionMove2->clone(), actionDone, NULL);
//飛機開始跑動
spritePlane1->runAction(sequence1);
spritePlane2->runAction(sequence2);
spritePlane3->runAction(sequence3);
spritePlane4->runAction(sequence4);
spritePlane5->runAction(sequence5);
}
然后還是相同的原理,開個定時器,來看看效果: //每隔0.5調用1次
schedule(schedule_selector(GameMain::enemyBuild4), 0.5f);
兩種飛機1起來:

3、總結
這里飛機的路徑設計了4種,由于還沒有進行優化,所之內存占用會有點多,后面筆者將會把敵機類全都放在1個Plist中,這模樣內存就會小點了。其實,在飛行游戲中。還有BOSS機,BOSS機的智能AI設計也是1個很好玩。固然,敵機子彈類也很重要,而這1部份的內容將會放在敵機類設計完成以后再來說。下1講中我們將來封裝自己的敵機類。
林炳文Evankaka原創作品。轉載請注明出處http://blog.csdn.net/evankaka
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈