林炳文Evankaka原创作品。转载请注明出处http://www.jb51.cc/tag/http://blog.csdn.net/evankaka
笔者近来比较忙,所以游戏更新都很慢,有此网友也一直在催,但是确实是没办法。今天5.1有时间,再来把游戏更新下。
此文接上文Cocos2d-x《雷电大战》(6) 智能敌机AI来袭--飞行路径算法设计与实现(上) ,还是对游戏中的敌机路径进行一个设计和实现。这里笔者又实现了两种敌机路线。分别如下:
(1)敌机朝着英雄飞机的位置飞去
(2)左右两群飞机穿过,其实就是一大群飞机从左到右和从右到左的飞行。
本文效果:
Cocos2d-x版本:3.4
工程环境:VS30213
一、敌机朝英雄飞机飞行
首先来讲讲敌机朝着英雄飞机的位置飞去,这里就比较简单,只要获取了英雄飞机的位置,再加了设置好敌机的初始位置,那么敌机的飞行路径就出来了。下面笔者画了张图,具体可以看如下图:
或者如下
其中英雄飞机的位置我们可以知道,就可以计算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); }注意,这里图片还是没有优化过的,敌机类也还没有单独写一个类,这里只是简单实现了下。
然后开一个定时器定时执行这个操作
//每隔0.5S调用一次 schedule(schedule_selector(GameMain::enemyBuild3),0.5f);
好了,现在来看看结果:
敌机能朝着英雄飞机撞去,并能实时改变自己的角度,当然。这个角度是一来就计算好了的。
二、左右群飞的敌机
左右群飞就是左边和右边都有一排飞机,然后同时向左或向右运动。飞机路径不是问题,最主要的是设置好它们的起始位置,让它们都能并排一起。原理图如下:
这里要注意的地方就是设置敌机的位置时记得要加上敌机图片的偏移量,Coco2dx中设置精灵位置时默认是以图片中心点为原点,所以得加上这个偏移量。并且它们移动的距离都是一样的,所以可以用MoveBy来实现,Y轴方向运动为0,X轴方向运动量为屏幕宽+敌机宽度。左右敌机X轴方向运动量不一样。记得!并且,这里的MoveBy的动作只能给一个敌机来使用,如果另一个敌机是相同的动作,那么就可以用clone()函数,而不用再重新创建一个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(-90); spritePlane5->setRotation(-90); spritePlane6->setRotation(-90); //设置缩放 //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-10)); 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,NULL); Sequence* sequence2 = Sequence::create(actionMove1->clone(),NULL); Sequence* sequence3 = Sequence::create(actionMove1->clone(),NULL); Sequence* sequence4 = Sequence::create(actionMove2,NULL); Sequence* sequence5 = Sequence::create(actionMove2->clone(),NULL); //飞机开始跑动 spritePlane1->runAction(sequence1); spritePlane2->runAction(sequence2); spritePlane3->runAction(sequence3); spritePlane4->runAction(sequence4); spritePlane5->runAction(sequence5); }
然后还是相同的原理,开个定时器,来看看效果:
//每隔0.5调用一次 schedule(schedule_selector(GameMain::enemyBuild4),0.5f);
两种飞机一起来:
三、总结
这里飞机的路径设计了四种,因为还没有进行优化,所以内存占用会有点多,后面笔者将会把敌机类全都放在一个Plist中,这样子内存就会小点了。其实,在飞行游戏中。还有BOSS机,BOSS机的智能AI设计也是一个很好玩。当然,敌机子弹类也很重要,而这一部分的内容将会放在敌机类设计完成之后再来讲。下一讲中我们将来封装自己的敌机类。
林炳文Evankaka原创作品。转载请注明出处http://www.jb51.cc/tag/http://blog.csdn.net/evankaka