Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm making a game in objective-c using cocos2d. I have the following:

@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

Now in the layer I would do:

//...
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];
    }
}

However, you can only add CCSprite to the spritebatchnode, that way I can't update my custom classes. What do I have to do?

share|improve this question

2 Answers 2

up vote 2 down vote accepted

I think you have a flaw in your architecture there. The Player should not be a subclass of CCNode (or any cocos2d node class for that matter).

The CCNode is only the visual representation of your player-character, therefore your Player class should have a CCNode as member (or property as it's called in Objective-C). This makes your architecture much more flexible. You could implement a component-based architecture, where your node is part of a "VisualComponent", or you could have an inheritance-based architecture where you inherit from a "GameEntity" base-class etc. But inheriting from CCNode is a bad idea and will definitely hurt you in the long run.

Update: As requested in the comments, here's a short guide how you could refactor your code using a Player class that inherits from NSObject and implements a GameEntity Protocol. For a more complete documentation of protocols, read the Objective-C docs.

Protocols are much like interfaces known from other programming-languages. A very simple protocol could look like this:

#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

Your Player class could then be implemented like this:

#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

And finally in your "Level" or "Game-World" you would have something like the following (note that you could also move the initialization of the player-node to the players init method, but it's easier to keep everything "outside" so you could read stuff from a data-file etc.):

// 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];
    }
}
share|improve this answer
    
Well, I read a lot and people say it's better composition than inheritance based games in cocos2d. –  marcg11 Dec 9 '11 at 14:39
1  
But what you're doing is inheritance based. You're inheriting from CCNode and that's clearly less composition than having a player class that has a CCNode as a property. –  bummzack Dec 9 '11 at 14:40
    
So what does the player class has to be? Just an NSObject? What's the point in adding a CCNode as a propery if I already have a CCSprite. I still won't be able to add my class to the spritebatchnode. –  marcg11 Dec 9 '11 at 14:45
    
Yes, you inherit from NSObject. Then you have Player.node which is your CCNode and you set that to your sprite-batchnode. You could also have a GameEntity Protocol which will be implemented by your game-entity-classes, so you can easily update all your game-entities in a loop. –  bummzack Dec 9 '11 at 14:50
    
OK, I could also use an Array and add all my objects and update this array instead of the spritebatchnode too... –  marcg11 Dec 9 '11 at 14:58

you can add any class inherited from of CCNode as a child of another CCNode instance.

player is a inherited from CCNode and CCLayer is also inherited from CCNode, so there is no need for a CCSpriteBatchNode instance in there, you can directly add player instance to your layer!

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

CCSpriteBatchNode provides better performance only to render multiple sprites with same texture, so if player does not use same texture as other objects in the scene you can't use an sprite batch! but you can define player class to inherit CCSprite instead of CCNode. this way you can attach it to the existing sceneSpriteBatchNode object.

share|improve this answer
    
Not if he's using a batch node.. which is preferable for better performance. Also you wouldn't add children inside the update loop. –  bummzack Dec 11 '11 at 10:13
    
@bummzack batch node is only providing better performance if player shares the same texture as other objects in the scene! –  Ali.S Dec 11 '11 at 12:17
    
Yup, I'm using spriteBatchNode. I'm rendering 70 sprites aprox.. –  marcg11 Dec 11 '11 at 12:26

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.