源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Cocos2d-x人物动作类实例

  • 时间:2020-09-24 14:58 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Cocos2d-x人物动作类实例
我们玩的游戏一般都可以看到精灵的运动,游戏的世界就是一个运动的世界,而所有的这些动作都可以分为一些基本的动作和动作的组合,今天就来学习一下动作类CCAction,首先看一下类之间的继承关系。 [img]http://files.jb51.net/file_images/article/201409/201491290417135.jpg?20148129427[/img] CCAction类下派生了三个动作类,执行动作的类是CCNode以及它的子类,通过函数runAction()来执行动作,其中CCFiniteTimeAction之下是常用的瞬时动作和延时动作。动作从本质上来说就是改变节点的属性,瞬时动作就是改变这些属性不需要时间,瞬时就完成了,而延时动作改变这些属性需要一些时间,可以通过参数来设置这个时间,下面是瞬时动作和延时动作的例子,解释看源代码。点击下图查看效果。 [img]http://files.jb51.net/file_images/article/201409/2014091209002747.gif?20148129627[/img]
bool HelloWorld::init()
{
  bool bRet = false;
  do
  {

    CC_BREAK_IF(! CCLayer::init());

  //创建一个精灵
  CCSprite * sprite = CCSprite::create("image.png");
  sprite->setPosition(ccp(240,160));
  //最后一个参数是精灵的tag,以便在众多的子节点中,通过getChildByTag()找到该节点
  this->addChild(sprite,0,0);

  //创建菜单
  CCMenuItemFont * fontMenu1 = CCMenuItemFont::create("start");
  CCMenuItemFont * fontMenu2 = CCMenuItemFont::create("stop");
  //和move函数相互绑定
  CCMenuItemToggle * toggleMenu = CCMenuItemToggle::createWithTarget(this,menu_selector(HelloWorld::move),
   fontMenu1,fontMenu2,NULL);
  CCMenu * menu = CCMenu::create(toggleMenu,NULL);
  menu->setPosition(ccp(420,40));
  this->addChild(menu);

    bRet = true;
  } while (0);

  return bRet;
}

