cocos2dx CCTransition各个子项

1、CCTransitionProgress

该类继承了CCTransitionScene,并且有两个子类:实现了顺时针跟逆时针的进度切屏动作。

复制代码
void CCTransitionProgress::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);
    texture->begin();
    m_pSceneToBeModified->visit(); // 用RenderTexture截屏,将当前的显示的scene截屏。具体可以看RenderTexture的使用方法,这里不作具体说明。
    texture->end();

    hideOutShowIn(); // 已经把out的截屏,则可以把它隐藏掉了
    // 将截完的图片从texture取出来放到ProgressTimer
    CCProgressTimer *pNode = progressTimerNodeWithRenderTexture(texture);//两个子类重写了该方法,实现顺时针或者逆时针的操作,其实在本类,该函数更应该使用纯虚函数。

    CCActionInterval* layerAction = (CCActionInterval*)CCSequence::create(
        CCProgressFromTo::create(m_fDuration, m_fFrom, m_fTo), // 这里使用的是从100到0,是因为刚开始是全部遮挡住的所以是100,最终我们需要的是将out层消失,所以最终是需要0
        CCCallFunc::create(this, callfunc_selector(CCTransitionProgress::finish)), 
        NULL);
    // run the blend action
    pNode->runAction(layerAction);

    // 这里将pNode放到上一层,确保能够顶层显示(out的精灵图片)
    addChild(pNode, 2, kCCSceneRadial);
}
复制代码

类似于进度切换的,如果需要另外的风格,则可以参照对应的子类进行实现:CCTransitionProgressRadialCCW,CCTransitionProgressRadialCW;比如这里抄CCTransitionProgressRadialCW自己重写一个

复制代码
class CCTransitionProgressRadialME : public CCTransitionProgress
{
public:
    static CCTransitionProgressRadialME* create(float t, CCScene* scene) {
        CCTransitionProgressRadialME* pScene = new CCTransitionProgressRadialME();
        if (pScene && pScene->initWithDuration(t, scene))
        {
            pScene->autorelease();
            return pScene;
        }
        CC_SAFE_DELETE(pScene);
        return NULL;
    }
protected:
    virtual CCProgressTimer* progressTimerNodeWithRenderTexture(CCRenderTexture* texture) {
        CCSize size = CCDirector::sharedDirector()->getWinSize();

        CCProgressTimer* pNode = CCProgressTimer::create(texture->getSprite());

        // but it is flipped upside down so we flip the sprite
        pNode->getSprite()->setFlipY(true);
        pNode->setType(kCCProgressTimerTypeRadial);

        //    Return the radial type that we want to use
        pNode->setReverseDirection(false);
        pNode->setPercentage(100);
        pNode->setPosition(ccp(size.width / 2, size.height / 2));
        pNode->setAnchorPoint(ccp(0.5f, 0.5f));

        return pNode;
    }

};
View Code
复制代码

代码中:pNode->getSprite()->setFlipY(true); 是因为opengl是以左下角为0坐标。而正常的图片以左上角为0坐标。比如正常的图片的矩阵

123

456

789

但是opengl从左下角开始扫描则存储的图片矩阵就成为了

789

456

123

所以这里需要进行setFlipY的操作。

具体的可以实现自己想要的功能。

 

2、CCTransitionCrossFade

复制代码
    inTexture->begin();
    m_pInScene->visit();
    inTexture->end();

    outTexture->begin();
    m_pOutScene->visit();
    outTexture->end();

    ccBlendFunc blend1 = {GL_ONE, GL_ONE};
    ccBlendFunc blend2 = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA};

    // set blendfunctions
    inTexture->getSprite()->setBlendFunc(blend1);
    outTexture->getSprite()->setBlendFunc(blend2);    

    // add render textures to the layer
    layer->addChild(inTexture);
    layer->addChild(outTexture);

    // initial opacity:
    inTexture->getSprite()->setOpacity(255);
    outTexture->getSprite()->setOpacity(255);

    // create the blend action
    CCAction* layerAction = CCSequence::create
    (
        CCFadeTo::create(m_fDuration, 0),
        CCCallFunc::create(this, callfunc_selector(CCTransitionScene::hideOutShowIn)),
        CCCallFunc::create(this, callfunc_selector(CCTransitionScene::finish)),
        NULL
    );
    outTexture->getSprite()->runAction( layerAction );
    addChild(layer, 2, kSceneFade);
