cocos2d-x开发记录:二,基本概念(动作,动画,坐标系统)

既然我们选择用cocos2d,那么他里面的一些基本概念我们肯定是要熟悉下的,以下资料来源于官网,英语好的可以直接去官网看。

一.Actions(动作)

动作都由于CCNode对象发出。这些动作通常修改对象的一些属性,比如位置,旋转,比例等。如果这些属性在某一个时间周期内被修改,那么它们是CCIntervalAction动作。否则它们是CCInstantAction动作。例如CCMoveBy动作在某段时间内修改了位置属性,因此,它是CCIntervalAction的子类。我们能运行TestCpp->Actions来看看动作的可视化效果。这个文件位于cocos2d-x/samples/Cpp/TestCpp/Classes/ActionsTest下。ActionsEaseTest是很好的示例代码用法。

CCIntervalAction动作有一些有趣的属性:

它们用于改变动作加速的快慢。你能使用CCActionManager恢复或暂停所有动作。

// Pause actions
CCDirector *director = CCDirector::sharedDirector();
m_pPausedTargets = director->getActionManager()->pauseAllRunningActions();
// resume actions
CCDirector *director = CCDirector::sharedDirector();
director->getActionManager()->resumeTargets(m_pPausedTargets);

基本动作

位置

CCMoveBy
CCMoveTo
CCJumpBy
CCJumpTo
CCBezierBy
CCBezierTo
CCPlace

比例

CCScaleBy
CCScaleTo

旋转

CCRotateBy
CCRotateTo

可见度

CCShow
CCHide
CCBlink
CCToggleVisibility

透明度

CCFadeIn
CCFadeOut
CCFadeTo

颜色

CCTintBy
CCTintTo

Example:

CCSprite *sprite = CCSprite::create("Images/grossini.png");
sprite->setPosition(ccp(100, 100));
addChild(sprite);

CCMoveBy* act1 = CCMoveBy::create(0.5, ccp(100, 0));
sprite->runAction(CCRepeat::create(act1, 1));

二.动画

帧动画

你能从一系列的图片文件中创建一个动画,如下所示:

 

CCAnimation *animation = CCAnimation::create();

 

 // load image file from local file system to CCSpriteFrame, then add into CCAnimation

 for (int i = 1; i < 15; i++)

 {

     char szImageFileName[128] = {0};

     sprintf(szImageFileName, "Images/grossini_dance_%02d.png", i);

     animation->addSpriteFrameWithFileName(szImageFileName); 

 }

 

animation->setDelayPerUnit(2.8f / 14.0f); // This animation contains 14 frames, will continuous 2.8 seconds.

animation->setRestoreOriginalFrame(true); // Return to the 1st frame after the 14th frame is played.

 

CCAnimate *action = CCAnimate::create(animation);

sprite->runAction(action);  // run action on sprite object

注意CCAnimation由精灵(sprite)帧组成。每帧间隔时间,动画持续时间等,这是一个“数据包”。然而CCAnimate是一个动作,它基于CCAnimation对象。

Sprite Sheet动画

虽然手动动画是非常容易理解的,但很少用于真正的游戏项目。所以精灵动画是更通用的2D动画解决方案。下图是一个典型的Sprite Sheet。它可以是一个序列帧动画,或者是一个图片包被用在同一场景中。

在 OpenGL ES 1.1时期,sprite sheets被广泛用于以下这些福利:

◆减少文件IO时间,载入一个大的sprite sheet文件跟载入大量小的文件整体速度更快。

◆减少内存消耗。OpenGL ES 1.1仅能用于纹理的2次方大小。(2,4,8,64,128,256,512,1024等)。换句话说,OpenGL ES 1.1分配2次方大小的内存给每一个纹理,即使这个纹理小于分配的宽高。因此使用sprite sheet包裹在一起的图片将会减少内存碎片。

◆减少OpenGL ES 绘制方法的调用并加速渲染。

Cocos2d-x v2.0升级到了OpenGL ES 2.0。OpenGL ES 2.0不再分配2次方纹理大小了。但减少文件IO和绘制调用的福利仍然有效。那么怎么样关联动画?正如我们所见,sprite sheet没有和动画有必然会发生的关系。但考虑到以上这些福利,sprite sheet动画是有效率的。在cocos2d中有不同的方法来创建sprite sheet动画。

从.png和 .plist文件中创建

在cocos2d-x 0.x和1.x 版本中,CCSpriteSheet是用于这个目的。然而 自从v2.0开始CCSpriteBatchNode已经替代了CCSpriteSheet。

