最终效果图:
一次完整的渲染包括三步:渲染前的准备(open)、执行渲染、渲染完成后的工作(close)
一个spriteBatchNode对应一个纹理\图片
因此,添加到spriteBatchNode里面的sprite必须使用同一个图片\纹理
从上面,可以看到,不使用spriteBatchNode时,精灵个数不停地增加
当使用了spriteBatchNode,精灵个数恒定
在上面的图片中,实例化spriteBatchNode时,参数指定的image file是一张打包合成的大图片
前面说过,
spriteFrameCache
精灵帧缓存
,
里面放的是
plist
文件中每一帧的数据
:
如
rect,rotated,
小图片名等
;
根据小图片在plist中的key(小图片名)
,可以
到一个大的图片中去裁剪出来想要的小图片
因此,可以将所有的裁剪出来的所有精灵帧添加到同一个spriteBatchNode里面去,由它统一管理、统一渲染(因为这些精灵帧用到的纹理都是同一个,即大的图片)
而场景里,只需添加一个spriteBatchNode即可;其他的,通过同一个大图片\纹理 创建出来的精灵或精灵帧只需添加到spriteBatchNode里面
类似的,如果项目中用到两个或多个图片(或大图片),只需要一个spriteBatchNode对应一个图片,一个图片(或大图片)创建出来的sprite全部统一添加到与该图片\纹理对应的spriteBatchNode里面
//
// SpriteBatchNode.m
// 31_cocos2D入门
//
// Created by beyond on 14-9-25.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//
// 添加SpriteBatchNode到当前场景,以后batch统一负责管理所有的【使用了同一张图片作为纹理的】精灵
/*
一个CCSpriteBatchNode对象只能处理一个纹理对象(添加到batch中的子节点必须和batch使用同一个纹理对象)
// 创建一个精灵批处理(类似一个池,所有用同一张图片,生成的精灵,全部加到这个池中,统一管理,重要前提:一个精灵批处理只认一张图片,即:一个精灵批处理只允许使用相同纹理的精灵加入它,加入池,加入这个大家庭)
// 因为一个spriteWithFile,会经历三个步骤:首先是open纹理, 然后是 渲染,最后是 close纹理
// 如果使用spriteWithFile方法,生成1000个sprite,上面三个步骤会执行一千次,屏幕上,此时也会生成1000个node
// 因此,使用spriteBatchNode之后,只会open纹理一次,渲染1000次,关闭纹理一次即可,此时屏幕上,始终只有一个Node,它就是spriteBatchNode,因为sprite全部添加到spriteBatchNode中,让它去统一管理
// 假如,项目中所有图片全部打包到一个大图片,那么项目就只有一个大的纹理,所有的精灵帧,都会根据Plist文件中的key即小图片名,到大的纹理相册中裁剪图片,那么,我们就可以就让一个spriteBatchNode管理该大图片,即大的纹理相册;所有的精灵帧对象,由于使用的是同一张大图片,所以可以全部添加到spriteBatchNode中统一进行管理;因为所有的精灵帧使用到同一个纹理相册,同一个大图片
// spriteFrameCache精灵帧缓存,里面放的是plist文件中每一帧的数据:如rect,rotated,小图片名等;根据这些,到一个大的图片中去裁剪出来想要的小图片
*/
#import "SpriteBatchNodeScene.h"
@interface SpriteBatchNodeScene()
{
CCSpriteBatchNode *_batch;
}
@end
@implementation SpriteBatchNodeScene
#pragma mark - 覆盖父类方法
-(id)init
{
if (self=[super init]) {
// 1、场景Node 允许交互
self.userInteractionEnabled = YES;
}
return self;
}
- (void)addSpriteInCenter{}
- (void)addShowBtns
{
// 1.使用spriteBatchNode
[self addBtn:@"【使用batchNode】" position:ccp(0, 0) target:self sel:@selector(use_batchNode)];
}
#pragma mark - 按钮点击
- (void)use_batchNode
{
// 添加SpriteBatchNode到当前场景,以后batch统一负责管理所有的【使用了同一张图片作为纹理的】精灵
// 1.加载大的纹理相册
CCSpriteFrameCache *spriteFrameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[spriteFrameCache addSpriteFramesWithFile:@"zhaoyun.plist"];
// 2.参数是图片名,一个batch只会只能管理 从同一个大图片 创建出来的sprite
_batch = [CCSpriteBatchNode batchNodeWithFile:@"zhaoyun.png"];
// 下面二句 等价于 上面的一句
CCTexture *texture = [CCTexture textureWithFile:@"zhaoyun.png"];
[CCSpriteBatchNode batchNodeWithTexture:texture];
// 3.添加batch到当前场景,以后所有创建出来的精灵,只需添加到spriteBatchNode中即可
// 当前场景 只管理batch,而batch统一负责管理所有的【使用了同一张图片作为纹理的】精灵
[self addChild:_batch];
}
#pragma mark - 点击屏幕
// 手抬起处就放一个精灵
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
// 得到触摸点
CGPoint touchLoc = [touch locationInNode:self];
// 从纹理相册plist文件中,根据key:图片名,从大图片中裁剪出小图片
// 从大图片中随机取出一个小图片,key为Plist中的图片名,1~9.png
NSString *imgName = [NSString stringWithFormat:@"%d.png",arc4random()%9+1];
CCSpriteFrame *frame = [CCSpriteFrame frameWithImageNamed:imgName];
CCSprite *s = [CCSprite spriteWithSpriteFrame:frame];
// 关键一句:
// 设置 子弹出现的位置
s.position = touchLoc;
if (_batch == nil) {
[self addChild:s];
} else {
[_batch addChild:s];
}
}
@end