动作在cocos2d-x中可以说是精华部分(不是说其它的不好,而是这一部分内容特别丰富!!),作为重中之重,我们会分几个阶段来学习,先从简单的动作开始,然后通过组合简单的动作形成复杂动作。

一下就是我们将会用到的主要函数,函数有些多,但不一定全部要学,可以根据自己的需要来由选择性的学习。

1.Manual Transformation

2.MoveTo / MoveBy

3.RotateTo / RotateBy

4.JumpTo / JumpBy

5.Blink

6.FadeIn / FadeOut

7.Tint

8.Animation

9.Sequence: Move + Rotate

10.Sequence of InstantActions

 

 

 

step1:创建一个cocos2d-win32 application,并命名为action;

以下是我将用到的图片素材:

step2:

首先,定义一些如下常量和变量:

static int index = 1;//浏览到第几个动作
const int MAX_INDEX = 10;//总共要展示的动作种类数目
 
enum
{
  MANUAL_ACTION = 1,
  MOVE_ACTION,
  ROTATE_ACTION,
  JUMP_ACTION,
  BLINK_ACTION,
  FADE_ACTION,
  TINT_ACTION,
  ANIMATE_ACTION,
  SEQUENCE_ACTION_1,
  SEQUENCE_ACTION_2
};

创建一个基本的动作类(仅仅包含三个操作按钮),然后让其他的动作类继承此基础类,可以减少重复写按钮操作函数。

在HelloWorldScene.h中添加如下动作类:

class BasicActions:public CCLayer
{
protected:
  CCSprite* m_player;
 
public:
  virtual void onEnter();
  virtual void onExit();
 
  virtual std::string title();
 
  void nextMenuCallback(CCObject* pSender);
  void backMenuCallback(CCObject* pSender);
  void restartMenuCallback(CCObject* psender);
};
 
//manual action
//基本的动作
class ActionManual:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
//move action
//对象移动操作
class ActionMove:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
//rotate action
//旋转动作
class ActionRotate:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
//jump action
//跳跃动作
class ActionJump:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
//blink action
//闪烁动作
class ActionBlink:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
 
 
//fade action
//淡化动作
class ActionFade:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
//tint action
//着色动作
class ActionTint:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
 
//animate action
//动画(由帧组成)
class ActionAnimate:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
//sequence action1
//连贯动作
class ActionSequence:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
};
 
 
 
//sequence action2
//连贯动作,带有事件响应
class ActionSequence2:public BasicActions
{
public:
  virtual void onEnter();
  virtual std::string title();
 
public:
  void callback1();
  void callback2();
 
};

由于在点击“back”、“next”两个按钮时会进行背景的切换,以更换动作:为了方便操作,我在HelloWorldScene.cpp中添加了一个函数用于操作对应动作类的创建:

CCLayer* runThisTest(int index)
{
  CCLayer* pLayer = NULL;
 
  switch (index)
  {
  case MANUAL_ACTION: 
    pLayer = new ActionManual(); break;
 
  case MOVE_ACTION:
    pLayer = new ActionMove();break;
 
  case ROTATE_ACTION:
    pLayer = new ActionRotate();break;
 
  case JUMP_ACTION:
    pLayer = new ActionJump();break;
 
  case BLINK_ACTION:
    pLayer = new ActionBlink();break;
 
  case FADE_ACTION:
    pLayer = new ActionFade();break;
 
  case TINT_ACTION:
    pLayer = new ActionTint();break;
 
  case ANIMATE_ACTION:
    pLayer = new ActionAnimate();break;
 
  case SEQUENCE_ACTION_1:
    pLayer = new ActionSequence();break;
 
  case SEQUENCE_ACTION_2:
    pLayer = new ActionSequence2();break;
  }
 
  return pLayer;
}

在runThisTest函数中index用来标记当前处于那个背景,以便创建响应的动作,这里我把BasicAction类中的成员函数定义罗列出来,方便大家理解runThisTest函数的用法:

