Sprite

1.两种图片方式:可以用单个文件,或者纹理贴图集(Texture Atlases)来生成精灵。
   在设计游戏的时候,少花时间在素材制作上面。只要制作的素材可以用于游戏中,表达游戏的意图就可以了。在游戏设计完成以后,你可以请设计师帮你设计游戏中的各种素材,用于替换原有的粗糙素材。
    免费图片编辑器叫Seashore。以下网址下载:http://seashore.sourceforge.net。
    动画,可以使用开源软件Pixen。在这里下载Pixen:http://opensword.org/Pixen。
    音效可以使用已经安装在Mac上的GarageBand。 只需要用麦克风录制一些噪音,然后花些时间调整声音的设置就可以得到想要的音效了。也可以在网上寻找免费或者便宜的声音文件,例如 http://www.soundsnap.com 或类似的网站。

2.纹理贴图集 Texture Atlases
    纹理贴图集是一张包含很多图片的纹理贴图(图片),可用于存放单个角色动画的所有动画帧,或者把任何图片放进同一张纹理贴图中,达到节省空间的目的。

    纹理贴图集软件:使用Zwoptex或TexturePacker软件:
    当我们来比较TexturePacker和Zwoptex的特性的时候,TexturePacker似乎包含了Zwoptex90%的功能。但是,TexturePacker有三个杀手锏级别的功能是Zwoptex所没有的。
    抖动,抖动,抖动. 噢,我是多么喜欢抖动啊!在过去,有时我想使用比较低的像素格式,但是我不能,因为它看起来效果很不好。但是TexturePacker内置的抖动功能使得图片看起来还是那么棒,尽管此时的图片质量很低。
    pvr.ccz 支持. 它能够使游戏启动得更快, 而且会使你的可执行程序更小. 现在我不用花很长时间来上传和下载我以前写的应用程序了,我可以很快的下载并更新。
    命令行工具支持. 一旦你花一点时间把TexturePacker集成到你的Xcode中去,你将会热爱生活。它是如此地方便,特别是在整个开发过程中,美工对图片改来改去的时候。

    我已经下载了可以使用的mac版本zwoptex。
    可以使用Zwoptex这个软件来创建纹理贴图集。完成纹理贴图集以后保存,将把 Zwoptex的当前设置保存到一个ZSS文件中。然后点击Publish按钮,Zwoptext会生成cocos2d需要的.png文件和.plist文件,保存到和ZSS文件相同的文件夹中。
    Zwoptex可以移除每个图片的外围的透明部份,所以单张图片带有多余的透明部分并没问题。
    应该试着调整最终画布的大小,点击Apply按钮,看看是不是所有的图片还是可以容纳在同一张纹理贴图集里。我们的目的是生成一张最小尺寸的纹理贴图集,所有的图片都包含在里面,同时图片之间不能产生叠加。
    旋转并不会影响图片的显示。cocos2d 在显示纹理贴图集中的图片之前,会先把旋转过的图片旋转回正常的方向。
    Padding设置的作用是用于决定所有图片之间应该存在的距离(以像素计算)。


    不使用纹理贴图,使用多个单张图片,容易出现重复绘制的像素。最极端的情况会发生两张全屏的图片叠加在一起,虽然在同一时间里只能看到其中一张图片,但是设备还是会绘制两张图片。这在技术上叫做“全景渲染造成的浪费”(overdraw)。将背景图分成单独的条纹图片,同时这些图片之间很少重叠,这样可以有效降低重复绘制的像素,从而提高帧率。

    对于代码来说,应该把它们分散到不同的逻辑模块中去。但是对于纹理贴图集,目标应该是把尽可能多的图片打包到同一个图片中去,同时尽量减少图片上空白空间的存在。不过有一种情况可能适合将图片分开放置到不同的纹理贴图集中,比如一个由很多不同关卡组成的游戏,里面分成很多个世界,每个世界都有不同的敌人。这样最好把不同的世界和敌人分开放置到不同的纹理贴图集中去。

     需要一个方法来卸载不再需要的贴图内存。大多数情况下可以依赖cocos2d卸载: [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
在有不需要用到的贴图存在时才应该调用上述方法。通常应该在完成场景转换以后才做上述操作,而不是在游戏运行的过程中进行。
     如果想在加载新场景之前完全删除所有内存中的贴图,应该使用以下方法:
[CCSpriteFrameCache purgeSharedSpriteFrameCache];
[CCTextureCache purgeSharedTextureCache];

    纹理贴图集只是一张包含多个图片的大图片,同时这张大图片满足“2的n次方规则”。每一张包含于纹理贴图集中的图片都有一个精灵帧(sprite frame),这些帧用于定义各个图片在纹理贴图集中所处的各个长方形区域。精灵帧就是一个CGRect结构,此结构
定义了各个图片在纹理贴图集上所处的位置。这些精灵帧保存在一个单独的.plist文件中,cocos2d 可以利用这个文件渲染纹理贴图集中指定的图片。

3.CCSpriteBatchNode 精灵批处理
     图片渲染过程:每次系统在屏幕上渲染一张贴图时,图形处理硬件必须首先准备渲染,然后渲染图形,最后在完成渲染以后进行清理。如果图形处理硬件知道只需要使用同一张纹理贴图渲染一组精灵,图形处理硬件将则只需要为这一组精灵执行一次准备、渲染、后清理的过程就可以了。
     把使用同一张纹理贴图的一组CCSprite节点添加到同一个CCSpriteBatchNode里,比逐个渲染CCSprite要高效很多。因为CCSpriteBatchNod告诉图形处理硬件CCSpriteBatchNod包含的精灵都使用同一张纹理贴图渲染。
    “精灵批处理”(Sprite Batching )是用于提高精灵渲染速度的技术。它可以
提高渲染大量相同精灵的速度,它同纹理贴图集配合使用的效率最高。
    当需要显示两个或者更多个相同的CCSprite节点时,可以使用 CCSpriteBatchNode。CCSpriteBatchNode一次性渲染所有它所包含的图片,从而降低内存使用量和提高渲染率。

    创建多个CCSprite节点,将它们添加到同一个CCSpriteBatchNode中以提高渲染速度:
CCSpriteBatchNode* batch = [CCSpriteBatchNode batchNodeWithFile:@"bullet.png"]; 
[self addChild:batch];
for (int i = 0; i < 100; i++)
{ 
 CCSprite* sprite = [CCSprite spriteWithFile:@"bullet.png"];
 [batch addChild:bullet];//这里是添加到CCSpriteBatchNode中,不是CCLayer了。
}

     
因为上面代码中CCSpriteBatchNode将一个图片文件名作为参数,所以所有被添加进 CCSpriteBatchNode的CCSprite节点中的图片数据都必须来自这同一个图片文件。否则将会在调试窗口中得到以下报错信息:
'NSInternalInconsistencyException', reason: 'CCSprite is not using the same texture id'。
还有一个方法是[CCSpriteBatchNode batchNodeWithTexture:]; 然后用 [CCSprite spriteWithSpriteFrameName:@"x.png"]; 来生成CCSprite。

[CCSpriteBatchNode batchNodeWithFile:@".png"]的内部会先从贴图生成一个CCTexture2D节点 CCTexture2D* texture = [[CCTextureCache sharedTextureCache] addImage:fileName];然后调用batchNodeWithTexture。所以CCSpriteBatchNode中总是会使用一个纹理贴图。



       所有添加到同一个CCSpriteBatchNode中的CCSprite节点必须使用同一个纹理贴图,这也意味着CCSpriteBatchNode非常适合使用纹理贴图集。 使用纹理贴图集的时候,你不仅仅局限于渲染一张图片;你可以把不同的图片 放到同一个纹理贴图集中,然后利用CCSpriteBatchNode将所有图片渲染出来, 以提高渲染速度。
       CCSpriteBatchNode 只接受使用同一张纹理贴图的CCSprite节点。
       CCSpriteBatchNode只能包含基于CCSprite的对象。同样的限制也延伸到CCSprite的对象的任何子节点上,所以StandardShootComponent必须继承自 CCSprite以满足CCSpriteBatchNode的要求。
      可以把CCSpriteBatchNode看成CCLayer,唯一的区别是:CCSpriteBatchNode
只接受使用同一张纹理贴图的CCSprite节点。

4.精灵动画的实现方式
   CCSprite运行了一个动画,这个动画使用所有的图片帧构造。
   //1.生成精灵动画帧数组
NSMutableArray* frames = [NSMutableArray arrayWithCapacity:5];
//有5帧,对应图片ship-anim0.png,ship-anim1.png,...
//图片命名规则中不要使用在数字前附加0的习惯
for (int i = 0; i < 5; i++) 
{
// 为动画帧生成一个贴图
NSString* fileName = [NSString stringWithFormat:@"ship-anim%i.png", i]; 
//从贴图生成一个CCTexture2D节点
CCTexture2D* texture = [[CCTextureCache sharedTextureCache] addImage:fileName];
// 整个贴图被用作动画帧
CGSize texSize = [texture contentSize];
CGRect texRect = CGRectMake(0, 0, texSize.width, texSize.height);
// 从CCTexture2D节点生成一个精灵动画帧 CCSpriteFrame
CCSpriteFrame* frame = [CCSpriteFrame frameWithTexture:texture rect:texRect];
[frames addObject:frame]; 
}

//2.根据帧数组生成一个CCAnimation对象
CCAnimation* anim = [CCAnimation animationWithName:@"move" delay:0.08f frames:frames];

//3.运行动画runAction
// 使用CCAnimate运行动画
// 使用CCRepeatForever进行动画循环
CCAnimate* animate = [CCAnimate actionWithAnimation:anim]; 
CCRepeatForever* repeat = [CCRepeatForever actionWithAction:animate];
[self runAction:repeat];


       其中,CCAnimate动作使用了一个CCAnimation对象,(CCAnimation对象是一个包含所有动画帧的容 器),定义了每一帧之间的延迟,同时也给了这个动画一个命名。动画的名称很有用,因为可以用这个名称来存储CCSprite节点里面的动画。CCSprite类可用于存储动画。之后可以通过动画名称来获取相对应的动画:
CCAnimation* anim = [CCAnimation animationWithName:@"move" delay:1 frames:frames];
// 将动画储存在CCSprite节点中
[mySprite addAnimation:anim];
// 在之后的某个时间:你可以通过动画名称从CCSprite节点中获取相应的动画
CCAnimation* moveAnim = [mySprite animationByName:@”move”];



4.加载和使用纹理贴图集,生成了CCSpriteFrameCache
    使用CCSpriteFrameCache的addSpriteFramesWithFile方法来加载纹
理贴图集,传入的参数是纹理贴图集的.plist文件。CCSpriteFrameCache 会加载精灵帧,同时尝试加载相同命名的贴图,使用的文件后缀名是.png。
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache]; 
[frameCache addSpriteFramesWithFile:@"ship-and-bullet.plist"];
然后根据图片文件名称得到CCSpriteFrame* frame = [frameCache spriteFrameByName:imageFileName]; 

