Cocos2d enemy classes

Nibbie
Posts: 3
Joined: 2008.12
Post: #1
I'm new to Objective-C but have a decent level of experience with C. I stumbled across Cocos2d and am hoping to give it a try. The problem I'm having at the moment is creating a structure to handle enemies within my little test game.

I'd like to create a base enemy class and eventually use it as a parent for future enemy classes. The class would contain a pointer to a Cocos2d Sprite object as well as a few methods: death, update, etc.

The problem is, I'm not really sure how to go about it all! I've had a stab at laying the groundwork for the enemy class.

Enemy.h
Code:
#import <UIKit/UIKit.h>
#import "cocos2d.h"

@interface Enemy : NSObject {
    
    Sprite *sprite;
    
}

@end

Enemy.m
Code:
#import "Enemy.h"

@implementation Enemy

- (id) init {
    
    self = [super init];
    return self;
    
}

@end

I'm just not sure how to create an array of Enemy instances and iterate through them. I've had a stab here, but am told that sprite is declared protected.

Code:
for( int i = 0; i < MAX_ENEMIES; i++ ) {
        Enemies[i] = NULL;
    }
    
    Enemies[0] = [[Enemy alloc] init];
    Enemies[0]->sprite = [Sprite spriteWithFile: @"player.png"];

If someone could point me in the right direction, or provide some example code, I'd be very grateful. If I'm going in totally the wrong direction, please tell me! I imagine I'll be repeating whatever solution I arrive at for things like particles and other sets of data that needs period logic updates.
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #2
Right; Because sprite is protected, you need Enemy to set the sprite reference. One possibility: have a setSprite: method in the enemy class, and/or add a sprite parameter to the init method and set the member variable sprite there.

Also, if you're not using garbage collection, make sure you're doing memory management correctly. (Your sprite is autoreleased in the last bit of code, but you will want Enemy to retain it.)
Quote this message in a reply
Nibbie
Posts: 3
Joined: 2008.12
Post: #3
I've made some progress! I'd like to make sure I'm doing this stuff logically. Questions at the bottom.

Enemy.h
Code:
#import <UIKit/UIKit.h>
#import "cocos2d.h"
#import "CocosNode.h"

@interface Enemy : CocosNode {

    @public
        Sprite *sprite;
        BOOL bIsDead;
    
}

- (void)tick: (ccTime)dt;
- (void)spawn;
- (void)update;
@end

Enemy.m
Code:
#import "GameScene.h"
#import "CocosNode.h"
#import "Enemy.h"

@implementation Enemy

- (id) init {
    
    self = [super init];
    
    bIsDead = true;
    
    if (self) {
        [self schedule:@selector(tick:) interval:0.5];
    }
    
    [self spawn];
    
    return self;
    
}

-(void)tick: (ccTime)dt {
}

- (void) spawn {
    
    bIsDead = false;
    
    sprite = [Sprite spriteWithFile: @"enemy.png"];
    [sprite setPosition: cpv(rand()%300, rand()%300)];
    [self add: sprite];
    
    [sprite do:[FadeIn actionWithDuration: 1]];
    
}

- (void) update {
}

@end

To create 100 enemies, I do the following:
Code:
for( int i = 0; i < MAX_ENEMIES; i++ ) {
        Enemies[i] = [[Enemy alloc] init];
        [self add: Enemies[i]];
    }

With the Enemy CocosNode class instance added to GameLayer which is a part of GameScene.



Questions:

1) I've setup a schedule event in both GameLayer and within each instance of the Enemy class. I'm wondering whether it's better to ditch the tick within the Enemy class and just have GameLayer's tick iterate through all active enemies and call their Update method?

2) Due to my inexperience with Cocos2d, I'm not sure how to handle enemy death. I have the boolean bIsDead within the enemy class. But I'm not sure how to factor that into the rendering process. Ideally, when an enemy dies, I'd like to set bIsDead = true, and then only render enemies where bIsDead = false. At the moment, the only way I can find to stop an enemy from rendering is to remove it from the GameLayer CocosNode, like so:

Code:
[self remove: Enemies[i]];

I'm not sure if this is intended behaviour?

3) As FreakSoftware mentioned, I'd like to make sure everything is neat, memory allocation-wise. Right now my GameLayer class' dealloc method looks like so:

Code:
- (void)dealloc {
    
    for( int i = 0; i < MAX_ENEMIES; i++ ) [Enemies[i] release];
    [super dealloc];
        
}

But I'm not entirely sure whether that's wise or not! Specifically:

Quote:(Your sprite is autoreleased in the last bit of code, but you will want Enemy to retain it.)

How can I avoid this? I'm guessing Cocos2d has some kind of texture manager so that calls to spriteWithFile aren't actually loading the same sprite into memory for each enemy?

Any and all help appreciated!
Quote this message in a reply
Member
Posts: 93
Joined: 2008.11
Post: #4
Dear NialG,
You really should read some book about Object oriented programming. Try Obj-C or C++ for instance. Object oriented programming is based on encapsulation which is hiding internals of an object (Enemy in your case). You should not make everything public and accessible to the whole application. Try setting things up in a way where you hide everything possible.
Quote this message in a reply
Nibbie
Posts: 3
Joined: 2008.12
Post: #5
godexsoft, I'm aware that I should (and will) eventually setup a few getter and setter methods for various variables within my Enemy class. I'm confident as to how I'd go about that. So at the moment, I'm really trying to get guidance with regards to my other questions.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Split Obj-C classes into multiple files Gillissie 18 9,635 Nov 24, 2009 02:19 PM
Last Post: Gillissie
  Enemy movement like in the 80's MikeD 4 3,163 Apr 16, 2009 03:46 AM
Last Post: MikeD