void BasicActions::onEnter()
{
  CCLayer::onEnter();
 
  CCSize size = CCDirector::sharedDirector()->getWinSize();
 
  //添加基本角色
  m_player = CCSprite::spriteWithFile("player.png");
  m_player->retain();//此处涉及到指针等内存管理机制,目前暂不展开做详细讨论,之后我会做一个专题来讲解这方面的知识
  m_player->setPosition(ccp(size.width/2, size.height/2));
  addChild(m_player, 1);
 
  //添加标题
  std::string strTitle = title();
  const char* ptitle = strTitle.c_str();
  CCLabelTTF* pLabel = CCLabelTTF::labelWithString(ptitle, "Arial", 30);
  pLabel->setPosition(ccp(size.width/2, size.height-40));
  addChild(pLabel);
 
  //添加基本按钮
  CCLabelTTF* pNextLabel  = CCLabelTTF::labelWithString("Next ", "Arial", 30);
  CCLabelTTF*pBackLabel = CCLabelTTF::labelWithString("Back ", "Arial", 30);
  CCLabelTTF*pRestartLabel = CCLabelTTF::labelWithString("Restart ", "Arial", 30);
 
  CCMenuItemLabel* pNextItem  = CCMenuItemLabel::itemWithLabel(
    pNextLabel, this, menu_selector(BasicActions::nextMenuCallback));
  CCMenuItemLabel* pBackItem = CCMenuItemLabel::itemWithLabel(
    pBackLabel, this, menu_selector(BasicActions::backMenuCallback));
  CCMenuItemLabel* pRestartItem = CCMenuItemLabel::itemWithLabel(
    pRestartLabel, this, menu_selector(BasicActions::restartMenuCallback));
 
  CCMenu* pNextMenu = CCMenu::menuWithItem(pNextItem);
  CCMenu* pBackMenu = CCMenu::menuWithItem(pBackItem);
  CCMenu* pRestartMenu = CCMenu::menuWithItem(pRestartItem);
 
  pNextItem->setPosition(ccp(size.width/2 +150, 50));
  pBackItem->setPosition(ccp(size.width/2 - 150, 50));
  pRestartItem->setPosition(ccp(size.width/2 , 50));
 
  pNextMenu->setPosition(CCPointZero);
  pBackMenu->setPosition(CCPointZero);
  pRestartMenu->setPosition(CCPointZero);
 
  addChild(pNextMenu,1);
  addChild(pBackMenu, 1);
  addChild(pRestartMenu,1);
}
 
void BasicActions::onExit()
{
  m_player->release();
 
  CCLayer::onExit();
}
 
std::string BasicActions::title()
{
  return "";
}
 
void BasicActions::nextMenuCallback(CCObject* pSender)
{
  if(index == MAX_INDEX)//已经是最后一个动作,不能再向下浏览
    return ;
  index++;
 
  CCScene* scene = new CCScene();
  //注意!!此处不能用CCScene::node(),node的释放方式是"autorelease",会与scene->release()重复
  scene->addChild(runThisTest(index));
  CCDirector::sharedDirector()->replaceScene(scene);
  scene->release();
}
 
void BasicActions::backMenuCallback(CCObject* pSender)
{
  if(index == 1)//index = 1表示上个动作不存在
    return ;
  index--;
 
  CCScene* scene = new CCScene();
  //注意!!此处不能用CCScene::node(),node的释放方式是"autorelease",会与scene->release()重复
  scene->addChild(runThisTest(index));
  CCDirector::sharedDirector()->replaceScene(scene);
  scene->release();
}
 
