您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x学习笔记(7)--动作(Actions)

2012-08-08 23:39 399 查看
cocos2d-x学习笔记(7)--动作(Actions)
本文出自http://www.wenbanana.com稻草人博客,欢迎访问!

动作在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: