cocos2dx里面有很多场景切换动画,使用起来也很简单,最简单的代码如下:
CCScene* newScene = new TransitionsTestScene(); |
newScene = CCTransitionProgressRadialCW::create(timeNeed, newScene); |
CCDirector::sharedDirector()->replaceScene(newScene); |
场景切换动画代码:
首先看下场景切换动画的继承关系:
class CC_DLL CCTransitionScene : public CCScene |
class CC_DLL CCTransitionSceneOriented : public CCTransitionScene |
class CC_DLL CCTransitionRotoZoom : public CCTransitionScene |
class CC_DLL CCTransitionJumpZoom : public CCTransitionScene |
可以看出,cocos2dx内部的场景切换动画继承自CCTransitionScene这个类,而CCTransitionScene这个类继承自CCScene,因此也是个场景类。
参考之前的【 笔记 】可以知道,CCTransitionScene在场景切换动画中担当了桥梁和动画播放的功能。
下面仔细分析下CCTransitionScene类的部分代码:
CCTransitionScene * CCTransitionScene::create( float t, CCScene *scene) |
CCTransitionScene * pScene = new CCTransitionScene(); |
if (pScene && pScene->initWithDuration(t,scene)) |
bool CCTransitionScene::initWithDuration( float t, CCScene *scene) |
CCAssert( scene != NULL, "Argument scene must be non-nil" ); |
m_pOutScene = CCDirector::sharedDirector()->getRunningScene(); |
m_pOutScene = CCScene::create(); |
CCAssert( m_pInScene != m_pOutScene, "Incoming scene must be different from the outgoing scene" ); |
void CCTransitionScene::sceneOrder() |
m_bIsInSceneOnTop = true ; |
void CCTransitionScene::draw() |
if ( m_bIsInSceneOnTop ) { |
void CCTransitionScene::finish() |
m_pInScene->setVisible( true ); |
m_pInScene->setPosition(ccp(0,0)); |
m_pInScene->setScale(1.0f); |
m_pInScene->setRotation(0.0f); |
m_pInScene->getCamera()->restore(); |
m_pOutScene->setVisible( false ); |
m_pOutScene->setPosition(ccp(0,0)); |
m_pOutScene->setScale(1.0f); |
m_pOutScene->setRotation(0.0f); |
m_pOutScene->getCamera()->restore(); |
this ->schedule(schedule_selector(CCTransitionScene::setNewScene), 0); |
void CCTransitionScene::setNewScene( float dt) |
this ->unschedule(schedule_selector(CCTransitionScene::setNewScene)); |
CCDirector *director = CCDirector::sharedDirector(); |
m_bIsSendCleanupToScene = director->isSendCleanupToScene(); |
director->replaceScene(m_pInScene); |
m_pOutScene->setVisible( true ); |
void CCTransitionScene::hideOutShowIn() |
m_pInScene->setVisible( true ); |
m_pOutScene->setVisible( false ); |
void CCTransitionScene::onEnter() |
CCDirector::sharedDirector()->getTouchDispatcher()->setDispatchEvents( false ); |
m_pOutScene->onExitTransitionDidStart(); |
void CCTransitionScene::onExit() |
CCDirector::sharedDirector()->getTouchDispatcher()->setDispatchEvents( true ); |
m_pInScene->onEnterTransitionDidFinish(); |
void CCTransitionScene::cleanup() |
if ( m_bIsSendCleanupToScene ) |
由于CCTransitionScene是个基类,真正的场景动画实现都是继承类实现的,这里分析几个场景切换动画的实现:
CCTransitionJumpZoom:
CCTransitionJumpZoom算是一个比较简单的动画实现,直接搞了一大堆动画:
CCTransitionJumpZoom* CCTransitionJumpZoom::create( float t, CCScene* scene) |
void CCTransitionJumpZoom::onEnter() |
CCTransitionScene::onEnter(); |
CCSize s = CCDirector::sharedDirector()->getWinSize(); |
m_pInScene->setScale(0.5f); |
m_pInScene->setPosition(ccp(s.width, 0)); |
m_pInScene->setAnchorPoint(ccp(0.5f, 0.5f)); |
m_pOutScene->setAnchorPoint(ccp(0.5f, 0.5f)); |
CCActionInterval *jump = CCJumpBy::create(m_fDuration/4, ccp(-s.width,0), s.width/4, 2); |
CCActionInterval *scaleIn = CCScaleTo::create(m_fDuration/4, 1.0f); |
CCActionInterval *scaleOut = CCScaleTo::create(m_fDuration/4, 0.5f); |
CCActionInterval *jumpZoomOut = (CCActionInterval*)(CCSequence::create(scaleOut, jump, NULL)); |
CCActionInterval *jumpZoomIn = (CCActionInterval*)(CCSequence::create(jump, scaleIn, NULL)); |
CCActionInterval *delay = CCDelayTime::create(m_fDuration/2); |
m_pOutScene->runAction(jumpZoomOut); |
CCCallFunc::create( this , callfunc_selector(CCTransitionScene::finish)), |
CCTransitionProgress:
CCTransitionProgress是一系列动画的父类,但是它也是CCTransitionScene的子类,它主要是实现一系列的进度条形式的动画。这里笔记下代码,看下它的实现方式:
class CC_DLL CCTransitionProgress : public CCTransitionScene |
void CCTransitionProgress::onEnter() |
CCTransitionScene::onEnter(); |
CCSize size = CCDirector::sharedDirector()->getWinSize(); |
CCRenderTexture *texture = CCRenderTexture::create(( int )size.width, ( int )size.height); |
texture->getSprite()->setAnchorPoint(ccp(0.5f,0.5f)); |
texture->setPosition(ccp(size.width/2, size.height/2)); |
texture->setAnchorPoint(ccp(0.5f,0.5f)); |
texture->clear(0, 0, 0, 1); |
m_pSceneToBeModified->visit(); |
if (m_pSceneToBeModified == m_pOutScene) |
CCProgressTimer *pNode = progressTimerNodeWithRenderTexture(texture); |
CCActionInterval* layerAction = (CCActionInterval*)CCSequence::create( |
CCProgressFromTo::create(m_fDuration, m_fFrom, m_fTo), |
CCCallFunc::create( this , callfunc_selector(CCTransitionProgress::finish)), |
pNode->runAction(layerAction); |
addChild(pNode, 2, kCCSceneRadial); |
在学习场景切换动画代码中,作者感觉这部分代码的实现比较怪异,每个新的场景动画都要复写父类的onEnter方法,而且要在复写的函数中调用父类的onEnter方法。作者的建议是CCTransitionScene类可以声明一个虚函数func专门供子类复写以实现不同的动画效果,CCTransitionScene可以在onEnter函数的最后调用func,这样子类就不需要复写onEnter方法,只需要复写func方法就可以了。一点点个人看法 呵呵~~
自定义的场景切换动画:
在特定的场景下我们可能想实现一些自定义的场景切换动画,来达到比较好的效果,这里作者笔记下一种实现方式:
首先看下cocos2dx的内部的场景切换动画,看下有没有相似的。比如作者这里想找一个类似于进度条的动画,但是进图条的样式作者想自定义,那么我们就可以先看下cocos2dx自带的进度条切换动画是如何实现的,然后我们就可以自己写一个类,继承CCTransitionScene来实现。代码如下:
头文件:
#ifndef _CUSTOMTRANSPROGRESSINOUT_H_ |
#define _CUSTOMTRANSPROGRESSINOUT_H_ |
class CustomTransProgressInOut : public CCTransitionScene |
static CustomTransProgressInOut* create( float t, CCScene* scene, const char *pStencilFileName, bool direction); |
virtual void sceneOrder(); |
#endif /* _CUSTOMTRANSPROGRESSINOUT_H_ */ |
cpp文件:
#include "CustomTransProgressInOut.h" |
CustomTransProgressInOut* CustomTransProgressInOut::create( float t, CCScene* scene, const char *pStencilFileName, bool direction) |
CustomTransProgressInOut* pScene = new CustomTransProgressInOut(); |
if (pScene && pScene->initWithDuration(t, scene)) |
pScene->m_pStencil = CCSprite::create(pStencilFileName); |
pScene->m_bDirection = direction; |
void CustomTransProgressInOut::sceneOrder() |
m_bIsInSceneOnTop = !m_bDirection; |
void CustomTransProgressInOut::onEnter() |
CCTransitionScene::onEnter(); |
CCSize size = CCDirector::sharedDirector()->getWinSize(); |
CCRenderTexture *texture = CCRenderTexture::create(( int )size.width, ( int )size.height); |
texture->getSprite()->setAnchorPoint(ccp(0.5f,0.5f)); |
texture->setPosition(ccp(size.width/2, size.height/2)); |
texture->setAnchorPoint(ccp(0.5f,0.5f)); |
texture->clear(0, 0, 0, 1); |
CCClippingNode *clippingNode = CCClippingNode::create(); |
clippingNode->setStencil(m_pStencil); |
CCSprite *background = CCSprite::createWithTexture(texture->getSprite()->getTexture()); |
background->setFlipY( true ); |
clippingNode->addChild(background); |
clippingNode->setAlphaThreshold(GLfloat(0.5f)); |
clippingNode->setAnchorPoint(ccp(0.5,0.5)); |
clippingNode->setPosition(ccp(size.width/2, size.height/2)); |
this ->addChild(clippingNode, 2, 9999); |
CCSize orgSize = m_pStencil->getContentSize(); |
CCSize minSize = CCSizeMake(2,2); |
float maxScale = maxSize.height * 1.0f / orgSize.height * 2.0f; |
float minScale = minSize.height * 1.0f / orgSize.height; |
m_pStencil->setScale(minScale); |
CCSequence* layerAction = CCSequence::create |
CCScaleTo::create(m_fDuration, maxScale), |
CCCallFunc::create( this , callfunc_selector(CustomTransProgressInOut::finish)), |
m_pStencil->runAction(layerAction); |
void CustomTransProgressInOut::onExit() |
this ->removeChildByTag(9999); |
CCTransitionScene::onExit(); |
测试代码:
CCTransitionScene* createTransition( int nIndex, float t, CCScene* s) |
return CustomTransProgressInOut::create(t,s, "stencil.png" , true ); |
效果截图:
stencil文件:
效果文件:

发表评论