void BasicActions::restartMenuCallback(CCObject* psender)
{
 
  CCScene* scene = new CCScene();
 
  scene->addChild(runThisTest(index ));
  CCDirector::sharedDirector()->replaceScene(scene);
  scene->release();

接下来,就只需把继承了BasicAction父类的子类全部补充完即可:

//Manual
 
void ActionManual::onEnter()
{
  BasicActions::onEnter();
 
  CCSize size = CCDirector::sharedDirector()->getWinSize();
 
  //m_player->setScaleX(3.0f);//水平拉伸对象
  //m_player->setScaleY(3.0);//垂直拉伸对象
  //m_player->setPosition(ccp(200,200));改变对象的位置
  //m_player->setOpacity(100);//设置透明度
  //m_player->setRotation(120);//对对象进行旋转
  //m_player->setColor(ccc3(255,0,0));//设置对象颜色
}
 
std::string ActionManual::title()
{
  return "basic action function";
}
 
//move to / move by
void ActionMove::onEnter()
{
  BasicActions::onEnter();
 
  CCSize size = CCDirector::sharedDirector()->getWinSize();
  CCActionInterval* moveToAction = CCMoveTo::actionWithDuration(2,ccp(size.width - 50, size.height - 50));
  //CCActionInterval是延时动作,与之对应的是CCActionInstant即时动作
  //CCMoveTo每次执行都到达指定的地点
  //actionWithDuration第一个参数是设置动作的时间(秒),第二个是动作最终的坐标位置
  CCActionInterval* moveByAction = CCMoveBy::actionWithDuration(2,ccp(80, 80));
  //CCMoveBy每次执行,x坐标增加80,y坐标增加80
  CCActionInterval* moveBackAction = moveByAction->reverse();//按相反的方式返回,即x坐标减少80,y坐标减少80
  
  //m_player->runAction(moveToAction);
  //m_player->runAction(moveByAction);
  //m_player->runAction(moveBackAction);
  m_player->runAction(CCSequence::actions(moveByAction, moveBackAction, NULL));
 
}
 
std::string ActionMove::title()
{
  return "MoveTo/MoveBy";
}
 
//rotate
void ActionRotate::onEnter()
{
  BasicActions::onEnter();
 
  CCActionInterval* actionTo = CCRotateTo::actionWithDuration(2,90);
  CCActionInterval* actionBy = CCRotateBy::actionWithDuration(2,45);
  CCActionInterval* actionReverse = actionBy->reverse();
 
  //m_player->runAction(actionBy);
  m_player->runAction(CCSequence::actions(actionBy, actionReverse, NULL));
}
 
std::string ActionRotate::title()
{
  return "Rotate";
}
 
//jump action
void ActionJump::onEnter()
{
  BasicActions::onEnter();
 
  CCSize size = CCDirector::sharedDirector()->getWinSize();
  CCActionInterval* actionTo = CCJumpTo::actionWithDuration(2,ccp(size.width - 50, size.height- 50),50,5);
  //第三个参数是跳跃的高度,第四个参数是跳跃的次数
  CCActionInterval* actionBy = CCJumpTo::actionWithDuration(2,ccp(size.width - 50, size.height- 50), 50,5);
  CCActionInterval* actionReverse = actionBy->reverse();
 
  //m_player->runAction(actionTo);
  //m_player->runAction(actionBy);
  //m_player->runAction(actionReverse);
  m_player->runAction(CCSequence::actions(actionBy, actionReverse, NULL));
}
 
std::string ActionJump::title()
{
  return "JumpTo / JumpBy";
}
 
 
//blink action
void ActionBlink::onEnter()
{
  BasicActions::onEnter();
 
  CCActionInterval* action = CCBlink::actionWithDuration(2,10);
  //第一个参数是动作时间,第二个是闪烁的次数
  m_player->runAction(action);
 
}
 
std::string ActionBlink::title()
{
  return "Blink";
}
 
 
//fade action
void ActionFade::onEnter()
{
  BasicActions::onEnter();
 
  CCActionInterval* action = CCFadeIn::actionWithDuration(1);
  CCActionInterval* back = action->reverse();
 
  //CCActionInterval* action = CCFadeOut::actionWithDuration(2);
  //CCActionInterval* back = action->reverse();
 
  m_player->runAction(CCSequence::actions(action,back,NULL ));
 
}
 
std::string ActionFade::title()
{
  return "FadeIn  / FadeOut";
}
 
//tint action
void ActionTint::onEnter()
{
  BasicActions::onEnter();
 
  CCActionInterval* action  = CCTintTo::actionWithDuration(2,255,0,255);
  CCActionInterval* back =action->reverse();
  //后面三个参数是三基色
  //m_player->runActin(action);
  m_player->runAction(CCSequence::actions(action, back, NULL));
}
 
std::string ActionTint::title()
{
  return "Tint";
}
 
 
//animate action
void ActionAnimate::onEnter()
{
  BasicActions::onEnter();
 
  CCAnimation* animation = CCAnimation::animation();
  char frameName[100] = {0};
 
  for(int i = 1; i<=5; i++)
  {
    sprintf(frameName, "player%d.png", i);
    animation->addFrameWithFileName(frameName);
  }
 
  CCActionInterval* action = CCAnimate::actionWithDuration(3,animation, false);
  m_player->runAction(action);
 
}
 
std::string ActionAnimate::title()
{
  return "animate";
}
 
//sequence action
void ActionSequence::onEnter()
{
  BasicActions::onEnter();
 
  CCSize size = CCDirector::sharedDirector()->getWinSize();
  CCFiniteTimeAction* action = CCSequence::actions(
    CCMoveTo::actionWithDuration(2,ccp(size.width - 50, size.height - 50)),
    CCRotateBy::actionWithDuration(2,720), NULL);
 
  m_player->runAction(action);
}
 
std::string ActionSequence::title()
{
  return "move + rotate";
}
 
 
//sequence action2
void ActionSequence2::onEnter()
{
  BasicActions::onEnter();
 
  CCFiniteTimeAction* action = CCSequence::actions(
    //CCPlace:放置到一个位置,是个即时动作
    CCPlace::actionWithPosition(ccp(300,200)),
    CCShow::action(),
    CCMoveBy::actionWithDuration(1, ccp(100,0)),
    //在游戏中,可能会出现一个角色使用某种技能召唤神兽之类的,一下的函数就是用于此
    CCCallFunc::actionWithTarget(this, callfunc_selector(ActionSequence2::callback1)),//响应callback1事件,此事件召唤一个同伴
    CCCallFunc::actionWithTarget(this, callfunc_selector(ActionSequence2::callback2)), NULL);//此事件弹出一行字
 
  m_player->runAction(action);
}
 
std::string ActionSequence2::title()
{
  return "sequence action2";
}
 
//弹出一个新角色
void ActionSequence2::callback1()
{
  CCSize size = CCDirector::sharedDirector()->getWinSize();
  CCSprite* pSprite = CCSprite::spriteWithFile("friend.png");
  pSprite->setPosition(ccp(size.width/4, size.height/3));
  addChild(pSprite);
}
//弹出一行字幕
void ActionSequence2::callback2()
{
  CCSize size = CCDirector::sharedDirector()->getWinSize();
  CCLabelTTF* label = CCLabelTTF::labelWithString("callback 2 is called", "Arial", 20);
  label->setPosition(ccp(size.width/4 + 200, size.height/3));
  addChild(label);
}

step3:编译运行程序,我们就可以见到相应的效果,下面我截图给大家看:

这是程序运行后第一个出现的画面,通过点击next back 和 restart我们可以切换到另外的动作。

 

源代码下载地址:http://download.csdn.net/download/wen294299195/4525809

 

打赏

发表评论

电子邮件地址不会被公开。