cocos2d-x 关于旋转和移动的一点小技巧

你犯困吗,恩。给你讲个笑话提提神~

一對情侶去從林遊玩。被食人族捉住。食人族首領心情非常好。說你們假设想活命,就吃掉對方的大便。在他們回來的路上。女人終於忍不住停下。坐到石頭上哭起來。男人摟住她的肩膀。

女人別過臉去,幽幽的說:你不愛我,要不然剛才你不會拉這麼多。

(能呵呵吗?)

================================================================================

一般在游戏中我们避免不了处理旋转或者子弹发射什么的,就比方塔防游戏来说吧,我们须要推断敌人往哪里走,炮塔就往哪里转,转完然后朝着一个方向发射子弹是一个方向而不是朝一个点,就比方保卫萝卜,子弹穿过怪物继续朝那个方向飞行。直到飞往屏幕外才移除),以下来简单分析一下实现的过程,须要涉及到一点点平面向量的数学知识。

(注意匀速)

1. 旋转 : 朝着某个点的方向匀速旋转

2.发射:让子弹朝着某个点的方向匀速移动

我们来分步骤实现,先实现旋转功能:

嗯,如今如果平面中有点A和点B,A是炮塔。B是敌人。如今我们须要让炮塔A的方向朝着敌人B旋转,由于炮塔放置的时候方向向上,所以我们要旋转的角度为α,如图

如今首先,我们创建敌人和塔

//敌人
auto enemy = Sprite::create("enemy.png");
enemy->setPostion(Point(100,200));
this->addChild(enemy);

//塔
auto tower = Sprite::create("tower.png");
tower->setPostion(Point(200,100));
this->addChild(tower);

然后我们让塔旋转瞄准敌人,仅仅是为了能射它一脸(呵呵?)

//让塔的方向旋转对准敌人

//射击方向向量
Point shootVector = enemy->getPosition() - tower->getPosition();
//向量标准化(即向量长度为1)
Point normalizedVector = ccpNormalize(shootVector) ;
//算出旋转的弧度
float radians = atan2(normalizedVector.y, - normalizedVector.x);
//将弧度转换成角度
float degree = CC_RADIANS_TO_DEGREES(radians);

//匀速旋转须要我们设置一下速度。这里如果旋转速度为 2π (rad/s)
float rotateSpeed = 2 * M_PI;
//那么旋转1弧度所用时间为
float rotate_1rad_time = 1 / rotateSpeed;
//所以旋转的时长为
float rotateDuration = 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)

旋转完后接下来我们再实现射击功能:

如果有塔。子弹和敌人,位置如图,我们须要把子弹由位置A沿着AB方向 匀速射到C(C点在屏幕外)

我们先创建敌人,塔和子弹

//敌人
auto enemy = Sprite::create("enemy.png");
enemy->setPostion(Point(100,200));
this->addChild(enemy);

//塔
auto tower = Sprite::create("tower.png");
tower->setPostion(Point(200,100));
this->addChild(tower);

//子弹,和塔在一个位置
auto tower = Sprite::create("bullet.png");
tower->setPostion(Point(200,100));
this->addChild(tower);

然后这次我们真的射它一脸(再次呵呵)

//射击方向向量
Point shootVector = enemy->getPosition() - bullet->getPosition();
//向量标准化(即向量长度为1)
Point normalizedVector = ccpNormalize(shootVector);
//移动长度向量
Point overShootVector = normalizedVector * 900;
//超出屏幕的点
Point offScreenPoint = bullet->getPosition() + overShootVector;

//如果速度为500(pix/s)
float moveSpeed = 500;
//移动时间
float moveDuration = overShootVector / moveSpeed;

//运行设计
auto move = MoveTo::create(moveDuration,offScreenPoint);
CallFunc* moveDone = CallFunc::create(CC_CALLBACK_0(shootFinish,this,bullet));
bullet->runAction(Sequence::create(move,moveDone,NULL));

射击结束后移除子弹

//射击结束后移除
void HelloWorld::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

时间: 2024-09-28 19:06:02

cocos2d-x 关于旋转和移动的一点小技巧的相关文章

在ASP.NET使用javascript的一点小技巧

