基于上个http://blog.youkuaiyun.com/qxbailv15/article/details/17334825笔记的基础,差不多就可以学习做个简单的动画了。
推荐阅读地球人系列之二 http://www.cocoachina.com/gamedev/misc/2012/0528/4297.html
1.先通过可爱的TexturePacker 把我们需要用的所有资源图片打包成一个纹理文件和plist配置文件放到资源目录
如下:
注意:girl.png 天生就是一个多个帧组成的资源,由于没有与girl.png 对应的plsit配置文件,那么就没办法用Anti_TexturePacker工具来“反打包”,即拆包,拆成一张张的小图。所以接下来的介绍的制作动画的方法是需要自己用程序拆的情况。
images2.png感觉浪费了好多空间,才刚开始学习使用TexturePacker 工具,好多参数还需要设置。
2.写一个获取纹理块上的所需要的一个帧的函数
// 获取一个帧 CCSpriteFrame * spriteFrameWithStrip(const char *name, int col, int row, int startingRow, int startingCol) { CCSpriteFrameCache* pCache = CCSpriteFrameCache::sharedSpriteFrameCache(); CCSpriteFrame* pStrip = pCache->spriteFrameByName(name); // pStrip 是纹理块对应的精灵帧,需要拆分 CCTexture2D* pTexture = pStrip->getTexture(); // 整个纹理 CCSize originalSize = pStrip->getOriginalSize(); // 取得纹理块的大小 bool bRotated = pStrip->isRotated(); float w = originalSize.width/col; // 单位帧的宽度 float h = originalSize.height/row; // 单位帧的高度 float xx = startingCol*w; // 裁剪的当前坐标xx float yy = startingRow*h; // 裁剪的当前坐标yy CCSpriteFrame *frame = CCSpriteFrame::frameWithTexture(pTexture, CCRectMake(xx, yy, w, h)); frame->setRotated(bRotated); return frame; }
3.写一个获取纹理块上的所需要的多个帧的函数(暂不支持旋转90度后的纹理块)
// 获取多个帧组成的动画 // count 是想要生成的动画的帧数 // name 是动画使用的纹理块,col是指纹理块一共多少个列,row是指纹理块一共多少个行, // startingRow 是指动画使用的纹理快开始的行索引frame,startingCol是动画开始的纹理块的列索引frame CCAnimation * animationWithStrip(const char *name, int count, float delay, int col, int row, int startingRow,int startingCol) { CCArray* array_spriteFrames = new CCArray(count); CCSpriteFrameCache* pCache = CCSpriteFrameCache::sharedSpriteFrameCache(); CCSpriteFrame* pStrip = pCache->spriteFrameByName(name); // pStrip 是纹理块对应的精灵帧,需要拆分 CCTexture2D* pTexture = pStrip->getTexture(); // 整个纹理 CCSize originalSize = pStrip->getOriginalSize(); // 取得纹理块的大小 bool bRotated = pStrip->isRotated(); CCRect stripRect = pStrip->getRect(); // 取得纹理快的矩形区域 float w = originalSize.width/col; // 单位帧的宽度 float h = originalSize.height/row; // 单位帧的高度 float x = stripRect.origin.x; // 纹理块的左上x坐标 float y = stripRect.origin.y; // 纹理块的左上y坐标 int n = 0; float xx = startingCol*w; // 裁剪的当前坐标xx float yy = startingRow*h; // 裁剪的当前坐标yy for (int n=0;n<count;n++) { CCSpriteFrame *frame = CCSpriteFrame::frameWithTexture(pTexture, CCRectMake(xx, yy, w, h)); frame->setRotated(bRotated); array_spriteFrames->addObject(frame); n++; xx+=w; } CCAnimation *animation = CCAnimation::animationWithSpriteFrames(array_spriteFrames, delay); return animation; }
4. 利用用上面的自定义工具函数在场景的init函数留写代码(以后可以封装到一个类,作为常用工具类)
CCSize size = CCDirector::sharedDirector()->getWinSize(); CCSpriteFrameCache* pCache = CCSpriteFrameCache::sharedSpriteFrameCache(); pCache->addSpriteFramesWithFile("src02/images2.plist","src02/images2.png"); CCTexture2D* pTexture = CCTextureCache::sharedTextureCache()->textureForKey("src02/images2.png"); CCSpriteBatchNode* pSpriteBatch = CCSpriteBatchNode::batchNodeWithTexture(pTexture); addChild(pSpriteBatch); CCSprite* pBk = CCSprite::spriteWithSpriteFrameName("bk.jpg"); CC_BREAK_IF(! pBk); pBk->setPosition(ccp(size.width/2, size.height/2)); pSpriteBatch->addChild(pBk); CCAnimation *animation = animationWithStrip("girl.png",8,0.1,10,5,1,2); CCSpriteFrame* pFirstFrame = spriteFrameWithStrip("girl.png",10,5,1,2); CCSprite* pSprite = CCSprite::spriteWithSpriteFrame(pFirstFrame); CC_BREAK_IF(! pSprite); pSprite->setPosition(ccp(size.width/2, size.height/2)); pSpriteBatch->addChild(pSprite); pSprite->runAction( CCRepeatForever::actionWithAction( CCAnimate::actionWithAnimation(animation)) );
CCSpriteFrame* pFirstFrame = spriteFrameWithStrip("girl.png",10,5,1,2);
CCSprite* pSprite = CCSprite::spriteWithSpriteFrame(pFirstFrame);
这个调用是取第1行,第2列的那个帧,来作为原始帧,然后利用它生成一个精灵。
CCAnimation *animation = animationWithStrip("girl.png",8,0.1,10,5,1,2);
这个调用是取得一系列的帧信息,然后保存到animation里。
5.运行代码:
哈哈,可以看见一个小姑娘在原地不断切换自己的脚步了。
下一次再帮她移动位置好了,边移动位置,边切换脚步,才不会看起来那么奇怪。
好了,再说说另一种情况,那就是假如我有一张组合图,它有对应的plist,
那么就简单很多了,不需要自己用程序写切图的代码来生成动画。
// 初始玩家精灵,用于运行动画 CCSprite* sprite = CCSprite::createWithSpriteFrameName("player_01.png"); CC_BREAK_IF(! sprite); sprite->setPosition(XSystem::xccp(SCREEN_DEFAULT_WIDTH / 2, SCREEN_DEFAULT_HEIGHT/8)); //*创建一个帧动画,让玩家有动态感,可以逐张图片添加方式去添加动画 */ CCSpriteFrameCache* pCache = CCSpriteFrameCache::sharedSpriteFrameCache(); CCArray* frames = new CCArray(); // 帧图片 CCSpriteFrame* pSpriteFrame = NULL; // 通过几张独立的帧图片去组成动画 char szImageName[128] = {0}; for (int i=1; i<=3; i++) { sprintf(szImageName,"player_%02d.png",i); pSpriteFrame = pCache->spriteFrameByName(szImageName); frames->addObject(pSpriteFrame); } //创建动画,第二个参数默认delay为0.0f,请不要以为0表示没有延迟,而是直接停止了。 CCAnimation* anim = CCAnimation::animationWithSpriteFrames(frames, 3.0f); //播放动画 sprite->runAction(CCRepeatForever::actionWithAction(CCAnimate::actionWithAnimation(anim))); batchNode->addChild(sprite); this->setVisual(sprite);