地球人己阻止不了程序猿们学习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应该就是和JavaList类似?但是coco2d-x2.x版本里把CCArray的泛型去掉

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

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

 

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*很不习惯,嘻嘻。

 

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

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

 

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

/************************************************************************/
/* 根据图片列数,自动切割图片,生成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;
}


 

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

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

我在这里只说两点:

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

 

 

.

 

.

 

.

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值