要注意sprite.texture.contentSize与sprite.contentSize不同,前者表示贴图的尺寸,后者表示精灵的尺寸。

如果加载了好几个纹理贴图集,而只有其中一个包含了需要的ship.png, cocos2d还是可以找到正确的贴图进行加载。从本质上说,通过名字来拿到精灵帧就像使用图片文件名一样。并不需要知道具体是哪个贴图集包含了需要的图片,除非使用的是CCSpriteBacthNode,它会要求所有子节点使用相同的贴图文件。
  
//扩展了的CCAnimation(Helper)的interface申明
@interface CCAnimation (Helper)
+(CCAnimation*) animationWithFile:(NSString*)name frameCount:(int)frameCount
delay:(float)delay; 
+(CCAnimation*) animationWithFrame:(NSString*)frame frameCount:(int)frameCount delay:(float)delay;
@end

// 利用精灵帧生成一个动画对象
+(CCAnimation*) animationWithFrameName:(NSString*)generalName frameCount:(int)frameCount delay:(float)delay
{
// 将动画帧作为贴图加载,生成一个精灵帧
NSMutableArray* frames = [NSMutableArray arrayWithCapacity:frameCount];
 for (int i = 0; i < frameCount; i++)
{
NSString* file = [NSString stringWithFormat:@"%@%i.png", generalName, i]; CCSpriteFrameCache* frameCache = [CCSpriteFrameCache
sharedSpriteFrameCache]; 
CCSpriteFrame* frame = [frameCache spriteFrameByName:file];
[frames addObject:frame];
}

// 使用所有得到的精灵帧生成一个动画对象,然后返回
return [CCAnimation animationWithName:frame delay:delay frames:frames];
}