一个CCSpriteBatchNode对象包含所有精灵帧的实际图像纹理。你必须添加它到场景中。即使它不会绘制它自己。但它只需要一部分的渲染管道。例如:

CCSpriteBatchNode* spritebatch = CCSpriteBatchNode::create("animations/grossini.png");

下一步,你需要使用CCSpriteFrameCache单例来跟踪帧名和宽高。下面是prite sheet的矩形区域,例如:

CCSpriteFrameCache* cache =  CCSpriteFrameCache::sharedSpriteFrameCache();
cache->addSpriteFramesWithFile("animations/grossini.plist");

一旦你的sprite sheet和帧被载入,并且sprite sheet被添加到场景中,你能使用“createWithSpriteFrameName”方法来创建精灵用于这些帧数中,并作为一个孩子把这个Sprite添加到batch中:

m_pSprite1 = CCSprite::createWithSpriteFrameName("grossini_dance_01.png");
spritebatch->addChild(m_pSprite1);
addChild(spritebatch);

createWithSpriteFrameName方法会从grossini.plist中找到正确的坐标和矩形,然后裁切纹理到一个精灵帧中。现在我们需要创建一个CCArray对象并添加所有动画帧到它里面去。对于这个动画,我们知道所有14帧有同样的尺寸,因此我们可以用一个循环遍历它们,当添加到第14帧的时候跳出循环。

 CCArray* animFrames = CCArray::createWithCapacity(15);

 char str[100] = {0};

 for(int i = 1; i < 15; i++)
 {

     sprintf(str, "grossini_dance_%02d.png", i);

     CCSpriteFrame* frame = cache->spriteFrameByName( str );

     animFrames->addObject(frame);

}

最后,我们需要创建一个CCAnimate动作实例,我们可以在CCSprite 执行。我们也把CCAnimate动作包裹到CCRepeatForever 动作里,然后你想要的就是永远重复这个动画:

CCAnimation* animation = CCAnimation::createWithSpriteFrames(animFrames, 0.3f);

m_pSprite1->runAction( CCRepeatForever::create( CCAnimate::create(animation) ) );

文件动画

CCAnimationCache 能载入xml/plist文件,很好的描述了批处理节点,精灵帧名字和它们的矩形。接口更容易使用

CCAnimationCache *cache = CCAnimationCache::sharedAnimationCache(); // "caches" are always singletons in cocos2d

cache->addAnimationsWithFile("animations/animations-2.plist");

CCAnimation animation = cache->animationByName("dance_1");  // I apologize for this method name, it should be getAnimationByName(..) in future versions

CCAnimate animate = CCAnimate::create(animation);  // Don't confused between CCAnimation and CCAnimate :)

sprite->runAction(animate);

三.坐标系统

不同坐标系统的介绍

1.笛卡尔坐标系统

你在学校的时候可能知道笛卡尔坐标系统它大量用于几何课程中。如果你已经忘记了,下面这些图片会让你马上回想起来:

在手机游戏开发中,你会遇到3种坐标系统

2.UI坐标系统

UI坐标系在iOS/Android/Windows SDK中常见:

原点(x=0,y=0)在左上角。

X轴从屏幕的左边往右边增加。

Y轴从屏幕的顶部往底部增加。

如下所示:

3.Direct3D坐标系统

DirectX使用的是左手笛卡尔坐标系统。

4.OpenGL和Cocos2d坐标系统

Cocos2d-x/-html5/-iphone和OpenGL一样使用同样的坐标系统,它被叫做右手笛卡尔坐标系

 

在2D世界中,我们仅使用X轴和Y轴。因此在你的cocos2d游戏中:

原点(x=0, y=0)在屏幕左下方,这意味着屏幕在右手笛卡尔坐标系的第一象限

X轴从屏幕的左边往右边增加。

Y轴从屏幕的底部往顶部增加。

下图更直接的解释了cocos2d-x的坐标系:

注意它不同于常见的UI坐标系和DirectX 坐标系

父类于子类

每个类都是CCNode(这是cocos2d-x的最基类,就像java中的Object一样)的子类,并且都有一个anchorPoint(锚点)属性。当确定绘制对象的位置时,cocos2d-x将联合position和anchorPoint属性。当旋转对象时,cocos2d-x也会根据此锚点旋转。我们创建一个父类(灰色)精灵和一个子类(蓝色)精灵。并且父类的位置为cpp(100,100),子类的锚点设置为中心,代码如下所示:

   

  CCSprite* parent = CCSprite::create("parent.png");

     parent->setAnchorPoint(ccp(0, 0));// Anchor Point

     parent->setPosition(ccp(100, 100));

     parent->setAnchorPoint(ccp(0, 0));

     addChild(parent);

 

     //create child

     CCSprite* child = CCSprite::create("child.png");

     child->setAnchorPoint(ccp(0.5, 0.5));

     child->setPosition(ccp(0, 0));

     parent->addChild(child);//add child sprite into parent sprite.

