hello,一些游戏中经常有一些自动跟踪的子弹,一旦发射,就一定可以命中到玩家,同时玩家也是不断运动的,看看效果吧,这里我随便找了一张小图当作子弹或者敌人。
比如王者荣耀的水晶的攻击玩家。
解决这个问题,首先先来分析一下怎么去设计。
首先玩家是不断运动的,子弹在运动的时候需要改变自己的运动轨迹。
子弹在发射的时候总是跟踪着玩家,而且一定会命中
小code到了这一篇,差不多讲完了一个飞行射击游戏的一些常用功能。
这里需要分析4中情况。
1
2(原来可以用箭头和形状啊)
3
4
在每一种情况子弹/敌人的步进方向都不一样。
步进,可以简单理解为各在x , y轴方向上各“走”多少像素。
这里画一张图,方便理解
这里我们只要确定好子弹的步进长度(可以理解为速度)因为它直观的表现出速度,哈哈
然后,剩下的就交给3角函数吧
但是在此之前,还要获取子弹/敌人与我们玩家的之间的角度
看一张图
分别求出A,B,C的坐标
c点的坐标也很容易算出来。对于第1种情况(1图)计算如下
然后可以写代码算出角度了
我们应该在设计这种有跟踪行为的子弹的时候就设计好类
class Emeny{
public:
static Emeny*create(int type);//创建方法,为静态
virtual bool init(int type);//初始化方法
void move(Point pos);//移动方法。通过传递进来玩家的坐标对玩家相对于子弹的方向做出判断
Point getPos(Point pos);//返回x和y轴的步进
float getAngle(Point pos1,Point pos2,Point pos3); //得到玩家相对于子弹的角度
private:
float speed;//子弹步进
}
实现文件
Emeny*Emeny::create(int type){
//这是一种防御的写法,一起的文已经有写过了,这里偷懒就不在写了
auto emeny=new Emeny();
if(emeny&&emeny->init(type)){
emeny->autorelease();
return emeny;
}else{
delete emeny;
return NULL;
}
}
bool Emeny::init(int type){
speed=1;//初始化步进长度
if(type==1){
//判断参数实现子弹类型
this->initWithFile("blueemeny.png");
setHp(10);
}
if(type==2){
this->initWithFile("abouton.png");
}
//把它放在一个位置,这里我直接放在随便一个位置
this->setPosition(Point(240,160));
this->setAnchorPoint(Point(0.5,0.5));//设置锚点
return true;
}
void Emeny::move(Point pos){
this->setPosition(this->getPosition()+getPos(pos));//这里是通过把传递进来的pos即是玩家的坐标,把它交给getPos()函数去获得各坐标轴的步进长度。
//子弹或者敌人的运动方法
}
注意:因为控制篇幅,这里没有考虑子弹和玩家处于同一直线的原因,大家可以翻阅上次的360度子弹发射,这篇文章,其实是一样的。
Point Emeny::getPos(Point pos){
Point nextPos;//判断敌人或者子弹相对于玩家处于那个位置
这里的情况是如下图(其他的也就是上面所说的4种情况之一,这里是通过他们各自所处的x,y轴的位置来判断他们的相对位置)
if(this->getPositionX()>pos.x&&this->getPositionY()>pos.y){
float rad=getAngle(pos,this->getPosition(),Point(this->getPositionX(),this->getPositionY()-(this->getPositionY()-pos.y)));// 把A,B,C三个点传递给getAngle()函数
auto p=CC_DEGREES_TO_RADIANS(rad);
//把角度转化成幅度
nextPos=Point(-speed*cos(p),-speed*sin(p));//这种情况的x轴步进为-speed*cos(p),y轴的步进为-speed*sin(p),下面的情况也是差不多的
}
if(this->getPositionX()<pos.x&&this->getPositionY()<pos.y){
float rad=getAngle(pos,this->getPosition(),Point(this->getPositionX(),this->getPositionY()-(this->getPositionY()-pos.y)));
auto p=CC_DEGREES_TO_RADIANS(rad);
nextPos=Point(speed*cos(p),speed*sin(p));
}
if(this->getPositionX()<pos.x&&this->getPositionY()>pos.y){
float rad=getAngle(pos,this->getPosition(),Point(this->getPositionX(),this->getPositionY()-(this->getPositionY()-pos.y)));
auto p=CC_DEGREES_TO_RADIANS(rad);
nextPos=Point(speed*cos(p),-speed*sin(p));
}
if(this->getPositionX()>pos.x&&this->getPositionY()<pos.y){
float rad=getAngle(pos,this->getPosition(),Point(this->getPositionX(),this->getPositionY()-(this->getPositionY()-pos.y)));
auto p=CC_DEGREES_TO_RADIANS(rad);
nextPos=Point(-speed*cos(p),speed*sin(p));
}
return nextPos;
}
/下面的代码根上次那个《实现360度摇杆。。》是一样的,这里就再重复了
float Emeny::getAngle(Point pos1,Point pos2,Point pos3){
float dx1,dx2,dy1,dy2;
float angle;
dx1=pos2.x-pos1.x;
dx2=pos3.x-pos1.x;
dy1=pos2.y-pos1.y;
dy2=pos3.y-pos1.y;
float c= sqrt(dx1*dx1+dy1*dy1)*sqrt(dx2*dx2+dy2*dy2);
if(c==0){
return -1;
}
angle=acos((dx1*dx2+dy1*dy2)/c)/(3.1415)*180;
return angle;
}
到这里已经实现了所有的方法,现在就调用它吧
auto em1=Emeny::create(1);//创建一个子弹
然后用一个时间调度器。在每一帧都执行它 的move方法
这里假设玩家为_player
emeny->move(_player->getPosition());通过这样已经写好了全部。
其实这个算法不够高效,也存在一些精确问题,下次会有更加完善的方法分享给大家
想制作属于自己的网页小导游吗?也可以说是萌宠,一定要持续关注哦
(例子)
我们会给她加入导航和问好等一系列语言和一些其他帮助功能,假如在参加网页设计赛事的时候用上,说不定会成为加分项哦
拜拜~
网友评论