一般在游戏中我们避免不了处理旋转或者子d发射什么的,就比如塔防游戏来说吧,我们需要判断敌人往哪里走,炮塔就往哪里转,转完然后朝着一个方向发射子d(是一个方向而不是朝一个点,就比如保卫萝卜,子d穿过怪物继续朝那个方向飞行,直到飞往屏幕外才移除),下面来简单分析一下实现的过程,需要涉及到一点点平面向量的数学知识。
(注意匀速)
1. 旋转 : 朝着某个点的方向匀速旋转
2.发射:让子d朝着某个点的方向匀速移动
我们来分步骤实现,先实现旋转功能:
嗯,现在假设平面中有点A和点B,A是炮塔,B是敌人,现在我们需要让炮塔A的方向朝着敌人B旋转,因为炮塔放置的时候方向向上,所以我们要旋转的角度为α,如图
现在首先,我们创建敌人和塔
[cpp] view plain copy //敌人 autoenemy=Sprite::create("enemy.png"); enemy->setPostion(Point(100,200)); this->addChild(enemy); //塔 autotower=Sprite::create("tower.png"); tower->setPostion(Point(200,100)); this->addChild(tower);
然后我们让塔旋转瞄准敌人,只是为了能射它一脸(呵呵?)
//让塔的方向旋转对准敌人 //射击方向向量 PointshootVector=enemy->getposition()-tower->getposition(); //向量标准化(即向量长度为1) PointnormalizedVector=ccpnormalize(shootVector); //算出旋转的弧度 floatradians=atan2(normalizedVector.y,-normalizedVector.x); //将弧度转换成角度 floatdegree=CC_radians_TO_degrees(radians); //匀速旋转需要我们设置一下速度,这里假设旋转速度为2π(rad/s) floatrotateSpeed=2*M_PI; //那么旋转1弧度所用时间为 floatrotate_1rad_time=1/rotateSpeed; //所以旋转的时长为 floatrotateDuration=fabs(radians*rotate_1rad_time); //最后执行旋转 _sprite->runAction(Rotateto::create(rotateDuration,degree-90));
需要注意一下
(1)假设点A为塔,B为敌。则 向量 shootVector = OB -OA = AB
(2)atan2(y,x)是就是反正切函数, 算出的是 点(x,y)与x轴正方向的夹角,返回的是角的弧度值
(3)所以degree算出的角度其实是与x轴正方向的夹角
(4)由于炮塔方向向上,所以 【旋转的角度 α 】= degree - 90
如果你想不起来什么是反正切,那没关系,看下面假设和图(再想不起来我只能呵呵了)
假设tan(α) = y / x , 则有α = arctan(y / x)
旋转完后接下来我们再实现射击功能:
假设有塔,子d和敌人,位置如图,我们需要把子d由位置A沿着AB方向 匀速射到C(C点在屏幕外)
我们先创建敌人,塔和子d
this->addChild(tower); //子d,和塔在一个位置 autotower=Sprite::create("bullet.png"); tower->setPostion(Point(200,100)); this->addChild(tower);
然后这次我们真的射它一脸(再次呵呵)
@H_566_404@ PointshootVector=enemy->getposition()-bullet->getposition(); //移动长度向量 PointoverShootVector=normalizedVector*900; //超出屏幕的点 PointoffScreenPoint=bullet->getposition()+overShootVector; //假设速度为500(pix/s) floatmoveSpeed=500; //移动时间 floatmoveDuration=overShootVector/moveSpeed; //执行设计 automove=Moveto::create(moveDuration,offScreenPoint); CallFunc*moveDone=CallFunc::create(CC_CALLBACK_0(shootFinish,this,bullet)); bullet->runAction(Sequence::create(move,moveDone,NulL)); 射击结束后移除子d
//射击结束后移除 voIDHelloWorld::shootFinish(Node*pNode){ Sprite*bullet=(Sprite*)pNode; if(bullet!=NulL) bullet->stopAllActions(); this->removeChild(bullet); }
稍稍解释一下 :
(1)shootVector就是向量AB。
(2)overShootVector = (AB向量标准化)× 900 即得到 AC。比如说你设置的分辨率为 800 x 400 ,那么你可以用标准化向量 × 你最大分辨率再大一点,这样子向量就会超出屏幕之外而且长度又固定。
(3)然后根据向量OC = OA + AC ,算出要移动到的点offScreenPoint(即点C)。
(4)设置一下速度,长度一定了,所以时间 = 长度 / 速度 。
=====================================================
其实也没啥东西,纯属小白教程。。
转载请注明出处:http://blog.csdn.net/shun_fzll/article/details/34430045
总结以上是内存溢出为你收集整理的cocos2d-x 炮台旋转和子d移动的一点小技巧全部内容,希望文章能够帮你解决cocos2d-x 炮台旋转和子d移动的一点小技巧所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)