Cocos2d-x《雷电大战》(6) 智能敌机AI来袭--飞行路径算法设计与实现(下)
来源:程序员人生 发布时间:2015-05-06 09:06:59 阅读次数:4198次
林炳文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
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