捕鱼达人鱼游动时的转向例子
2015-07-12 20:09
531 查看
作为一个标准的程序员应该有写博客的习惯,其实早就有这个念头了,只是不知道该写点什么,最近一直有朋友问我捕鱼达人鱼游动的时候鱼的方向转动该如何实现。
其实我没有写过捕鱼达人,一年前有个朋友公司做捕鱼达人类的游戏,然后问我如何写鱼游动这一块,那个时候我就思考过这个问题。
其实鱼游动的实现可以分为3部分:1,鱼本身的游动图片的切换,即一个帧动画。2,鱼的坐标的变化,也就是鱼沿着路径游动的位置变化。3,鱼的方向的变化,简单的说就是鱼头的转向。
对于第一部分,我相信大家都会了,就是一个帧动画的播放而已;然后第二部分,坐标的变化也不难,可以自己设计一个鱼游走的路径算法,如果不想写那么复杂的算法,也可以直接写好几套路径保存在文件中直接读取;到了第三部分,也就是我人生中第一篇博文的内容,就是鱼的转向。
其实我也不明白,很多人问我关于捕鱼达人中鱼的游动的重点都是鱼的转向该如何实现,其实并不难,我以前只是把思路告诉他们,没有真正敲出代码来,今天又有一位小伙伴问我,我答应他下班帮他写个小demo,也就是这篇博文了。
先说一下思路:鱼的游动中,第一部分播放鱼的帧动画其实跟后面两个部分没什么关系,除非你还需要根据鱼的转向播放不同的帧动画,如果有朋友在这部分处理遇到难题的话,可以给我留言。
第二部分和第三部分其实有着密切的关系,鱼游动的路径其实决定着鱼的转向,我们来从数学的角度来分析一下,首先鱼的路径是一条曲线,而鱼在每个位置的转向是如何的呢?其实就是该点在曲线上的切线方向!没错!就是这么简单!那如何得到切线的系数k呢?利用我们的数学知识很容易就可以解决,只要获取一个不久之前某个时刻的坐标P1跟当前坐标P2,即可大概算出当前所在点的切线的系数K。然后每隔一段很短的时间就获取一次K的值,然后修改鱼的转向即可。大家很容易就可以看出,要想提高K的精度,只有一个方法,那就是让P1更加接近P2,也就是选取相隔的时间越短(纯粹的数学知识)。
好了,废话那么多,也该上代码了,首先,我们先让鱼游动:
接下来就到重点了,其实代码跟思路一样简单,就是利用一个定时刷新器每隔一小段时间就刷新一下鱼的转向:
没错,就是这么简单,接下来我把所有代码传上来:
Pond.h
Pond.cpp
第一次写博文,如果大家觉得写得不好的话留言给我建议,如果大家有什么疑问也可以给我留言,我会尽力回答大家的。感谢大家的支持!
其实我没有写过捕鱼达人,一年前有个朋友公司做捕鱼达人类的游戏,然后问我如何写鱼游动这一块,那个时候我就思考过这个问题。
其实鱼游动的实现可以分为3部分:1,鱼本身的游动图片的切换,即一个帧动画。2,鱼的坐标的变化,也就是鱼沿着路径游动的位置变化。3,鱼的方向的变化,简单的说就是鱼头的转向。
对于第一部分,我相信大家都会了,就是一个帧动画的播放而已;然后第二部分,坐标的变化也不难,可以自己设计一个鱼游走的路径算法,如果不想写那么复杂的算法,也可以直接写好几套路径保存在文件中直接读取;到了第三部分,也就是我人生中第一篇博文的内容,就是鱼的转向。
其实我也不明白,很多人问我关于捕鱼达人中鱼的游动的重点都是鱼的转向该如何实现,其实并不难,我以前只是把思路告诉他们,没有真正敲出代码来,今天又有一位小伙伴问我,我答应他下班帮他写个小demo,也就是这篇博文了。
先说一下思路:鱼的游动中,第一部分播放鱼的帧动画其实跟后面两个部分没什么关系,除非你还需要根据鱼的转向播放不同的帧动画,如果有朋友在这部分处理遇到难题的话,可以给我留言。
第二部分和第三部分其实有着密切的关系,鱼游动的路径其实决定着鱼的转向,我们来从数学的角度来分析一下,首先鱼的路径是一条曲线,而鱼在每个位置的转向是如何的呢?其实就是该点在曲线上的切线方向!没错!就是这么简单!那如何得到切线的系数k呢?利用我们的数学知识很容易就可以解决,只要获取一个不久之前某个时刻的坐标P1跟当前坐标P2,即可大概算出当前所在点的切线的系数K。然后每隔一段很短的时间就获取一次K的值,然后修改鱼的转向即可。大家很容易就可以看出,要想提高K的精度,只有一个方法,那就是让P1更加接近P2,也就是选取相隔的时间越短(纯粹的数学知识)。
好了,废话那么多,也该上代码了,首先,我们先让鱼游动:
m_fish = Sprite::create("fish.png"); m_fish->setPosition(0, m_winSize.height); this->addChild(m_fish); //随便设置一个贝塞尔曲线 ccBezierConfig bezier; bezier.controlPoint_1 = Vec2(m_winSize.width/4, 0); bezier.controlPoint_2 = Vec2(m_winSize.width*3/4, m_winSize.height); bezier.endPosition = Vec2(m_winSize.width, 0); FiniteTimeAction* beizerAction=CCBezierTo::create(10,bezier); m_fish->runAction(beizerAction);然后,鱼的位置就可以变化了:(我就随便找了一张图片,大伙凑合着看)
接下来就到重点了,其实代码跟思路一样简单,就是利用一个定时刷新器每隔一小段时间就刷新一下鱼的转向:
void Pond::refreshFish( float dt ) { static Vec2 lastPoint = Vec2(0, m_winSize.height); Vec2 curPoint = m_fish->getPosition(); //获取鱼当前坐标 if (curPoint == lastPoint) // { this->unschedule(schedule_selector(Pond::refreshFish)); return ; } float K = atan( (curPoint.x - lastPoint.x) / (curPoint.y - lastPoint.y) ); m_fish->setRotation(K*180/3.14159265); lastPoint = curPoint; //保存当前的坐标给下一轮刷新使用 }然后我们一起来看看效果:
没错,就是这么简单,接下来我把所有代码传上来:
Pond.h
#ifndef __POND_SCENE_H__ #define __POND_SCENE_H__ #include "cocos2d.h" using namespace cocos2d; class Pond : public Layer { public: static cocos2d::Scene* createScene(); CREATE_FUNC(Pond); virtual bool init(); void refreshFish(float dt); private: Sprite* m_fish; Size m_winSize; }; #endif // __POND_SCENE_H__
Pond.cpp
#include "Pond.h" const static float s_dt = 0.05; Scene* Pond::createScene() { auto scene = Scene::create(); auto layer = Pond::create(); scene->addChild(layer); return scene; } bool Pond::init() { if (!Layer::init()) { return false; } m_winSize = Director::getInstance()->getWinSize(); m_fish = Sprite::create("fish.png"); m_fish->setPosition(0, m_winSize.height); this->addChild(m_fish); //随便设置一个贝塞尔曲线 ccBezierConfig bezier; bezier.controlPoint_1 = Vec2(m_winSize.width/4, 0); bezier.controlPoint_2 = Vec2(m_winSize.width*3/4, m_winSize.height); bezier.endPosition = Vec2(m_winSize.width, 0); FiniteTimeAction* beizerAction=CCBezierTo::create(10,bezier); m_fish->runAction(beizerAction); this->schedule(schedule_selector(Pond::refreshFish), s_dt); return true; } void Pond::refreshFish( float dt ) { static Vec2 lastPoint = Vec2(0, m_winSize.height); Vec2 curPoint = m_fish->getPosition(); //获取鱼当前坐标 if (curPoint == lastPoint) // { this->unschedule(schedule_selector(Pond::refreshFish)); return ; } float K = atan( (curPoint.x - lastPoint.x) / (curPoint.y - lastPoint.y) ); m_fish->setRotation(K*180/3.14159265); lastPoint = curPoint; //保存当前的坐标给下一轮刷新使用 }
第一次写博文,如果大家觉得写得不好的话留言给我建议,如果大家有什么疑问也可以给我留言,我会尽力回答大家的。感谢大家的支持!
相关文章推荐
- cocos2dx 交叉编译 iconv库 protobuf库
- Cocos2d-x中PageView使用中的问题
- cmake clion 构建cocos2dx 应用程序并编译ios mac android
- 【笔记】试玩 cocos2d-x-3.0beta on android
- cocos2dx出现 Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)
- cocos2dx 粒子系统CCParticleSystem
- cocos2dx 中各种运动和速度
- CCScale9Sprite的用法
- cocos2dx入门
- [cocos2dx]随机数的使用
- 滴答UI编辑器初实战,实现cocos2dx的支持
- 成都公司诚聘cocos2dx(有wp经验)
- cocos2dx中js绑定的回调
- 第一次写博客,多多关照,
- xcode创建cocos2dx模版 关于couldn't add 'com.apple.XcodeGenerated' tag错误
- cocos2d-x 重力感应 加速器的使用
- cocos2d-x 一些有用的函数
- cocos2dx radiogrouop实现
- cocos2dx 坐标系锚点总结