使用CCSpriteBatchNode的Cocos2d组合

我使用cocos2d在objective-c中制作游戏。 我有以下几点:

@interface Player : CCNode { CCSprite *mySprite; CCSpriteBatchNode *sceneSpriteBatchNode; //... } @property (nonatomic,retain) CCSprite *mySprite; - (id)initWithSpriteBatch:(CCSpriteBatchNode *)_spn; -(void)updateStateWithDeltaTime:(ccTime)deltaTime andListOfGameObjects:(CCArray*)listOfGameObjects; @end @implementation Player - (id)initWithSpriteBatch:(CCSpriteBatchNode *)_spn { self = [super init]; if (self) { sceneSpriteBatchNode = _spn; mySprite = [CCSprite spriteWithSpriteFrameName:@"player_image.png"]; [_spn addChild:mySprite]; } return self; } //.... @end 

现在在图层中,我会做:

 //... Player *player = [[Player alloc] initWithSpriteBatch:sceneSpriteBatchNode]; [player release]; -(void) update:(ccTime)deltaTime { CCArray *listOfGameObjects = [sceneSpriteBatchNode children]; for (CCNode *tempChar in listOfGameObjects) { [tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:listOfGameObjects]; } } 

但是,您只能将CCSprite添加到spritebatchnode,这样我无法更新我的自定义类。 我需要做什么?

我认为你在那里的建筑有一个缺陷。 玩家不应该是CCNode的子类(或者任何cocos2d节点类)。

CCNode只是你的player-character的可视化表示,因此你的Player类应该有一个CCNode作为成员(或者Objective-C中调用的属性)。 这使得你的架构更加灵活。 你可以实现一个基于组件的架构,其中你的节点是“VisualComponent”的一部分,或者你可以有一个基于inheritance的架构,从“GameEntity”基类inheritance。但是从CCNodeinheritance是一个坏主意从长远来看肯定会伤害你。

更新:根据评论的要求,这里有一个简短的指南,你可以使用一个从NSObjectinheritance的Player类来实现GameEntity协议来重构你的代码。 要获得更完整的协议文档,请阅读Objective-C文档 。

协议非常类似于其他编程语言已知的接口。 一个非常简单的协议可能是这样的:

 #import "cocos2d.h" /** Protocol for a game entity */ @protocol GameEntityProtocol<NSObject> /** Visual representation of the entity */ @property(assign) CCNode* node; /** Update method */ -(void) update:(ccTime)dt; @end 

您的Player类可以像这样实现:

 #import "GameEntityProtocol.h" // Player interface @interface Player : NSObject<GameEntityProtocol> { // player related members } @end // Player implementation @implementation Player @synthesize node; -(void) dealloc { [self setNode: nil]; [super dealloc]; } -(void) update:(ccTime)dt { // do something.. update node position etc. } @end 

最后在你的“关卡”或“游戏世界”中,你可能会看到类似下面的内容(注意,你也可以将玩家节点的初始化移动到玩家init方法中,你可以读取数据文件等):

 // in your init method or where you load the level // entities is a class member of type NSMutableArray* entities = [NSMutableArray arrayWithCapacity: 4]; Player *player = [[Player alloc] init]; [player setNode:[CCSprite spriteWithSpriteFrameName:@"player_image.png"]]; [sceneSpriteBatchNode addChild: player.node]; [entities addObject:player]; // update loop could look like this -(void) update:(ccTime)deltaTime { for (id<GameEntityProtocol> entity in entities) { [entity update:deltaTime]; } } 

您可以添加从CCNodeinheritance的任何类作为另一个CCNode实例的子CCNode

播放器是从CCNodeinheritance的, CCNode也是从CCNodeinheritance的,所以在这里不需要CCSpriteBatchNode实例,你可以直接将播放器实例添加到你的图层中!

 -(void) update:(ccTime)deltaTime { CCArray *listOfGameObjects = [sceneSpriteBatchNode children]; for (CCNode *tempChar in listOfGameObjects) { [tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:listOfGameObjects]; } [self addChild:player]; } 

CCSpriteBatchNode提供了更好的性能,只能渲染具有相同纹理的多个精灵,所以如果玩家不使用与场景中的其他对象相同的纹理,则不能使用精灵批处理! 但你可以定义播放器类来inheritanceCCSprite而不是CCNode 。 这样你可以将它附加到现有的sceneSpriteBatchNode对象上。