【转】Cocos2d-x 2.0 拖尾效果深入分析
Cocos2d-x 2.0 拖尾效果深入分析
另:本章所用Cocos2d-x版本为:
cocos2d-2.0-x-2.0.2@ Aug 30 2012
http://cn.cocos2d-x.org/download
今天我们来学习一下Cocos2d-x中的拖尾效果。在游戏中,拖尾效果常常用来做刀光,火球法术等一些运动物体的效果。如图:
在Cocos2d-x中,拖尾效果有一个专门的类CCMotionStreak来实现。下面我们打开CCMotionStreak.h来看一下:
[cpp] view plaincopy
- #ifndef __CCMOTION_STREAK_H__
- #define __CCMOTION_STREAK_H__
- #include “CCProtocols.h”
- #include “textures/CCTexture2D.h”
- #include “ccTypes.h”
- #include “base_nodes/CCNode.h”
- //使用Cocos2d命名空间
- NS_CC_BEGIN
- //条带由三个基类共同派生
- class CC_DLL CCMotionStreak : public CCNode, public CCTextureProtocol, public CCRGBAProtocol
- {
- public:
- //构造
- CCMotionStreak();
- //析构
- virtual ~CCMotionStreak();
- //静态函数,创建一个拖尾效果,内部调用create实现,参一为消隐动画时长,参二为拖尾条带相邻顶点间的最小距离,参三为拖尾条带的宽度,参四为顶点颜色值,参五为所使用的纹理图片。
- CC_DEPRECATED_ATTRIBUTE static CCMotionStreak* streakWithFade(float fade, float minSeg, float stroke, ccColor3B color, const char* path);
- //静态函数,创建一个拖尾效果,内部调用create实现,参一为消隐动画时长,参二为拖尾条带相邻顶点间的最小距离,参三为拖尾条带的宽度,参四为顶点颜色值,参五为所使用的纹理对象指针。
- CC_DEPRECATED_ATTRIBUTE static CCMotionStreak* streakWithFade(float fade, float minSeg, float stroke, ccColor3B color, CCTexture2D* texture);
- //上面第一个创建函数的create实现。
- static CCMotionStreak* create(float fade, float minSeg, float stroke, ccColor3B color, const char* path);
- //上面第二个创建函数的create实现。
- static CCMotionStreak* create(float fade, float minSeg, float stroke, ccColor3B color, CCTexture2D* texture);
- //初始化拖尾效果
- bool initWithFade(float fade, float minSeg, float stroke, ccColor3B color, const char* path);
- //初始化拖尾效果
- bool initWithFade(float fade, float minSeg, float stroke, ccColor3B color, CCTexture2D* texture);
- //
- void tintWithColor(ccColor3B colors);
- //重置,删除所有的条带段
- void reset();
- //设置位置
- virtual void setPosition(const CCPoint& position);
- //绘制
- virtual void draw();
- //更新
- virtual void update(float delta);
- //取得纹理。
- virtual CCTexture2D* getTexture(void);
- //设置纹理。
- virtual void setTexture(CCTexture2D *texture);
- //设置
- virtual void setBlendFunc(ccBlendFunc blendFunc);
- virtual ccBlendFunc getBlendFunc(void);
- //设置颜色
- virtual void setColor(const ccColor3B& color);
- virtual const ccColor3B& getColor(void);
- //设置透明度
- virtual GLubyte getOpacity(void);
- virtual void setOpacity(GLubyte opacity);
- nbsp; i2 *= 4;
- newIdx2 *= 4;
- m_pColorPointer[newIdx2+0] = m_pColorPointer[i2+0];
- m_pColorPointer[newIdx2+1] = m_pColorPointer[i2+1];
- m_pColorPointer[newIdx2+2] = m_pColorPointer[i2+2];
- m_pColorPointer[newIdx2+4] = m_pColorPointer[i2+4];
- m_pColorPointer[newIdx2+5] = m_pColorPointer[i2+5];
- m_pColorPointer[newIdx2+6] = m_pColorPointer[i2+6];
- }else
- newIdx2 = newIdx*8;//如果mov等于0,则R,G,B值不用变,只修改A值即可。
- //将当前顶点原来的颜色顶点缓冲中Alpha值保存到顶点缓冲新位置Alpha值中。
- const GLubyte op = (GLubyte)(m_pPointState[newIdx] * 255.0f);
- m_pColorPointer[newIdx2+3] = op;
- m_pColorPointer[newIdx2+7] = op;
- }
- }
- //当前的顶点数量减去完全消隐的顶点数量。
- m_uNuPoints-=mov;
- //响应菜单按钮项进行下一个演示。
- void nextCallback(CCObject* pSender);
- //响应菜单按钮项进行上一个演示。
- void backCallback(CCObject* pSender);
- //响应菜单文字项进行模式切换。
- void modeCallback(CCObject* pSender);
- protected:
- //拖尾对象指针。
- CCMotionStreak *streak;
- };
对应CPP:
[cpp] view plaincopy
- //枚举所用到的精灵的TAG值
- enum {
- kTagLabel = 1,
- kTagSprite1 = 2,
- kTagSprite2 = 3,
- };
- //下一个效果演示
- CCLayer* nextMotionAction();
- //上一个效果演示
- CCLayer* backMotionAction();
- //重新演示当前的效果
- CCLayer* restartMotionAction();
- //场景索引
- static int sceneIdx = -1;
- //最大层数
- #define MAX_LAYER 3
- //根据效果创建不同的拖尾效果
- CCLayer* createMotionLayer(int nIndex)
- {
- switch(nIndex)
- {
- case 0: return new MotionStreakTest1();
- case 1: return new MotionStreakTest2();
- case 2: return new Issue1358();
- }
- return NULL;
- }
- //下一个效果
- CCLayer* nextMotionAction()
- {
- sceneIdx++;
- sceneIdx = sceneIdx % MAX_LAYER;
- CCLayer* pLayer = createMotionLayer(sceneIdx);
- pLayer->autorelease();
- return pLayer;
- }
- //上一个效果演示
- CCLayer* backMotionAction()
- {
- sceneIdx—;
- int total = MAX_LAYER;
- if( sceneIdx < 0 )
- sceneIdx += total;
- CCLayer* pLayer = createMotionLayer(sceneIdx);
- pLayer->autorelease();
- return pLayer;
- }
- //重新演示当前的效果
- CCLayer* restartMotionAction()
- {
- CCLayer* pLayer = createMotionLayer(sceneIdx);
- pLayer->autorelease();
- return pLayer;
- }
- //构造
- MotionStreakTest::MotionStreakTest(void)
- {
- }
- //析构
- MotionStreakTest::~MotionStreakTest(void)
- {
- }
- //标题
- std::string MotionStreakTest::title()
- {
- return “No title”;
- }
- //副标题。
- std::string MotionStreakTest::subtitle()
- {
- return “”;
- }
- //当前层加载时的处理
- void MotionStreakTest::onEnter()
- {
- //调用基类的相应处理。
- CCLayer::onEnter();
- //获取屏幕大小
- CCSize s = CCDirector::sharedDirector()->getWinSize();
- //创建标题文字标签
- CCLabelTTF* label = CCLabelTTF::create(title().c_str(), “Arial”, 32);
- //将文字标签加入当前层中
- addChild(label, 0, kTagLabel);
- //设置文字标签的位置
- label->setPosition(CCPointMake(s.width/2, s.height-50));
- //取得副标题
- string subTitle = this->subtitle();
- //创建副标题文字标签
- if (subTitle.size() > 0)
- {
- CCLabelTTF *l = CCLabelTTF::create(subTitle.c_str(), “Thonburi”, 16);
- addChild(l, 1);
- l->setPosition(ccp(s.width/2, s.height-80));
- }
- //创建菜单项
- CCMenuItemImage *item1 = CCMenuItemImage::create(s_pPathB1, s_pPathB2, this, menu_selector(MotionStreakTest::backCallback) );
- CCMenuItemImage *item2 = CCMenuItemImage::create(s_pPathR1, s_pPathR2, this, menu_selector(MotionStreakTest::restartCallback) );
- CCMenuItemImage *item3 = CCMenuItemImage::create(s_pPathF1, s_pPathF2, this, menu_selector(MotionStreakTest::nextCallback) );
- //创建菜单
- CCMenu *menu = CCMenu::create(item1, item2, item3, NULL);
- //设置菜单与各菜单项的位置
- menu->setPosition(CCPointZero);
- item1->setPosition(CCPointMake(s.width/2 - item2->getContentSize().width*2, item2->getContentSize().height/2));
- item2->setPosition(CCPointMake(s.width/2, item2->getContentSize().height/2));
- item3->setPosition(CCPointMake(s.width/2 + item2->getContentSize().width*2, item2->getContentSize().height/2));
- //将菜单加入当前层
- addChild(menu, 1);
- //创建一个菜单切换文字项,其实就是有复选框效果的文字标签。这里创建的切换项为“质量优先模式”和“效率优先模式”,响应函数为modeCallback。
- CCMenuItemToggle *itemMode = CCMenuItemToggle::createWithTarget(this, menu_selector(MotionStreakTest::modeCallback),
- CCMenuItemFont::create(“Use High Quality Mode”),
- CCMenuItemFont::create(“Use Fast Mode”),
- NULL);
- //创建第二个菜单并加入当前层
- CCMenu *menuMode = CCMenu::create(itemMode, NULL);
- addChild(menuMode);
- //设置菜单位置
- menuMode->setPosition(ccp(s.width/2, s.height/4));
- }
- //切换文字项的响应函数。
- void MotionStreakTest::modeCallback(CCObject *pSender)
- {
- //来回切换模式
- bool fastMode = streak->isFastMode();
- streak->setFastMode(! fastMode);
- }
- //重新演示当前效果。
- void MotionStreakTest::restartCallback(CCObject* pSender)
- {
- //创建一个演示场景。
- CCScene* s = new MotionStreakTestScene();//CCScene::create();
- s->addChild(restartMotionAction());
- //使用当前场景。
- CCDirector::sharedDirector()->replaceScene(s);
- s->release();
- }
- //下一个效果的演示
- void MotionStreakTest::nextCallback(CCObject* pSender)
- {
- //创建一个演示场景。
- CCScene* s = new MotionStreakTestScene();//CCScene::create();
- //将下一个演示层加入场景,并运行这个场景
- s->addChild( nextMotionAction() );
- CCDirector::sharedDirector()->replaceScene(s);
- s->release();
- }
- //上一个效果的演示
- void MotionStreakTest::backCallback(CCObject* pSender)
- { //创建一个演示场景。
- CCScene* s = new MotionStreakTestScene;//CCScene::create();
- //将上一个演示层加入场景,并运行这个场景
- s->addChild( backMotionAction() );
- CCDirector::sharedDirector()->replaceScene(s);
- s->release();
- }
然后是派生的第一个拖尾效果演示类:
[cpp] view plaincopy
- class MotionStreakTest1 : public MotionStreakTest
- {
- protected:
- //根结点
- CCNode* m_root;
- //带拖尾的目标结点
- CCNode* m_target;
- public:
- //加载当前层时的处理
- virtual void onEnter();
- //更新函数
- void onUpdate(float delta);
- //取得标题
- virtual std::string title();
- };
对应CPP:
[cpp] view plaincopy
- //加载当前层时的处理
- void MotionStreakTest1::onEnter()
- {
- //调用基类的相应函数。
- MotionStreakTest::onEnter();
- //取和屏幕大小
- CCSize s = CCDirector::sharedDirector()->getWinSize();
- // 创建根精灵结点,放入当前层中的屏幕中心位置。
- m_root = CCSprite::create(s_pPathR1);
- addChild(m_root, 1);
- m_root->setPosition(ccp(s.width/2, s.height/2));
- //创建目标精灵结点,放入根结点下的右边1/4屏幕宽度位置。
- m_target = CCSprite::create(s_pPathR1);
- m_root->addChild(m_target);
- m_target->setPosition(ccp(s.width/4, 0));
- // 创建拖尾效果并放入到当前层下。
- streak = CCMotionStreak::create(2, 3, 32, ccGREEN, s_streak);
- addChild(streak);
- //每帧调用onUpdate函数。
- schedule(schedule_selector(MotionStreakTest1::onUpdate));
- //创建一个旋转动画,2秒内自转360度。
- CCActionInterval* a1 = CCRotateBy::create(2, 360);
- //创建一个al1的无限循环动画。
- CCAction* action1 = CCRepeatForever::create(a1);
- //创建一个平移动画,2秒内向右移动100像素。
- CCActionInterval* motion = CCMoveBy::create(2, CCPointMake(100,0) );
- //根结点运行一个无限循环的动画序列,动画序列为平移动画及其反向动画。 m_root->runAction( CCRepeatForever::create((CCActionInterval*)(CCSequence::create(motion, motion->reverse(), NULL)) ) );
- //同时也运行无限循环的自转动画。
- m_root->runAction( action1 );
- //创建一个无限循环的动画序列,动画序列为7个变色动画,哪个结点使用它就会不断的变色。
- CCActionInterval *colorAction = CCRepeatForever::create((CCActionInterval *)CCSequence::create(
- CCTintTo::create(0.2f, 255, 0, 0),
- CCTintTo::create(0.2f, 0, 255, 0),
- CCTintTo::create(0.2f, 0, 0, 255),
- CCTintTo::create(0.2f, 0, 255, 255),
- CCTintTo::create(0.2f, 255, 255, 0),
- CCTintTo::create(0.2f, 255, 0, 255),
- CCTintTo::create(0.2f, 255, 255, 255),
- NULL));
- //让拖尾运行这个变色动画序列。
- streak->runAction(colorAction);
- }
- //实时更新函数。
- void MotionStreakTest1::onUpdate(float delta)
- {
- //更新拖尾的位置,设置为目标精灵结点的位置。
- streak->setPosition( m_target->convertToWorldSpace(CCPointZero) );
- }
- //取得标题。
- std::string MotionStreakTest1::title()
- {
- return “MotionStreak test 1”;
- }
演示如图:
派生的第二个拖尾效果演示类:
[cpp] view plaincopy
- class MotionStreakTest2 : public MotionStreakTest
- {
- //根结点
- CCNode* m_root;
- //带拖尾的目标结点
- CCNode* m_target;
- public:
- //加载当前层时的处理
- virtual void onEnter();
- //触屏并移动时响应处理
- void ccTouchesMoved(CCSet* touches, CCEvent* event);
- //取得标题
- virtual std::string title();
- };
对应的CPP:
[cpp] view plaincopy
- //加载当前层时的处理
- void MotionStreakTest2::onEnter()
- {
- //调用基类的相应函数。
- MotionStreakTest::onEnter();
- //这里设置打开触屏响应
- setTouchEnabled(true);
- //取得屏幕大小
- CCSize s = CCDirector::sharedDirector()->getWinSize();
- // 创建拖尾效果并放入到当前层下。
- streak = CCMotionStreak::create(3, 3, 64, ccWHITE, s_streak );
- addChild(streak);
- //设置拖尾的初始位置为屏幕中小。
- streak->setPosition( CCPointMake(s.width/2, s.height/2) );
- }
- //触屏并移动时响应处理
- void MotionStreakTest2::ccTouchesMoved(CCSet* touches, CCEvent* event)
- {
- //取得触点位置。
- CCSetIterator it = touches->begin();
- CCTouch* touch = (CCTouch*)(*it);
- CCPoint touchLocation = touch->getLocation();
- //设置为拖层的位置。
- streak->setPosition( touchLocation );
- }
- //取得标题
- std::string MotionStreakTest2::title()
- {
- return “MotionStreak test”;
- }
效果如图:
派生的第三个拖尾效果演示类:
[cpp] view plaincopy
- class Issue1358 : public MotionStreakTest
- {
- public:
- //取得标题
- virtual std::string title();
- //取得副标题
- virtual std::string subtitle();
- //加载当前层时的处理
- virtual void onEnter();
- //更新函数
- virtual void update(float dt);
- private:
- //中心位置
- CCPoint m_center;
- //半径
- float m_fRadius;
- //角度
- float m_fAngle;
- };
对应CPP:
[cpp] view plaincopy
- //加载当前层时的处理
- void Issue1358::onEnter()
- {
- //调用基类的相应函数。
- MotionStreakTest::onEnter();
- //取得屏幕位置
- CCSize size = CCDirector::sharedDirector()->getWinSize();
- // 创建拖尾效果并放入到当前层下。
- streak = CCMotionStreak::create(2.0f, 1.0f, 50.0f, ccc3(255, 255, 0), “Images/Icon.png”);
- addChild(streak);
- //初始化中心位置,半径和角度。
- m_center = ccp(size.width/2, size.height/2);
- m_fRadius = size.width/3;
- m_fAngle = 0.0f;
- //设置每帧的回调更新函数。
- schedule(schedule_selector(Issue1358::update), 0);
- }
- //每帧的回调更新函数。
- void Issue1358::update(float dt)
- {
- //角度增加1.0f
- m_fAngle += 1.0f;
- //计算拖尾的位置
- streak->setPosition(ccp(m_center.x + cosf(m_fAngle/180 * M_PI)*m_fRadius,
- m_center.y + sinf(m_fAngle/ 180 * M_PI)*m_fRadius));
- }
- //取得标题。
- std::string Issue1358::title()
- {
- return “Issue 1358”;
- }
- //取得副标题。
- std::string Issue1358::subtitle()
- {
- return “The tail should use the texture”;
- }
效果如图:
然后是演示用的场景:
[cpp] view plaincopy
- class MotionStreakTestScene : public TestScene
- {
- public:
- //运行场景的处理
- virtual void runThisTest();
- };
- //运行场景的处理
- void MotionStreakTestScene::runThisTest()
- {
- //创建下一个要演示的效果并放入当前场景中。
- CCLayer* pLayer = nextMotionAction();
- addChild(pLayer);
- //使用当前场景。
- CCDirector::sharedDirector()->replaceScene(this);
- }
总结一下:
拖尾效果的原理就是在相应距离内动态生成条带,然后逐渐消隐,在Cocos2d-x中可以指定这个最小距离,以及消隐的速度,还有条带的粗细,相应的纹理对象,都是通过CCMotionStreak 类来实现的。
又一篇结束了,看看时间,一点半了,为了今年的目标,我只能坚持下去。工作,写作,工具箱,一个都不能少!努力吧,骚年!
【转】Cocos2d-x 2.0 拖尾效果深入分析的更多相关文章
- cocos2d-x 2.0 拖尾效果分析
转自:http://game.dapps.net/gamedev/game-engine/7281.html 在Cocos2d-x中,拖尾效果有一个专门的类CCMotionStreak来实现.下面我们 ...
- cocos2dx 以子弹飞行为例解说拖尾效果类CCMotionStreak
在游戏开发中,有时会须要在某个游戏对象上的运动轨迹上实现渐隐效果.比方子弹的运动轨迹,假设不借助引擎的帮助,这样的效果则须要通过大量的图片来实现.而Cocos2D-x的拖动渐隐效果类CCMotionS ...
- [Unity3d]向量的过度方法以及拖尾效果
Vector3.RotateTowards() 用法 public static function RotateTowards(current: Vector3, target: Vector3, m ...
- 浅谈canvas中的拖尾效果
引言 很早就想了解以下 canvas 中的拖尾效果(如彗星,烟花等效果)是怎么实现的,但是一直没有深入了解,正巧在 codepen 上看到一个 demo,代码简单,效果炫酷,故有此文. 什么黑科技 在 ...
- [Cocos2d-x For WP8]MotionStreak拖尾效果
拖尾效果是指在在游戏中,一个精灵在运动的过程中会留下一个短暂的轨迹效果,在游戏里面如打斗的特效往往会需要用到这种效果来给运动的增加绚丽的效果.那么在Cocos2D-x里面我们可以使用一种内置的拖动渐隐 ...
- Cocos Creator 的实现拖尾效果
在游戏中,有时会需要在某个游戏对象上加上移动后的轨迹若隐若现的效果.使得游戏的效果较好,比如游戏大招,刀光,法术,流星划痕之类. Cocos Creator提供了一种内置的拖尾渐隐效果的实现方法:组件 ...
- Unity3D-飞机拖尾效果
1.插件准备 unity3d官网,Assert Store搜索Cartoon_airplane 插件 2.拖尾效果实现 飞机显示 拖尾组件设计 在airplane_02下 右键 Effects-Tra ...
- Unity 武器拖尾效果
Pocket RPG Weapon Trails 武器拖尾效果 Asset Store地址:https://www.assetstore.unity3d.com/en/#!/content/2458 ...
- 如何用纯 CSS 创作一个慧星拖尾效果的 loader 动画
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/YLRLaM 可交互视频教 ...
随机推荐
- Android Integer.decode()和Intger.valueof()
decode合适用来分析数字 可以分析 8进:010=>分析后为 8 10进:10=>分析后为 10 16进:#10|0X10|0x10=>分析后是 16 而valueof 只 ...
- Android 动态背景的实现以及SurfaceView中添加EditText控件
首先还是一贯作风,我们先看案例: \ 静态图看不出来效果,如果用过此软件(扎客)的同学们都知道,她的背景会动.怎么样,是不是觉得很时尚,起码比静态的要好(个人观点).其实实现起来并不复杂,这个如果让做 ...
- spring声明式事务 同一类内方法调用事务失效
只要避开Spring目前的AOP实现上的限制,要么都声明要事务,要么分开成两个类,要么直接在方法里使用编程式事务 [问题] Spring的声明式事务,我想就不用多介绍了吧,一句话“自从用了Spring ...
- 【HDOJ】1045 Fire Net
经典深搜.注意满足条件. #include <stdio.h> #include <string.h> #define MAXNUM 5 char map[MAXNUM][MA ...
- Android开发之bindService()通信
Service启动方式有两种,startService(intent)和bindService(intent,conn,Context.BIND_AUTO_CREATE) startService(i ...
- [Hadoop源码解读](一)MapReduce篇之InputFormat
平时我们写MapReduce程序的时候,在设置输入格式的时候,总会调用形如job.setInputFormatClass(KeyValueTextInputFormat.class);来保证输入文件按 ...
- [编译] g++ 与 Makefile
g++ -c CppSoureFile -o ObjectCodeFile -c 编译而不链接 -lm 链接数学库 -static 生成静态链接的程序
- [译]PyUnit—Python单元测试框架(1)
1. 原文及参考资料 原文链接:http://docs.python.org/2/library/unittest.html# 参考文档: http://pyunit.sourceforge.net/ ...
- WPF学习小记
WPF通用控制事件 Click:当控件被单击时发生.某些情况下,当用户按下Enter键时也会发生这样的事件. Drop:当拖曳操作完成时发生,也就是说,当用户将某个对象拖曳dao该控件上,然后松开鼠标 ...
- HDU5654xiaoxin and his watermelon candy 离线+树状数组
题意:bc 77div1 d题(中文题面),其实就是询问一个区间有多少不同的三元组,当然这个三元组要符合条件 分析(先奉上官方题解) 首先将数列中所有满足条件的三元组处理出来,数量不会超过 nn个. ...