void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //瞬时动作CCPlace,改变了精灵的坐标,可以用sprite->setPosition(ccp(60,160))代替,但写成动作可以加入到动作序列中
 CCPlace * action1 = CCPlace::create(ccp(60,160));
 //瞬时动作,使精灵做X轴的翻转
 CCFlipX * action2 = CCFlipX::create(true);

 if(toggleMenu->getSelectedIndex() == 1)
 {
  //通过runAction精灵执行动作
  sprite->runAction(action2);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {

 }
}
[img]http://files.jb51.net/file_images/article/201409/2014091209002748.gif[/img] [url=http://files.jb51.net/file_images/article/201409/2014091209002749.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002749.gif[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002750.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002750.gif[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002751.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002751.gif[/img] [/url]
void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //延时动作,第一个参数是执行动作所需要的时间,moveTo是绝对的,就是移动到哪个坐标,而moveBy是相对的
 //传入的ccp(10,0)是一个向量,精灵沿着x轴移动了10个像素
 CCMoveTo * moveTo = CCMoveTo::create(2.0,ccp(240,180));
 CCMoveBy * moveBy = CCMoveBy::create(2.0,ccp(10,0));
 //rotate按照一定的角度旋转,to强调的是结果,现在是0度,会旋转到90度,如果现在是90度,还是会在90度
 CCRotateTo * rotateTo = CCRotateTo::create(2.0,90);
 //by强调旋转的相对角度,不论现在多少度都会旋转90度,以to和by结尾的动作类都是相同的道理
 CCRotateBy * rotateBy = CCRotateBy::create(2.0,90);

 if(toggleMenu->getSelectedIndex() == 1)
 {
  //通过runAction精灵执行动作
  //sprite->runAction(moveTo);
  //sprite->runAction(moveBy);
  sprite->runAction(rotateBy);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {

 }
}
以by结尾的延时动作都可以通过reverse()获得它的反动作。 [url=http://files.jb51.net/file_images/article/201409/2014091209002752.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002752.gif[/img] [/url]
void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //第二个参数是跳跃的向量,第三个参数是跳跃的高度,第四个参数是跳跃的次数
 CCJumpBy * jumpBy = CCJumpBy::create(2.0,ccp(100,30),50,4);
 //以by结尾的延时动作都可以通过reverse()获得它的反动作
 CCActionInterval * jumpBack = jumpBy->reverse();

 if(toggleMenu->getSelectedIndex() == 1)
 {
  //通过runAction精灵执行动作
  sprite->runAction(jumpBy);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {
  sprite->runAction(jumpBack);
 }
}
延时动作中还有俩个重复动作的函数,就是重复不断的执行某一个动作,看下他们的继承关系。 [url=http://files.jb51.net/file_images/article/201409/2014091209002853.jpg][img]http://files.jb51.net/file_images/article/201409/2014091209002853.jpg[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002854.jpg][img]http://files.jb51.net/file_images/article/201409/2014091209002854.jpg[/img] [/url] 下面是实现的源代码。 [url=http://files.jb51.net/file_images/article/201409/2014091209002855.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002855.gif[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002856.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002856.gif[/img] [/url]
void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //第一个参数传入重复的动作,第二个参数传入重复的次数
 CCRepeat * repeat = CCRepeat::create(rotateBy,4);
 //永远重复执行一个动作
 CCRepeatForever * repeatForever = CCRepeatForever::create(rotateBy);

 if(toggleMenu->getSelectedIndex() == 1)
 {
  //通过runAction精灵执行动作
  sprite->runAction(repeatForever);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {

 }
}
下面再列举一下基本常用的瞬时动作和延续动作。 瞬时动作: 放置Place:效果类似于 setPosition = ccp(x, y)。 隐藏Hide:效果类似于setVisible:false。 显示Show:效果类似于setVisible:true。 可见切换:ToggleVisibility。 延时动作: 移动到CCMoveTo 移动CCMoveBy 跳跃到CCJumpTo设置终点位置和跳跃的高度和次数。 跳跃CCJumpBy设置终点位置和跳跃的高度和次数。 贝塞尔CCBezierBy支持 3 次贝塞尔曲线:P0-起点,P1-起点切线方向,P2-终点切线方向,P3-终点。 放大到CCScaleTo设置放大倍数,是浮点型。 放大CCScaleBy 旋转到CCRotateTo 旋转CCRotateBy 闪烁CCBlink设定闪烁次数 色调变化到CCTintTo 色调变换CCTintBy 变暗到CCFadeTo 由无变亮CCFadeIn 由亮变无CCFadeOut 每个函数的具体用法请大家自行试验。 接下来说一下同步动作序列和顺序动作序列。同步动作序列,就是几个动作同时执行,顺序动作序列,就是传入的几个动作按照顺序顺序执行。以下是他们的继承关系图。 [url=http://files.jb51.net/file_images/article/201409/2014091209002857.jpg][img]http://files.jb51.net/file_images/article/201409/2014091209002857.jpg[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002858.jpg][img]http://files.jb51.net/file_images/article/201409/2014091209002858.jpg[/img] [/url] 接下来看一下实现的源代码 [url=http://files.jb51.net/file_images/article/201409/2014091209002859.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002859.gif[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002860.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002860.gif[/img] [/url]
void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //创建如下几个动作

 CCMoveBy * move = CCMoveBy::create(2.0,ccp(100,0));
 CCRotateBy * rotate = CCRotateBy::create(2.0,720);

 CCFiniteTimeAction * moveBack = move->reverse();
 CCFiniteTimeAction * rotateBack = rotate->reverse();

 CCFlipY * flip = CCFlipY::create(true);

 //同步动作序列,传入的几个动作同时执行,执行的整个时间是最长的一个动作的执行时间,参数类型是CCFiniteTimeAction
 //传入的动作(动作的实质就是改变节点的属性)所影响的属性不要有冲突
 CCSpawn * spawn = CCSpawn::create(move,rotate,NULL);
 CCSpawn * spawnBack = CCSpawn::create(moveBack,rotateBack,NULL);

 //顺序动作序列,传入的几个动作按照传入的顺序顺序执行,执行的整体时间是所有动作的时间之和
 CCSequence * sequence = CCSequence::create(move,rotate,flip,NULL);
 CCSequence * sequenceBack = CCSequence::create(moveBack,rotateBack,flip->reverse(),NULL);

 if(toggleMenu->getSelectedIndex() == 1)
 {
  sprite->runAction(spawn);
  //sprite->runAction(sequence);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {
  sprite->runAction(spawnBack);
  //sprite->runAction(sequenceBack);
 }
}
接下来介绍CCAction的另外来个子类,CCFollow实现镜头跟随的效果,类似于我们在横版过关游戏中看到的人物永远在屏幕中间,而背景在移动,不过它们的实现具体是不是靠这个类就不知道了。CCSpeed可以实现快进和慢放的效果,就是改变了执行的速度。以下是源代码。 [url=http://files.jb51.net/file_images/article/201409/2014091209002961.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002961.gif[/img] [/url] [url=http://files.jb51.net/file_images/article/201409/2014091209002962.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002962.gif[/img] [/url]
void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //创建如下几个动作

 CCMoveBy * move = CCMoveBy::create(2.0,ccp(100,0));
 CCRotateBy * rotate = CCRotateBy::create(2.0,720);

 CCFiniteTimeAction * moveBack = move->reverse();
 CCFiniteTimeAction * rotateBack = rotate->reverse();

 CCFlipY * flip = CCFlipY::create(true);

 //同步动作序列,传入的几个动作同时执行,执行的整个时间是最长的一个动作的执行时间,参数类型是CCFiniteTimeAction
 //传入的动作(动作的实质就是改变节点的属性)所影响的属性不要有冲突
 CCSpawn * spawn = CCSpawn::create(move,rotate,NULL);
 CCSpawn * spawnBack = CCSpawn::create(moveBack,rotateBack,NULL);

 //顺序动作序列,传入的几个动作按照传入的顺序顺序执行,执行的整体时间是所有动作的时间之和
 CCSequence * sequence = CCSequence::create(move,rotate,flip,NULL);
 CCSequence * sequenceBack = CCSequence::create(moveBack,rotateBack,flip->reverse(),NULL);

 //CCFollow实现一个节点跟随一个节点运动,传入的参数是要跟随的节点
 CCFollow * follow = CCFollow::create(sprite);
 //执行这个动作的是要跟随的节点,一般是层,效果累世于横版过关游戏中的场景
 this->runAction(follow);

 if(toggleMenu->getSelectedIndex() == 1)
 {
  sprite->runAction(spawn);
  //sprite->runAction(sequence);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {
  sprite->runAction(spawnBack);
  //sprite->runAction(sequenceBack);
 }
}
以下是CCSpeed的实现,在上述代码的基础上做了一点修改。
void HelloWorld::move(CCObject* pSender)
{
 //通过tag获得添加的精灵
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
 CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;

 //创建如下几个动作

 CCMoveBy * move = CCMoveBy::create(2.0,ccp(100,0));
 CCRotateBy * rotate = CCRotateBy::create(2.0,720);

 CCFiniteTimeAction * moveBack = move->reverse();
 CCFiniteTimeAction * rotateBack = rotate->reverse();

 CCFlipY * flip = CCFlipY::create(true);

 //同步动作序列,传入的几个动作同时执行,执行的整个时间是最长的一个动作的执行时间,参数类型是CCFiniteTimeAction
 //传入的动作(动作的实质就是改变节点的属性)所影响的属性不要有冲突
 CCSpawn * spawn = CCSpawn::create(move,rotate,NULL);
 CCSpawn * spawnBack = CCSpawn::create(moveBack,rotateBack,NULL);

 //顺序动作序列,传入的几个动作按照传入的顺序顺序执行,执行的整体时间是所有动作的时间之和
 CCSequence * sequence = CCSequence::create(move,rotate,flip,NULL);
 CCSequence * sequenceBack = CCSequence::create(moveBack,rotateBack,flip->reverse(),NULL);

 //CCFollow实现一个节点跟随一个节点运动,传入的参数是要跟随的节点
 CCFollow * follow = CCFollow::create(sprite);
 //执行这个动作的是要跟随的节点,一般是层,效果累世于横版过关游戏中的场景
 this->runAction(follow);

 //CCSpeed分装了一个动作类,第二个参数是要改变的速度的倍数
 CCSpeed * speed1 = CCSpeed::create(spawn,2.0);
 CCSpeed * speed2 = CCSpeed::create(spawnBack,2.0);

 if(toggleMenu->getSelectedIndex() == 1)
 {
  sprite->runAction(speed1);
  //sprite->runAction(sequence);
 }
 else if(toggleMenu->getSelectedIndex() == 0)
 {
  sprite->runAction(speed2);
  //sprite->runAction(sequenceBack);
 }
}
以下再来介绍一下CCCallFunc家族类的使用方法,它们也是一个动作类,一般用在顺序动作序列中执行的最后一个动作,目的是调用一个函数,来完成一些功能。以下是这些类的继承关系。 [url=http://www.zaojiahua.com/wp-content/uploads/2014/02/2014-02-15_190652.jpg][img]http://files.jb51.net/file_images/article/201409/2014091209002963.jpg[/img] [/url] 接下来贴上源代码,注释是对各个类的使用的详细讲解。 [url=http://files.jb51.net/file_images/article/201409/2014091209002964.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002964.gif[/img] [/url][url=http://files.jb51.net/file_images/article/201409/2014091209002965.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002965.gif[/img] [/url][url=http://files.jb51.net/file_images/article/201409/2014091209002966.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002966.gif[/img] [/url][url=http://files.jb51.net/file_images/article/201409/2014091209002967.gif][img]http://files.jb51.net/file_images/article/201409/2014091209002967.gif[/img] [/url]
bool HelloWorld::init()
{
  bool bRet = false;
  do
  {
    CC_BREAK_IF(! CCLayer::init());

  CCSprite * sprite = CCSprite::create("image.png");
  sprite->setPosition(ccp(240,160));
  this->addChild(sprite,0,0);

  //创建一个菜单,添加一个run事件
  CCMenuItemFont * fontMenu = CCMenuItemFont::create("begin",this,menu_selector(HelloWorld::run));
  CCMenu * menu = CCMenu::create(fontMenu,NULL);
  menu->setPosition(ccp(400,40));
  this->addChild(menu);

    bRet = true;
  } while (0);

  return bRet;
}

void HelloWorld::run(CCObject* pSender)
{
 CCSprite * sprite = (CCSprite *)this->getChildByTag(0);

 //创建延时动作
 CCRotateBy * rotate = CCRotateBy::create(2.0,3*360);
 //CCCallFunc,为这个动作绑定一个函数,执行这个动作的时候会调用这个函数,创建以下四个动作的时候使用了不同的选择器,但名字和各个动作有关
 CCCallFunc * func = CCCallFunc::create(this,callfunc_selector(HelloWorld::show));
 //CCCallFuncN(N就是node的意思),与上边不同的是,绑定的函数需要一个参数,这个传入的参数就是执行这个动作的节点
 CCCallFuncN * funcN = CCCallFuncN::create(this,callfuncN_selector(HelloWorld::remove));
 int num = 10;
 //CCCallFuncND(D就是data的意思),这次绑定的函数,不仅需要绑定动作的节点作为参数传递,还带了一个void *类型的参数,代表可以是任何类型
 CCCallFuncND *funcND = CCCallFuncND::create(this,callfuncND_selector(HelloWorld::showData),(void *)num);
 CCSprite * sprite2 = CCSprite::create("image2.png");
 //CCCallFuncO(O就是object的意思)这次需要传入的参数是CCObject *类型的
 CCCallFuncO * funcO = CCCallFuncO::create(this,callfuncO_selector(HelloWorld::showSprite),sprite2);

 //创建顺序动作序列
 //CCSequence * sequence = CCSequence::create(rotate,func,funcND,NULL);
 //CCSequence * sequence = CCSequence::create(rotate,func,funcN,NULL);
 CCSequence * sequence = CCSequence::create(rotate,func,funcN,funcO,NULL);

 sprite->runAction(sequence);
}

//以下函数不要忘记在头文件中声明,注意每个函数的参数
void HelloWorld::show()
{
 CCLabelTTF * ttf = CCLabelTTF::create("action end","Arial",32);
 ttf->setPosition(ccp(240,260));
 this->addChild(ttf);
}

void HelloWorld::remove(CCNode * node)
{
 //没有通过getChildByTag()函数获得执行动作的精灵,而是使用remove传来的参数
 CCSprite * sprite = (CCSprite *)node;
 //true表示sprite不仅会移除,而且这个节点上的所有操作和回调都将删除
 sprite->removeFromParentAndCleanup(true);
 //通过以下的方法可以实现相同的效果,只是函数执行的对象不同
 //this->removeChild(sprite,true);
}

void HelloWorld::showData(CCNode * node,void * data)
{
 CCSprite * sprite = (CCSprite *)node;
 this->removeChild(sprite,true);
 CCLog("num = %d",data);
}

void HelloWorld::showSprite(CCObject * sender)
{
 CCSprite * sprite = (CCSprite *)sender;
 sprite->setPosition(ccp(240,160));
 this->addChild(sprite);
}
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部