地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

时间:2021-02-12 09:07:27

地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

 

 

笨木头花心贡献,啥?花心?不呢,是用心~

转载请注明,原文地址
http://blog.csdn.net/musicvs/article/details/8105611

 

正文:

 

 

 

第二篇的重点是:(内容重点:动画, CCAnimation, CCAnimate, CCSpriteFrameCache)

 

原教程地址:http://cn.cocos2d-x.org/bbs/forum.php?mod=viewthread&tid=805&extra=page%3D1

 

1.    会动的精灵

第一篇教程教我们的是创建一个精灵,但是它不会动,现在终于可以创建会动的精灵了,看代码先:

/* 加载图片帧*/
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();
cache->addSpriteFramesWithFile("images.plist", "images.png");

/* 创建一个精灵*/
CCSprite* girlSprite = CCSprite::createWithSpriteFrameName("girl1.png");
CCSize size = CCDirector::sharedDirector()->getWinSize();
girlSprite->setPosition(ccp(size.width / 2, size.height / 2));

/* 让精灵执行一个动画,
animation是名称,animate是动词,
所以要动起来就要用CCAnimate创建一个会动的动画,我是这么记忆的,嘿嘿
*/
girlSprite->runAction(CCAnimate::create(animation));

this->addChild(girlSprite);

首先加载图片(SpriteFrame),这是上一篇教程教过我们的。

然后我先省略了中间的重要步骤,直接创建了一个精灵,最后有一句话:

 

girlSprite->runAction(CCAnimate::create(animation));

 

这就是让精灵动起来的方法——runAction

要让精灵动起来,我们需要一个动画对象,这个对象其实就是由若干个图片帧组合的:

/* 数组对象,和Java的集合差不多?*/
CCArray* framesArray = CCArray::create();

/* 把动画所需的所有图片帧添加到数组里*/
CCSpriteFrame* frame = cache->spriteFrameByName("girl1.png");
framesArray->addObject(frame);

frame = cache->spriteFrameByName("girl2.png");
framesArray->addObject(frame);

frame = cache->spriteFrameByName("girl3.png");
framesArray->addObject(frame);

frame = cache->spriteFrameByName("girl4.png");
framesArray->addObject(frame);

/* 使用图片帧生成动画对象,每隔500毫秒播放一帧*/
CCAnimation* animation = CCAnimation::createWithSpriteFrames(framesArray, 0.5f);
animation->setLoops(-1); // 设置循环播放
animation->setRestoreOriginalFrame(true); // 设置播放完毕后恢复精灵原始帧


 

好像没有什么能解释的,CCAnimation对象需要一组图片帧(SpriteFrame)来创建,而

这组SpriteFrame对象用一个CCArray来存放。

CCArray应该就是和JavaList类似?但是coco2d-x2.x版本里把CCArray的泛型去掉

了,有点不习惯(不知道是不是我弄错了?噗)。

对了,1.x版本和2.x版本创建CCAnimation是有点不一样的(我就不说了哈,我只研究2.x版本~)。

地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

 

2.    工具类

每次要一个精灵动起来就要写这么多行代码,虽然简单,但是看着就很繁琐,所以教程里面就教我们写一个工具类。

把前面生成CCAnimation的步骤抽离出来,写成一个函数:

 

cocos2d::CCAnimation* SpriteHelper::createAnimWithSingleFrameN( const char* name, int count, float delay )
{
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();

CCArray* framesArray = CCArray::createWithCapacity(count);

char str[80];
for(int i = 1; i <= count; i++)
{
sprintf(str, "%s%d.png", name, i);
framesArray->addObject(cache->spriteFrameByName(str));
}

CCAnimation* animation = CCAnimation::createWithSpriteFrames(framesArray);
animation->setLoops(-1);
animation->setRestoreOriginalFrame(true);
animation->setDelayPerUnit(delay);

return animation;
}

没有什么新的知识,噗,当然了,用了一个sprintf函数,用来连接字符串的。我到现在还不懂怎么用C++里面的String对象,Java里用String用习惯了,现在用char*很不习惯,嘻嘻。

地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

 

3.    如果精灵图片是连在一起的

我们常常会看到这样连在一起的图片:

地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

 

而刚刚写的那个工具类的函数是针对一张一张分开的图片的,于是,我们要修改一下:

