Cocos2d-x人物動作類實(shí)例
我們玩的游戲一般都可以看到精靈的運(yùn)動,游戲的世界就是一個(gè)運(yùn)動的世界,而所有的這些動作都可以分為一些基本的動作和動作的組合,今天就來學(xué)習(xí)一下動作類CCAction,首先看一下類之間的繼承關(guān)系。

CCAction類下派生了三個(gè)動作類,執(zhí)行動作的類是CCNode以及它的子類,通過函數(shù)runAction()來執(zhí)行動作,其中CCFiniteTimeAction之下是常用的瞬時(shí)動作和延時(shí)動作。動作從本質(zhì)上來說就是改變節(jié)點(diǎn)的屬性,瞬時(shí)動作就是改變這些屬性不需要時(shí)間,瞬時(shí)就完成了,而延時(shí)動作改變這些屬性需要一些時(shí)間,可以通過參數(shù)來設(shè)置這個(gè)時(shí)間,下面是瞬時(shí)動作和延時(shí)動作的例子,解釋看源代碼。點(diǎn)擊下圖查看效果。

bool HelloWorld::init()
{
bool bRet = false;
do
{
CC_BREAK_IF(! CCLayer::init());
//創(chuàng)建一個(gè)精靈
CCSprite * sprite = CCSprite::create("image.png");
sprite->setPosition(ccp(240,160));
//最后一個(gè)參數(shù)是精靈的tag,以便在眾多的子節(jié)點(diǎn)中,通過getChildByTag()找到該節(jié)點(diǎn)
this->addChild(sprite,0,0);
//創(chuàng)建菜單
CCMenuItemFont * fontMenu1 = CCMenuItemFont::create("start");
CCMenuItemFont * fontMenu2 = CCMenuItemFont::create("stop");
//和move函數(shù)相互綁定
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;
//瞬時(shí)動作CCPlace,改變了精靈的坐標(biāo),可以用sprite->setPosition(ccp(60,160))代替,但寫成動作可以加入到動作序列中
CCPlace * action1 = CCPlace::create(ccp(60,160));
//瞬時(shí)動作,使精靈做X軸的翻轉(zhuǎn)
CCFlipX * action2 = CCFlipX::create(true);
if(toggleMenu->getSelectedIndex() == 1)
{
//通過runAction精靈執(zhí)行動作
sprite->runAction(action2);
}
else if(toggleMenu->getSelectedIndex() == 0)
{
}
}
void HelloWorld::move(CCObject* pSender)
{
//通過tag獲得添加的精靈
CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;
//延時(shí)動作,第一個(gè)參數(shù)是執(zhí)行動作所需要的時(shí)間,moveTo是絕對的,就是移動到哪個(gè)坐標(biāo),而moveBy是相對的
//傳入的ccp(10,0)是一個(gè)向量,精靈沿著x軸移動了10個(gè)像素
CCMoveTo * moveTo = CCMoveTo::create(2.0,ccp(240,180));
CCMoveBy * moveBy = CCMoveBy::create(2.0,ccp(10,0));
//rotate按照一定的角度旋轉(zhuǎn),to強(qiáng)調(diào)的是結(jié)果,現(xiàn)在是0度,會旋轉(zhuǎn)到90度,如果現(xiàn)在是90度,還是會在90度
CCRotateTo * rotateTo = CCRotateTo::create(2.0,90);
//by強(qiáng)調(diào)旋轉(zhuǎn)的相對角度,不論現(xiàn)在多少度都會旋轉(zhuǎn)90度,以to和by結(jié)尾的動作類都是相同的道理
CCRotateBy * rotateBy = CCRotateBy::create(2.0,90);
if(toggleMenu->getSelectedIndex() == 1)
{
//通過runAction精靈執(zhí)行動作
//sprite->runAction(moveTo);
//sprite->runAction(moveBy);
sprite->runAction(rotateBy);
}
else if(toggleMenu->getSelectedIndex() == 0)
{
}
}
以by結(jié)尾的延時(shí)動作都可以通過reverse()獲得它的反動作。
void HelloWorld::move(CCObject* pSender)
{
//通過tag獲得添加的精靈
CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;
//第二個(gè)參數(shù)是跳躍的向量,第三個(gè)參數(shù)是跳躍的高度,第四個(gè)參數(shù)是跳躍的次數(shù)
CCJumpBy * jumpBy = CCJumpBy::create(2.0,ccp(100,30),50,4);
//以by結(jié)尾的延時(shí)動作都可以通過reverse()獲得它的反動作
CCActionInterval * jumpBack = jumpBy->reverse();
if(toggleMenu->getSelectedIndex() == 1)
{
//通過runAction精靈執(zhí)行動作
sprite->runAction(jumpBy);
}
else if(toggleMenu->getSelectedIndex() == 0)
{
sprite->runAction(jumpBack);
}
}
延時(shí)動作中還有倆個(gè)重復(fù)動作的函數(shù),就是重復(fù)不斷的執(zhí)行某一個(gè)動作,看下他們的繼承關(guān)系。
下面是實(shí)現(xiàn)的源代碼。
void HelloWorld::move(CCObject* pSender)
{
//通過tag獲得添加的精靈
CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;
//第一個(gè)參數(shù)傳入重復(fù)的動作,第二個(gè)參數(shù)傳入重復(fù)的次數(shù)
CCRepeat * repeat = CCRepeat::create(rotateBy,4);
//永遠(yuǎn)重復(fù)執(zhí)行一個(gè)動作
CCRepeatForever * repeatForever = CCRepeatForever::create(rotateBy);
if(toggleMenu->getSelectedIndex() == 1)
{
//通過runAction精靈執(zhí)行動作
sprite->runAction(repeatForever);
}
else if(toggleMenu->getSelectedIndex() == 0)
{
}
}
下面再列舉一下基本常用的瞬時(shí)動作和延續(xù)動作。
瞬時(shí)動作:
放置Place:效果類似于 setPosition = ccp(x, y)。
隱藏Hide:效果類似于setVisible:false。
顯示Show:效果類似于setVisible:true。
可見切換:ToggleVisibility。
延時(shí)動作:
移動到CCMoveTo
移動CCMoveBy
跳躍到CCJumpTo設(shè)置終點(diǎn)位置和跳躍的高度和次數(shù)。
跳躍CCJumpBy設(shè)置終點(diǎn)位置和跳躍的高度和次數(shù)。
貝塞爾CCBezierBy支持 3 次貝塞爾曲線:P0-起點(diǎn),P1-起點(diǎn)切線方向,P2-終點(diǎn)切線方向,P3-終點(diǎn)。
放大到CCScaleTo設(shè)置放大倍數(shù),是浮點(diǎn)型。
放大CCScaleBy
旋轉(zhuǎn)到CCRotateTo
旋轉(zhuǎn)CCRotateBy
閃爍CCBlink設(shè)定閃爍次數(shù)
色調(diào)變化到CCTintTo
色調(diào)變換CCTintBy
變暗到CCFadeTo
由無變亮CCFadeIn
由亮變無CCFadeOut
每個(gè)函數(shù)的具體用法請大家自行試驗(yàn)。
接下來說一下同步動作序列和順序動作序列。同步動作序列,就是幾個(gè)動作同時(shí)執(zhí)行,順序動作序列,就是傳入的幾個(gè)動作按照順序順序執(zhí)行。以下是他們的繼承關(guān)系圖。
接下來看一下實(shí)現(xiàn)的源代碼
void HelloWorld::move(CCObject* pSender)
{
//通過tag獲得添加的精靈
CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;
//創(chuàng)建如下幾個(gè)動作
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);
//同步動作序列,傳入的幾個(gè)動作同時(shí)執(zhí)行,執(zhí)行的整個(gè)時(shí)間是最長的一個(gè)動作的執(zhí)行時(shí)間,參數(shù)類型是CCFiniteTimeAction
//傳入的動作(動作的實(shí)質(zhì)就是改變節(jié)點(diǎn)的屬性)所影響的屬性不要有沖突
CCSpawn * spawn = CCSpawn::create(move,rotate,NULL);
CCSpawn * spawnBack = CCSpawn::create(moveBack,rotateBack,NULL);
//順序動作序列,傳入的幾個(gè)動作按照傳入的順序順序執(zhí)行,執(zhí)行的整體時(shí)間是所有動作的時(shí)間之和
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的另外來個(gè)子類,CCFollow實(shí)現(xiàn)鏡頭跟隨的效果,類似于我們在橫版過關(guān)游戲中看到的人物永遠(yuǎn)在屏幕中間,而背景在移動,不過它們的實(shí)現(xiàn)具體是不是靠這個(gè)類就不知道了。CCSpeed可以實(shí)現(xiàn)快進(jìn)和慢放的效果,就是改變了執(zhí)行的速度。以下是源代碼。
void HelloWorld::move(CCObject* pSender)
{
//通過tag獲得添加的精靈
CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;
//創(chuàng)建如下幾個(gè)動作
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);
//同步動作序列,傳入的幾個(gè)動作同時(shí)執(zhí)行,執(zhí)行的整個(gè)時(shí)間是最長的一個(gè)動作的執(zhí)行時(shí)間,參數(shù)類型是CCFiniteTimeAction
//傳入的動作(動作的實(shí)質(zhì)就是改變節(jié)點(diǎn)的屬性)所影響的屬性不要有沖突
CCSpawn * spawn = CCSpawn::create(move,rotate,NULL);
CCSpawn * spawnBack = CCSpawn::create(moveBack,rotateBack,NULL);
//順序動作序列,傳入的幾個(gè)動作按照傳入的順序順序執(zhí)行,執(zhí)行的整體時(shí)間是所有動作的時(shí)間之和
CCSequence * sequence = CCSequence::create(move,rotate,flip,NULL);
CCSequence * sequenceBack = CCSequence::create(moveBack,rotateBack,flip->reverse(),NULL);
//CCFollow實(shí)現(xiàn)一個(gè)節(jié)點(diǎn)跟隨一個(gè)節(jié)點(diǎn)運(yùn)動,傳入的參數(shù)是要跟隨的節(jié)點(diǎn)
CCFollow * follow = CCFollow::create(sprite);
//執(zhí)行這個(gè)動作的是要跟隨的節(jié)點(diǎn),一般是層,效果累世于橫版過關(guān)游戲中的場景
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的實(shí)現(xiàn),在上述代碼的基礎(chǔ)上做了一點(diǎn)修改。
void HelloWorld::move(CCObject* pSender)
{
//通過tag獲得添加的精靈
CCSprite * sprite = (CCSprite *)this->getChildByTag(0);
CCMenuItemToggle * toggleMenu = (CCMenuItemToggle *)pSender;
//創(chuàng)建如下幾個(gè)動作
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);
//同步動作序列,傳入的幾個(gè)動作同時(shí)執(zhí)行,執(zhí)行的整個(gè)時(shí)間是最長的一個(gè)動作的執(zhí)行時(shí)間,參數(shù)類型是CCFiniteTimeAction
//傳入的動作(動作的實(shí)質(zhì)就是改變節(jié)點(diǎn)的屬性)所影響的屬性不要有沖突
CCSpawn * spawn = CCSpawn::create(move,rotate,NULL);
CCSpawn * spawnBack = CCSpawn::create(moveBack,rotateBack,NULL);
//順序動作序列,傳入的幾個(gè)動作按照傳入的順序順序執(zhí)行,執(zhí)行的整體時(shí)間是所有動作的時(shí)間之和
CCSequence * sequence = CCSequence::create(move,rotate,flip,NULL);
CCSequence * sequenceBack = CCSequence::create(moveBack,rotateBack,flip->reverse(),NULL);
//CCFollow實(shí)現(xiàn)一個(gè)節(jié)點(diǎn)跟隨一個(gè)節(jié)點(diǎn)運(yùn)動,傳入的參數(shù)是要跟隨的節(jié)點(diǎn)
CCFollow * follow = CCFollow::create(sprite);
//執(zhí)行這個(gè)動作的是要跟隨的節(jié)點(diǎn),一般是層,效果累世于橫版過關(guān)游戲中的場景
this->runAction(follow);
//CCSpeed分裝了一個(gè)動作類,第二個(gè)參數(shù)是要改變的速度的倍數(shù)
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家族類的使用方法,它們也是一個(gè)動作類,一般用在順序動作序列中執(zhí)行的最后一個(gè)動作,目的是調(diào)用一個(gè)函數(shù),來完成一些功能。以下是這些類的繼承關(guān)系。
接下來貼上源代碼,注釋是對各個(gè)類的使用的詳細(xì)講解。
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);
//創(chuàng)建一個(gè)菜單,添加一個(gè)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);
//創(chuàng)建延時(shí)動作
CCRotateBy * rotate = CCRotateBy::create(2.0,3*360);
//CCCallFunc,為這個(gè)動作綁定一個(gè)函數(shù),執(zhí)行這個(gè)動作的時(shí)候會調(diào)用這個(gè)函數(shù),創(chuàng)建以下四個(gè)動作的時(shí)候使用了不同的選擇器,但名字和各個(gè)動作有關(guān)
CCCallFunc * func = CCCallFunc::create(this,callfunc_selector(HelloWorld::show));
//CCCallFuncN(N就是node的意思),與上邊不同的是,綁定的函數(shù)需要一個(gè)參數(shù),這個(gè)傳入的參數(shù)就是執(zhí)行這個(gè)動作的節(jié)點(diǎn)
CCCallFuncN * funcN = CCCallFuncN::create(this,callfuncN_selector(HelloWorld::remove));
int num = 10;
//CCCallFuncND(D就是data的意思),這次綁定的函數(shù),不僅需要綁定動作的節(jié)點(diǎn)作為參數(shù)傳遞,還帶了一個(gè)void *類型的參數(shù),代表可以是任何類型
CCCallFuncND *funcND = CCCallFuncND::create(this,callfuncND_selector(HelloWorld::showData),(void *)num);
CCSprite * sprite2 = CCSprite::create("image2.png");
//CCCallFuncO(O就是object的意思)這次需要傳入的參數(shù)是CCObject *類型的
CCCallFuncO * funcO = CCCallFuncO::create(this,callfuncO_selector(HelloWorld::showSprite),sprite2);
//創(chuàng)建順序動作序列
//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);
}
//以下函數(shù)不要忘記在頭文件中聲明,注意每個(gè)函數(shù)的參數(shù)
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()函數(shù)獲得執(zhí)行動作的精靈,而是使用remove傳來的參數(shù)
CCSprite * sprite = (CCSprite *)node;
//true表示sprite不僅會移除,而且這個(gè)節(jié)點(diǎn)上的所有操作和回調(diào)都將刪除
sprite->removeFromParentAndCleanup(true);
//通過以下的方法可以實(shí)現(xiàn)相同的效果,只是函數(shù)執(zhí)行的對象不同
//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);
}
- Cocos2d-x保存用戶游戲數(shù)據(jù)CCUserDefault類使用實(shí)例
- Cocos2d-x中背景音樂和音效使用實(shí)例
- Cocos2d-x中獲取系統(tǒng)時(shí)間和隨機(jī)數(shù)實(shí)例
- Cocos2d-x觸摸事件實(shí)例
- php中Swoole的熱更新實(shí)現(xiàn)代碼實(shí)例
- React Native 實(shí)現(xiàn)熱更新并自動簽名打包功能
- nodemon實(shí)現(xiàn)Typescript項(xiàng)目熱更新的示例代碼
- 解決vuecli3.0熱更新失效的問題
- 詳解webpack 熱更新優(yōu)化
- 全面講解CocosCreator熱更新
相關(guān)文章
C++ 基礎(chǔ)教程之虛函數(shù)實(shí)例代碼詳解
虛函數(shù)在 c++ 的繼承體系中是一個(gè)非常重要概念,讓我們可以在子類中復(fù)寫父類的方法。這篇文章主要介紹了C++ 基礎(chǔ)教程之虛函數(shù)實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2020-02-02
C語言實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
利用C++的基本算法實(shí)現(xiàn)十個(gè)數(shù)排序
以下是對利用C++的基本算法實(shí)現(xiàn)十個(gè)數(shù)排序的代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-10-10
C++ OpenCV實(shí)戰(zhàn)之網(wǎng)孔檢測的實(shí)現(xiàn)
這篇文章主要介紹了如何利用C++和OpenCV實(shí)現(xiàn)網(wǎng)孔檢測,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)OpenCV有一定幫助,感興趣的小伙伴可以了解一下2022-05-05





