// 使用单个文件生成动画
+(CCAnimation*) animationWithFile:(NSString*)name frameCount:(int)frameCount
delay:(float)delay
{
// 把动画帧作为贴图进行加载,然后生成精灵动画帧
NSMutableArray* frames = [NSMutableArray arrayWithCapacity:frameCount];
for (int i = 0; i < frameCount; i++)
 {
// 假设所有动画帧文件的名字是”nameX.png”
NSString* file = [NSString stringWithFormat:@"%@%i.png", name, i]; 
CCTexture2D* texture = [[CCTextureCache sharedTextureCache] addImage:file];
// 假设总是使用整个动画帧文件
CGSize texSize = texture.contentSize;
CGRect texRect = CGRectMake(0, 0, texSize.width, texSize.height); 
CCSpriteFrame* frame = [CCSpriteFrame frameWithTexture:texture rect:texRect offset:CGPointZero];
[frames addObject:frame];
}
// 使用所有的精灵动画帧,返回一个动画对象
return [CCAnimation animationWithName:name delay:delay frames:frames]; 
}



可以在制作动画的过程中,先用animationWithFile做快速的动画测试。等完全满意动画以后,你才把所有动画帧文件打包成一个纹理贴图集,然后将animationWithFile方法替换成 animationWithFrame方法。

5.// 将精灵平行翻转过来与第一组图片相连接
sprite.flipX = YES;




7.通过使用组件类和利用cocos2d的节点层级,可以创建“即插即用”式的拥有特定功能的类(组件)。这有助于使用 “复合”而不是“继承”来创建游戏中的对象。可以在编写游戏逻辑代码时得到更多的自由度和实现更好的代码重用。

8. 速度矢量
     速度矢量velocity类型是CGPoint,表示两个方向上的速度。例如以下代码,子弹的速度是固定向前为1,向上或向下随机。
     float spread = (CCRANDOM_0_1() - 0.5f) * 0.5f;
     CGPoint velocity = CGPointMake(1, spread);


9.创建CCSprite的时候并不需要指定精灵的大小,传递一个文件名给它,它会自动计算出大小。

10.Cocos2d-x 动画工具 Flash2Cocos2d-x
http://www.dapps.net/dev/gamedev/cocos2d-x-animation-flash2cocos2d-x.html

猜你喜欢

转载自wwk.iteye.com/blog/1681248