复制代码

由于是图片混淆的方式进行切换。所以需要两张图片,这里将inscene跟outscene都获取出图片然后进行渐变的操作。

in图片保持原样不需要进行额外的操作,所以sec_alpha跟dest_alpha的因子都设置成GL_ONE

out图片需要从不透明渐变成全透明。{GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA};该参数的意思是:

假设我们将in图片上面的某个点的颜色设置为dest_col,将out图片对应位置的点的颜色设置为src_col

则通过那两个参数的操作之后的颜色则为:result_col = src_col * SRC_ALPHA + dest_col * (1 - SRC_ALPHA) 当src_alpha从1 变成0 之后就变成全透明了。这里src_alpha的值是x / 255.0f ;x的取值范围是0~255

这里先将x设置成255,即:outTexture->getSprite()->setOpacity(255);

接下去的操作就是添加action:CCFadeTo::create(m_fDuration, 0) ,将to设置为0,即最终的src_alpha设置为0

复制代码
bool CCFadeTo::initWithDuration(float duration, GLubyte opacity)
{
        m_toOpacity = opacity; // 初始化为0


void CCFadeTo::startWithTarget(CCNode *pTarget)
{
    CCRGBAProtocol *pRGBAProtocol = dynamic_cast<CCRGBAProtocol*>(pTarget);
    if (pRGBAProtocol)
    {
        m_fromOpacity = pRGBAProtocol->getOpacity(); // 将刚才设置的setOpacity(255)设置给from


void CCFadeTo::update(float time)
{
    CCRGBAProtocol *pRGBAProtocol = dynamic_cast<CCRGBAProtocol*>(m_pTarget);
    if (pRGBAProtocol)
    {
        pRGBAProtocol->setOpacity((GLubyte)(m_fromOpacity + (m_toOpacity - m_fromOpacity) * time)); // 从255到0的过程
复制代码

如上是fadeto的action实现过程。

 

接下去调用finish的action函数。会调用:director->replaceScene(m_pInScene);将inscene替换进来,替换完成之后本身的CCTransitionScene会被调用OnExit()函数,

void CCTransitionCrossFade::onExit()
{
    // remove our layer and release all containing objects 
    this->removeChildByTag(kSceneFade, false);

则刚才操作的layer会被remove掉

 

3、不大理解的CCOrbitCamera

顾名思义Camera就是以相机的视角来显示

该action是跟camera有关的。当前处于3D的时候如果图片不在正中间,所显示的效果跟期望的效果可能会有差(网上看的)

如果要让它没差,则需要将视角变成2D的:CCDirector::sharedDirector()->setProjection(ccDirectorProjection::kCCDirectorProjection2D);

图片沿y轴旋转90度:CCOrbitCamera* cameraAction1 = CCOrbitCamera::create(5.0f, 1, 0, 0, -90, 0, 0);

图片沿x轴旋转90度:CCOrbitCamera* cameraAction2 = CCOrbitCamera::create(5.0f, 1, 0, 0, 90, 90, 0);

旋转度数的多少是deltaAngles这个参数决定的。

注意:最好操作都是在90度以内的

复制代码
void CCOrbitCamera::update(float dt)
{
    float r = (m_fRadius + m_fDeltaRadius * dt) * CCCamera::getZEye();//目前知道的只有正负值之分负值为原图片的左右镜像
    float za = m_fRadZ + m_fRadDeltaZ * dt;//原来的z的弧度再加上delta的弧度
    float xa = m_fRadX + m_fRadDeltaX * dt;//原来的x的弧度再加上delta的弧度

    float i = sinf(za) * cosf(xa) * r + m_fCenterXOrig;//当xa为90度的时候cos(xa)=0即i为0,j为1
    float j = sinf(za) * sinf(xa) * r + m_fCenterYOrig;//所以当xa是否为90度即angleX决定了沿x轴旋转还是沿y轴旋转
    float k = cosf(za) * r + m_fCenterZOrig;//如果deltaAngleZ为0时,如果za为0或者90度会导致ij为0或者k为0从而整个页面都不动

    m_pTarget->getCamera()->setEyeXYZ(i,j,k);
}
复制代码

 

posted @   LCAC  阅读(218)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示