【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用

时间:2022-05-03 11:43:17

本系列学习教程使用的是cocos2d-x-2.1.4(最新版为3.0alpha0-pre) ,PC开发环境Windows7,C++开发环境VS2010





一、摄像机动作


      在前面我们学习过了摄像机类CCCamera,动作中也有一个摄像机类CCOrbitCamera,它是摄像机环绕屏幕中心

转所形成的动作。

 

1、首先看CCOrbitCamera的使用。

 

CCOrbitCamera::create(float t,float radius,float deltaRadius,float angleZ,float deltaAngleZ,float angleX,float deltaAngleX)

作用:创建一个球面坐标轨迹进行旋转的动作。

参数1:旋转轨迹所需的时间。

参数2:起始半径。

参数3:半径差。

参数4:起始z角。

参数5:旋转z角差。

参数6:起始x角。

参数7:旋转x角差。

 

 

2、示例代码如下所示。


首先新建Cocos2D-X项目,取名为“CCActionOrbit”,然后在HelloWorldScene.cpp文件的init函数中添加如下代码。

bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! CCLayer::init());

       //获得尺寸大小
		CCSize s = CCDirector::sharedDirector()->getWinSize();

		//创建精灵
        CCSprite* m_grossini = CCSprite::create("grossini.png");
		CCSprite* m_tamara = CCSprite::create("grossinis_sister1.png");
		CCSprite* m_kathia = CCSprite::create("grossinis_sister2.png");

		//设置精灵的位置
		m_grossini->setPosition( ccp(s.width/2, s.height/2));
		m_tamara->setPosition( ccp(s.width/4, s.height/2));
        m_kathia->setPosition( ccp(3 * s.width/4, s.height/2));
       
		//添加精灵到图层
		addChild(m_grossini, 1);
		addChild(m_tamara, 2);
		addChild(m_kathia, 3);
      
		CCActionInterval*  orbit1 = CCOrbitCamera::create(2,1, 0, 0, 180, 0, 0);
		CCSequence*  action1 = CCSequence::create(
        orbit1,
        orbit1->reverse(),
        NULL);

		CCActionInterval*  orbit2 = CCOrbitCamera::create(2,1, 0, 0, 180, -45, 0);
		CCSequence*  action2 = CCSequence::create(
        orbit2,
        orbit2->reverse(),
        NULL);

		CCActionInterval*  orbit3 = CCOrbitCamera::create(2,1, 0, 0, 180, 90, 0);
		CCSequence*  action3 = CCSequence::create(
        orbit3,
        orbit3->reverse(),
        NULL);
	
		m_kathia->runAction(CCRepeatForever::create(action1));
		m_tamara->runAction(CCRepeatForever::create(action2));
		m_grossini->runAction(CCRepeatForever::create(action3));

		CCActionInterval*  move = CCMoveBy::create(3, ccp(100,-100));
		CCActionInterval*  move_back = move->reverse();
		CCSequence*  seq = CCSequence::create(move, move_back, NULL);
		CCAction*  rfe = CCRepeatForever::create(seq);

		m_kathia->runAction(rfe);
		m_tamara->runAction((CCAction*)(rfe->copy()->autorelease()));
		m_grossini->runAction((CCAction*)(rfe->copy()->autorelease()));

        bRet = true;
    } while (0);

    return bRet;
}


旋转的坐标描述采用了球坐标。球坐标采用球面半径、与x轴夹角、与z轴夹角这几个值来描述坐标点。如下图所示。

【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用

 

注意 :在使用摄像机旋转时,如果正在旋转的这个节点后面还有其它节点的话,可能会出现旋转的节点只有一部

分显示出来的这种情况。这时只需要关闭OpenGL的深度检测,获得导演类并调用setDepthTest设置为false即可,如

下面的代码所示:CCDirector::sharedDirector()->setDepthTest(false)。

 

3、示例效果图。

 

【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用                        【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用



 

二、基本样条动作


    在游戏中,有时会希望使用一些非常规轨迹能描述的运动轨迹,希望只是“告诉”游戏对象几个离散的点,游戏对

象就可以根据这些离散的点模拟出相应的路径。当然,有相应的公式模拟出这条曲线,那就是基本样条。Cocos2D-X

中有沿基本样条路径移动动作类CCCardinalSplineTo和其子类实现这样的功能,它的继承关系如下图所示。

【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用


 

      其中CCCardinalSplineTo和CCCardinalSplineBy的关系与之前以“To”和“By”结尾的类类似,CCCatmullRomTo

CCCatmullRomBy也是这样的。它们都是采用基本样条的公式;不同的是,CCCatmullRomTo和CCCatmullRomBy

拉力系数是0.5,而之前的CCCardinalSplineTo和CCCardinalSplineBy的拉力系数是可以自定义的。


1、画基本样条路径

 

<1> 首先来看CCCardinalSplineTo和CCCardinalSplineBy的使用。

① CCCardinalSplineTo::create(float duration,CCPointArray * points,float tension)

作用:创建一个样条曲线轨迹的动作。

参数1:完成轨迹所需的时间。

参数2:控制点的坐标数组。

参数3:拟合度。其值=0时,路径最柔和。

 

② CCCardinalSplineBy::create(float duration,CCPointArray * points,float tension)

作用:创建一个样条曲线轨迹的动作。

参数1:完成轨迹所需的时间。

参数2:控制点的坐标数组。

参数3:拟合度。其值=0时,路径最柔和。

CCCardinalSplineBy支持reverse()函数,可以获取其反向动作。

 

<2> 示例代码如下所示。


首先新建Cocos2D-X项目,取名为“CCActionSpline”,然后在HelloWorldScene.cpp文件的init函数中添加如下代码。

bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! CCLayer::init());

         //获得尺寸大小
		CCSize s = CCDirector::sharedDirector()->getWinSize();

		//创建精灵
		CCSprite* m_tamara = CCSprite::create("grossinis_sister1.png");
		CCSprite* m_kathia = CCSprite::create("grossinis_sister2.png");

		//设置精灵的位置
		m_kathia->setPosition( ccp(s.width/3, s.height/2));
        m_tamara->setPosition( ccp(2*s.width/3, s.height/2));
       
		//添加精灵到图层		
		addChild(m_tamara, 2);
		addChild(m_kathia, 3);

		CCPointArray *array = CCPointArray::create(20);
    
		array->addControlPoint(ccp(0, 0));
		array->addControlPoint(ccp(s.width/2-30, 0));
		array->addControlPoint(ccp(s.width/2-30, s.height-80));
		array->addControlPoint(ccp(0, s.height-80));
		array->addControlPoint(ccp(0, 0));
    
		//
		// sprite 1 (By)
		//
		// Spline with no tension (tension==0)
		//
    
		CCCardinalSplineBy *action = CCCardinalSplineBy::create(3, array, 0);
		CCActionInterval *reverse = action->reverse();
    
		CCFiniteTimeAction *seq = CCSequence::create(action, reverse, NULL);
    
		m_tamara->setPosition(ccp(50, 50));
		m_tamara->runAction(seq);
    
		//
		// sprite 2 (By)
		//
		// Spline with high tension (tension==1)
		//
    
		CCCardinalSplineBy *action2 = CCCardinalSplineBy::create(3, array, 1);
		CCActionInterval *reverse2 = action2->reverse();
    
		CCFiniteTimeAction *seq2 = CCSequence::create(action2, reverse2, NULL);
    
		m_kathia->setPosition(ccp(s.width/2, 50));
		m_kathia->runAction(seq2);
   
		array->retain();

        bRet = true;
    } while (0);

    return bRet;
}

    首先定义一个点数组,把路径的点放入数组中。创建基本样条动作时,三个参数分别是动作时间、点数组、拉力系

数。 CCCardinalSplineTo和CCCardinalSplineBy的区别是,由于第一个是绝对的,第二个是相对的,第二个定义点

数组的时候,第一个点最好设置为(0,0),否则起始点会被忽略掉。可以重写布景层的draw函数来把路径画出来。

<3> 示例效果图。

【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用             【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用

 

 

2、画Catmull-Rom样条路径

 

<1> 首先来看CCCatmullRomToCCCatmullRomBy的使用。

CCCatmullRomTo::create(float dt,CCPointArray * points)

作用:创建一个样条插值轨迹。

参数1:完成轨迹的时间。

参数2:控制点的坐标数组。

 

 CCCatmullRomBy::create(float dt,CCPointArray * points)

作用:创建一个样条插值轨迹。

参数1:完成轨迹的时间。

参数2:控制点的坐标数组。

CCCatmullRomBy支持reverse()函数,可以获取其反向动作。

 

 

<2> 示例代码如下所示。


     首先新建Cocos2D-X项目,取名为“MyCCActionCatmullRom”,然后在HelloWorldScene.cpp文件的init函数中添加如下代码。

bool HelloWorld::init()
{
    bool bRet = false;
    do 
    {
        CC_BREAK_IF(! CCLayer::init());

        //获得尺寸大小
		CCSize s = CCDirector::sharedDirector()->getWinSize();

		//创建精灵
		CCSprite* m_tamara = CCSprite::create("grossinis_sister1.png");
		CCSprite* m_kathia = CCSprite::create("grossinis_sister2.png");

		//设置精灵的位置
		m_kathia->setPosition( ccp(s.width/3, s.height/2));
		m_tamara->setPosition(ccp(50, 50));
       
		//添加精灵到图层		
		addChild(m_tamara, 2);
		addChild(m_kathia, 3);

		
    
		CCPointArray *array = CCPointArray::create(20);
    
		array->addControlPoint(ccp(0, 0));
		array->addControlPoint(ccp(80, 80));
		array->addControlPoint(ccp(s.width - 80, 80));
		array->addControlPoint(ccp(s.width - 80, s.height - 80));
		array->addControlPoint(ccp(80, s.height - 80));
		array->addControlPoint(ccp(80, 80));
		array->addControlPoint(ccp(s.width / 2, s.height / 2));
    
		CCCatmullRomBy *action = CCCatmullRomBy::create(3, array);
		CCFiniteTimeAction *reverse = action->reverse();
    
		CCFiniteTimeAction *seq = CCSequence::create(action, reverse, NULL);
    
		m_tamara->runAction(seq);
    
    
		//
		// sprite 2 (To)
		//
		// The startPosition is not important here, because it uses a "To" action.
		// The initial position will be the 1st point of the Catmull Rom path
		//    
    
		CCPointArray *array2 = CCPointArray::create(20);
    
		array2->addControlPoint(ccp(s.width / 2, 30));
		array2->addControlPoint(ccp(s.width  -80, 30));
		array2->addControlPoint(ccp(s.width - 80, s.height - 80));
		array2->addControlPoint(ccp(s.width / 2, s.height - 80));
		array2->addControlPoint(ccp(s.width / 2, 30));
    
		CCCatmullRomTo *action2 = CCCatmullRomTo::create(3, array2);
		CCFiniteTimeAction *reverse2 = action2->reverse();
    
		CCFiniteTimeAction *seq2 = CCSequence::create(action2, reverse2, NULL);
    
		m_kathia->runAction(seq2);

        bRet = true;
    } while (0);

    return bRet;
}


 

<3> 示例效果图。

 

【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用             【Cocos2d-X开发学习笔记】第15期:动作类之摄像机动作和基本样条动作的使用

 

 

源码下载地址