首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

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

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

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

地球人己阻止不了程序猿们学习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应该就是和Java的List类似?但是coco2d-x的2.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.       仔细研究教程作者的算法,我们应该会发现,截取被旋转后的图片帧的方式有点奇怪,并且,当使用CCSpriteFrame的setRotate方法后,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

 

 

.

 

.

 

.

热点排行