Cocos2D中:对CCSpriteBatchNode的使用6个疑虑(Cocos2d: 6 doub

2019-07-31 15:31发布

我想知道如何优化CCSpriteBatchNode的使用。 换句话说,我认识到:

  • 1)每个CCSpriteBatchNode实例执行一个呼叫到绘制方法,从而减少OpenGL调用且因此显著性能改进的
  • 2)每个CCSpriteBatchNode可以指一个且仅纹理地图

什么我不是100%肯定,我想你的答案是:

  • 3)如果我有一个纹理图集,如游戏,艺术hd.png,并创建各种类,我将获取多个绘图调用几个CCSpriteBatchNode? 换句话说,我假定CCSpriteBatchNode的每个实例将调用它自己的拉伸方法,导致多个GL绘图呼叫和比具有一个共享节点批量性能以下。 我对吗?

    - 4)如果我使用一个Sprite由多个帧的动画,我想我应该动画帧添加到雪碧批次节点。 我该怎么办呢?

    下面有我如何正常动画精灵的代码片断。 正如可以注意到的子画面帧不加入到子画面批次节点。 为了获得更好的性能也许我应该这样做在初始化时。 它是否正确?

      NSMutableArray* frames = [[NSMutableArray alloc]initWithCapacity:2]; for (int i = 0; i < 4; i++) { NSString*bulletFrame = [NSString stringWithFormat:@"animation-%i.png", i]; CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:bulletFrame]; [frames addObject:frame]; } CCAnimation* anim = [CCAnimation animationWithFrames:frames delay:0.1f]; CCAnimate* animate = [CCAnimate actionWithAnimation:anim]; CCRepeatForever* repeat = [CCRepeatForever actionWithAction:animate]; [self runAction:repeat]; } 
  • 5)部分指的4.你确认是希望避免增加并在运行时移除精灵的精灵一批节点?

  • 6)将CCSpriteBatchNode只考虑有肉眼可见设置为true或具有位置,实际上是画面区外精灵的精灵?


3其他注意事项

为了解决3.我的假设,并减少CCSpriteBatchNode实例的数量,我的解决方案将遵循什么在这个建议的@Suboptimus 答案 。 我喜欢初始化希望与MainScene类共享同一批次的节点,而不是让他们通过self.parent.parent访问MainScene类的建议的方法。(...)。parent.finallysharedbatchNode

其他人反而会建议使用通过..... self.parent父母和正确的浇铸成指MainScene。

这是最好的办法也是在软件工程方面

我喜欢并明确其中的精灵通过使用一个明确的参考MainScene类..如果我的团队,或者如果我更改类层次结构在工作这应该有助于增加。 但是,这种方法的缺点是,我“需要”的引用存储它,如果我想补充随后精灵到一批节点,从而导致更多的代码维护。

我问这个问题的原因是,如果找到我的传统的“软件工程”思想和“cocos2d的父节点”层级方法之间的轻微碰撞。 我是新来的游戏编程,我想了解哪一种方法是,经历了大团队中工作使用:)游戏开发商之一。 H

Answer 1:

  1. 正确的,但“左曲叫”不等同于执行draw方法。 绘制调用处于OpenGL的状态的变化,需要进行昂贵的操作以复位状态机。 绑定新的纹理或更改变换适应该法案。
  2. 正确。
  3. 正确。
  4. 没有必要那样做。 动画精灵上运行。 因此,只有精灵需要进行批处理。 如果一个动画帧由相同的纹理地图不是,CCSpriteBatchNode将当动画试图使用这样的帧抱怨。
  5. 这是理想的。 添加/在CCSpriteBatchNode更贵不是添加/任何其他节点的去除精灵的删除。 由于精灵一批节点的四边形需要更新。 虽然它可能只是使任何区别,如果你有很多的子节点,并添加/删除频繁。
  6. 没有,没有。 见这里我的答案 。

3其他注意事项:

如果您的场景层次不太深,你可以用self.parent去也许self.parent.parent有时但仅限于父母的关系实际上是固定的(即从一个精灵分批精灵绕过为了精灵一批节点去底层的“真”父)。 但我不会推荐任何打算更深。 见我的答案在这里为两个self.parent技术和避免保留周期。

这个问题self.parent.parent.(…).parent是,如果你需要通过添加或删除层次结构中的父节点来改变父子关系,例如,这完全打破。 那么这将EXC_BAD_ACCESS崩溃严重,很难调试,因为你必须检查每个父母和父母的父母,看看它到底是怎样的对象。 访问的父母在3个或更多级别的层次,我不会考虑不好的做法。 这是一个可怕的做法

就个人而言,用于访问如共享精灵批次常用节点,我更喜欢其中“MainScene”成为一个临时Singleton类的时间,而它是活性的溶液。 然后,你可以做任何的子节点如下:

CCSpriteBatchNode* mainBatch = [MainScene sharedMainScene].spriteBatchNode;

为了创建这个临时单:

static MainScene* instance;
-(id) init
{
    self = [super init];
    if (self)
    {
        instance = self;
    }
    return self;
}
-(void) dealloc
{
    instance = nil;
}
-(MainScene*) sharedMainScene
{
    NSAssert(instance, @"MainScene is not initialized!");
    return instance;
}

一个真正的单不同的是,如果不存在,就不会初始化实例。 因此,在NSAssert sharedMainScene。 虽然它已在运行时,才应进入现场情况,也就是说,它只是由该特定场景的子节点使用。

这种半单身允许访问所有场景的属性。 您还可以发送现场可以传输到其他节点的消息。 场景中所需要排队的物理对象被删除,但不能碰撞时的处理本身被删除。

如果这单困扰你,总有摆脱导演的现场运行的可能性:

MainScene* mainScene = (MainScene*)[CCDirector sharedDirector].runningScene;

你应该小心铸造到MainScene只有在runningScene确实是一个MainScene对象。 一个isKindOfClass:检查或断言是为了。



文章来源: Cocos2d: 6 doubts on usage of CCSpriteBatchNode