虽然我们设置子类的cpp(0,0),但父类的位置为cpp(100,100),因此运行后效果图,如下所示:

锚点

锚点被用于位置和旋转中。锚点坐标是相对坐标,通常对应于对象中的一个点。例如,锚点cpp(0.5,0.5)对应于对象的中心。当设置对象的位置时,setPosition()方法内部会调用锚点。旋转也是如此。例如,下面是一个精灵,它的锚点为cpp(0,0)并且位置为cpp(0,0);

 

代码如下所示:

// create sprite

CCSprite* sprite = CCSprite::create("bottomleft.png");

sprite->setAnchorPoint(ccp(0, 0));// Anchor Point

sprite->setPosition(ccp(0,0));

addChild(sprite);

运行后的效果如下所示:

如果锚点想设置为精灵的中心,则使用ccp(0.5, 0.5),代码如下所示:

 

// create sprite

CCSprite* sprite = CCSprite::create("center.png");

sprite->setAnchorPoint(ccp(0.5, 0.5));// Anchor Point

sprite->setPosition(ccp(0,0));

addChild(sprite);

运行后的效果如下:

getVisibleSize, getVisibleOrigin vs getWinSize

VisibleSize返回OpenGL视图中的可见大小。如果不调用CCEGLView::setDesignResolutionSize()的情况下它的值等于getWinSize
getVisibleOrigin返回可见的OpeaGL视图中的原点。更多细节可以参考官网的Multi resolution support

怎么转换到co坐标系

1.convertToNodeSpace(转换到节点空间):

convertToNodeSpace将被用于有一个大地图的骰牌游戏。convertToNodeSpace 将转换你的openGL触摸co-坐标到.tmx地图中或其他相似的文件中。例如:以下图片显示了2个节点。node1的锚点为(0,0),node2的锚点为(1,1)。

我们调用CCPoint point = node1->convertToNodeSpace(node2->getPosition()); 转换 node2的屏幕坐标到node1的本地坐标。node2的位置为(-25,-60),如下图所示 :

2.convertToWorldSpace(转换到世界空间):

convertToWorldSpace(const CCPoint& nodePoint) 

转换节点坐标到屏幕坐标。convertToWorldSpace将一直返回屏幕坐标,如果你想要在精灵上捕捉信号,但需要移动/缩放你的layer时,这个方法可能很有用。通常父节点通过子节点的位置调用这个方法,返回子节点的世界位置作为结果。如果调用者不是父节点,那么调用这个方法似乎毫无含义。

例如:

CCPoint point = node1->convertToWorldSpace(node2->getPosition());

上面的代码将转换节点2的坐标到屏幕坐标中。例如如果节点2的位置是(0,0),它在节点1的左下方,它不一定在屏幕上。节点2在屏幕的位置将被转换为(0,0),在本例中为(15,20),如下图所示:

 

3.convertToWorldSpaceAR(相对于锚点转换)

convertToWorldSpaceAR将返回相对于锚点的位置:如果我们的场景根节点layer的锚点为cpp(0.5f,0.5f)这是默认的。convertToWorldSpaceAR 将返回相对于屏幕中心的位置

convertToNodeSpaceAR逻辑和convertToWorldSpaceAR一样,如下面代码所示:

 

 CCSprite *sprite1 = CCSprite::create("CloseNormal.png");

 sprite1->setPosition(ccp(20,40));

 sprite1->setAnchorPoint(ccp(0,0));

 this->addChild(sprite1);

CCSprite *sprite2 = CCSprite::create("CloseNormal.png");

sprite2->setPosition(ccp(-5,-20));

sprite2->setAnchorPoint(ccp(1,1));

this->addChild(sprite2);

CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());

CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());

CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());

CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());

CCLog("position = (%f,%f)",point1.x,point1.y);

CCLog("position = (%f,%f)",point2.x,point2.y);

CCLog("position = (%f,%f)",point3.x,point3.y);

CCLog("position = (%f,%f)",point4.x,point4.y);

 

结果为:

 position = (-25.000000,-60.000000)

 position = (15.000000,20.000000)

 position = (-25.000000,-60.000000)

 position = (15.000000,20.000000)

原文地址:https://www.cnblogs.com/tianjian/p/3359164.html