我们在进行ASP.NET开发时,经常会用到一些javascript脚本,比如: private void Button1_Click(object sender, System.EventArgs e) { Response.Write( "<script language='javascript'>alert('OK');</script>") ; } 经常是重复的书写这些脚本,如果我们能做成一个相应的函数就好了,直接就可以拿来使用.很多人都有自己的一些jav

对于shell脚本参数获取时的一点小技巧

问题如下: 根据脚本参数的个数$#进行一个循环,在依次输出每个参数$1 $2 $3...... 我有一个循环变量i $i 取到这时的i为1,我想使用这个1再去调用$1,也是就是打印出第一个参数 就是$($i)的意思来取到第几个参数,当然$($i)是不好用的 当时纠结了好久,最后上百度提问,两位高手给出了答案: 1) #!/bin/sh NUMBER=$# echo $NUMBER i=1 while [ $i -le $NUMBER ] do a[$i]=$1 #将数组a[i]赋值为$1,即取得

ssm开发的一点小技巧

一般使用反转工作生成基础bean如Items然后我们使用的实体类一般是基础bean的拓展类ItemsCustomer,继承自基础类,这个是为了方便对于表字段的更改生成的bean影响减低我们查询一般是使用一个ViewObject VO类 配置文件的话一般是同名前缀,然后web.xml中配置使用通配符方式,这样便于管理,不需要一个一个include dao层中我们只需要写接口,impl由mybatis的mapper代劳就是dao层返回的是基于数据表的数据 然后service是业务层,一系列的逻辑都在

CMD明令行下操作的一点小技巧

1.更改CMD窗口整体颜色: (护眼色) color 02 2.更改CMD默认的路径: 开始-运行-输入regedit打开注册表,找到HKEY_CURRENT_USER\Software\Microsoft\Command Processor然后在其右边建立autorun字符串,内容为你想要的路径如:cd /d D:\oracle\script回车,然后重新打开一个CMD即刻生效.

android rss阅读器开发一点小技巧

这几天一直在学习开发Rss阅读器,遇到一个很坑的问题,InputSource这里总是出错.弄了好久,终于让我找到一个解决方法----看代码: new Thread(){ @Override public void run() { try { URL url = new URL(RSS_URL); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser();

mysql数据库中文乱码的一点小技巧

查询数据库中的所使用的字符集 SHOW VARIABLES LIKE 'CHARACTER%' 设置数据库的字符编码集 URL=jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8 今天添加数据到数据库,刚好就碰到了中文乱码,将eclipse里面的默认字符集和mysql数据库里面的字符集都改成了utf8,部署运行后还是不行. 后来在网上搜了一下,刚好看到了上面的这个方法, 在数据库连接池的配置文件中改了一下URL的地址,然后就好了.

SSRS(RDLC)报表开发的一点小技巧

说明: 开发工具为: SQL Server Data Tools     开发环境为: SQL Server 2012 一. 饼图数据外部显示 首先我们来看3张效果图:  内部显示 . 外部显示 . 3D效果-外部显示    默认是内部显示, 如何设置为外部显示呢?如下图: 设置好后数据是显示在外部了,但并没有出现数据和图之间的连接线条.想要显示线条,那么就要开启3D效果,步骤如下: 二. 将数值转为百分比显示 如示例一中的数值分别为: 76 , 39 ,  6 , 25 . 如果将其转为百分比

android 操作sqlite的一点小技巧

1.android 在sqlite插入数据时,是非常耗时的操作,原因是sqlite缺省会为每个插入操作开启一个事务,当数量变多的时候,自然时间就变得很慢,这时候可以考虑在插入等操作时先开启一个事务,再来批量操作. 可以参考例子:http://bbs.csdn.net/topics/360042960 2.sqlitedatabase关于事务的一些操作: SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查

linux目录太长怎么办?分享一点小技巧

在linux使用cd的时候,可能会遇到目录比较深的时候,这个时候总是cd一个很长的目录会很麻烦,那有没有什么比较方便的方法呢? 若是在两个目录中来回切换,这个时候可以使用cd - 这个命令,可以完成在两个目录中来回切换的作用,那为什么使用cd - 能够表示在两个目录中来回切换呢? 因为cd - 等同于 cd $OLDPWD 顾名思义,OLDPWD这个变量保存的就是前一次的PATH值 但若是经常切换目录数大于2个呢? 这时候可以采用这一对好基友 pushd 和 popd 来进行目录的切换,当然还需