/************************************************************************/
/* 根据图片列数,自动切割图片,生成CCAnimation对象 */
/************************************************************************/
cocos2d::CCAnimation* SpriteHelper::createAnimByLineFrameN( const char* name, int col, float delay )
{
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();
CCSpriteFrame* frame = cache->spriteFrameByName(name);

CCTexture2D* texture = frame->getTexture();
CCSize frameSize = frame->getOriginalSizeInPixels();
CCRect frameRect = frame->getRect();

float w = frameSize.width / col;
float h = frameSize.height;
float x = frameRect.origin.x;
float y = frameRect.origin.y;

CCArray* framesArray = CCArray::createWithCapacity(col);
for(int i = 0; i < col; i++)
{
framesArray->addObject(CCSpriteFrame::createWithTexture(texture, CCRectMake(x, y, w, h)));
x += w;
}

CCAnimation* animation = CCAnimation::createWithSpriteFrames(framesArray);
animation->setLoops(-1);
animation->setRestoreOriginalFrame(true);
animation->setDelayPerUnit(delay);

return animation;
}


 

因为怕大家看到代码太长会厌烦,所以我把注释都去掉了,大家先扫一眼,看懂了就好,如果还有疑问的话,请看下面这段加上详细注释之后的代码:

/************************************************************************/
/* 根据图片列数,自动切割图片,生成CCAnimation对象 */
/************************************************************************/
cocos2d::CCAnimation* SpriteHelper::createAnimByLineFrameN( const char* name, int col, float delay )
{
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache();

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

/*
SpriteFrame的纹理对象(CCTexture2D),
我的理解就是那张TexturePacker打包的大图
并且,同一张大图生成的SpriteFrame对象的getTexture的结果是一致的。
换句话说,SpriteFrame其实保存了一份图片纹理的引用。
*/
CCTexture2D* texture = frame->getTexture();

/*
我很好奇,getOriginalSize和getOriginalSizeInPixels倒底有什么区别?
稍微我研究一下,再和大家分享
*/
CCSize frameSize = frame->getOriginalSizeInPixels();

/*
SpriteFrame是否没有坐标的概念的,
只有矩阵范围这个概念,所以要获得它的位置,
必须通过它的矩阵范围来取得
*/
CCRect frameRect = frame->getRect();

float w = frameSize.width / col; /* 每帧图片的宽*/
float h = frameSize.height;

float x = frameRect.origin.x;
float y = frameRect.origin.y;

CCArray* framesArray = CCArray::createWithCapacity(col);
for(int i = 0; i < col; i++)
{
/*
我一直都很担心,createWithTexture是不是就生成了新的纹理对象?
不过,我再仔细想想,SpriteFrame本来就只是引用了纹理对象,而不是新建一份小纹理。
我的理解是,SpriteFrame其实只是其记录数据的作用,记录了某个图片帧在整张大图片的位置,以及截取范围等。
所以,createWithTexture只不过是把SpriteFrame的范围改变了一下而已。
*/
framesArray->addObject(CCSpriteFrame::createWithTexture(texture, CCRectMake(x, y, w, h)));

x += w;
}

CCAnimation* animation = CCAnimation::createWithSpriteFrames(framesArray);
animation->setLoops(-1);
animation->setRestoreOriginalFrame(true);
animation->setDelayPerUnit(delay);

return animation;
}


地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

 

4.    如果精灵图片是堆在一起并且被旋转了

哇,这种图片要我们来切的话,还是要花点心思的,教程里作者已经给出了算法了,有兴趣的朋友可以研究一下。

我在这里只说两点:

地球人己阻止不了程序猿们学习cocos2d-x了-学习笔记02

1.       CCSpriteFrame记录的是图片帧在整张大图片里的位置信息,而不管图片帧在大图片里是否旋转过,它所记录的图片宽高是不会变的。图片帧被旋转之后,CCSpriteFrame会使用isRotate来记录。

2.       仔细研究教程作者的算法,我们应该会发现,截取被旋转后的图片帧的方式有点奇怪,并且,当使用CCSpriteFramesetRotate方法后,CCSpriteFrame对象的纹理对象会以CCSpriteFrame所记录的位置为基准去旋转。有点难逻辑,要自己仔细看看算法才能体会到呢,噗。

 

了,第二篇教程的学习结束了,主要是学习怎么让精灵动起来,然后就是顺便学习了截取TexturePacker打包后的图片里的图片帧的方法。

 

接下来我也许会学习作者的第三篇教程(地球人己阻止不了程序猿们学习cocos2d-x了 (第三篇) :http://cn.cocos2d-x.org/bbs/forum.php?mod=viewthread&tid=852),但是第三篇讲的是多平台移植的知识,我只有Android开发环境,我曾经尝试用Vmware安装IOS开发环境,失败了两次,我会再试多一次,祝我好运。

如果我失败了,我只好跳过第三篇,直接学习第四篇了。

 

请允许我做个广告。

AndroidFans论坛,我经常在这活动,欢迎来交流:笨木头邀请您访问Android 开发论坛:
http://www.android-fans.net/?fromuid=35

 

 

.

 

.

 

.