1

I started experimenting with Cocos2D with Tiled, and had the player sprite and actions coded within a CCLayer along with everything else. Before continuing on, I wanted to subclass the player into a CCLayer, which I hope is correct.

My header and main code is as follows:

HeroClass.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface HeroClass : CCLayer {
    CCSprite *_hero;
    CCAction *_heroSpriteFlyAction;

}

@property(nonatomic, retain) CCSprite *hero;
@property(nonatomic, retain) CCAction *heroSpriteFlyAction;

@end

HeroClass.m

#import "HeroClass.h"

@implementation HeroClass

@synthesize hero =_hero;
@synthesize heroSpriteFlyAction = _heroSpriteFlyAction;

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

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"heroTestSheet.plist"];

    CCSpriteBatchNode *heroSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"heroTestSheet.png"];

    [self addChild:heroSpriteSheet];

    NSMutableArray *heroSpriteFlyAnimFrames = [NSMutableArray array];
    for(int i = 1; i <= 2; ++i) {
        [heroSpriteFlyAnimFrames addObject:
         [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
          [NSString stringWithFormat:@"heroFrame%d.png", i]]];
    }

    CCAnimation *heroSpriteFlyAnim = [CCAnimation animationWithFrames:heroSpriteFlyAnimFrames delay:0.03f];

    self = [CCSprite spriteWithSpriteFrameName:@"heroFrame1.png"];  

    _heroSpriteFlyAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:heroSpriteFlyAnim restoreOriginalFrame:NO]];
    [self runAction:_heroSpriteFlyAction];

    [heroSpriteSheet addChild:self];


    return self;
}

- (void) dealloc{
    self.hero = nil;
    self.heroSpriteFlyAction = nil;
    [super dealloc];
}

@end

I think the idea I want to achieve is that I can access things in this class as properties in other files. The code above gives no errors when I build it, but maybe I didn't do something right. The problem I'm having with the migration is what is happening now in my CCLayer class DebugZoneLayer, which creates the map and is supposed to add my player sprite but is giving me errors.

In DebugZoneLayer.h I imported the HeroClass.h and made a pointer from the HeroClass of the hero sprite and gave it a property. No errors here but it may be the start of where I'm going wrong:

#import "cocos2d.h"
#import "HeroClass.h"
@class HeroClass;

// DebugZone Layer
@interface DebugZoneLayer : CCLayer {

    HeroControl *heroControl;

    HeroClass *hero;    

    CCTMXTiledMap *theMap;
    CCTMXLayer *blocksCollidable;
    CCTMXLayer *invisiblePropertiesLayer;   
}


@property(nonatomic, retain) CCSprite *hero;

In DebugZoneLayer.m, when I synthesize hero, it gives the error "Type of property 'hero' does not match type of ivar 'hero'

@synthesize hero;

The rest of the file gives me more errors related to anything referencing hero, but at least that's where it starts.

EDIT (updated)

Just wanted to mention, since this was solved I cleared up some major issues in HeroClass.m which was causing a crash:

#import "HeroClass.h"

@implementation HeroClass

@synthesize heroSprite =_heroSprite;
@synthesize heroSpriteSheet =_heroSpriteSheet;
@synthesize heroSpriteFlyAction = _heroSpriteFlyAction;

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

    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"heroTestSheet.plist"];

    _heroSpriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"heroTestSheet.png"];

    //[self addChild:_heroSpriteSheet];

    NSMutableArray *heroSpriteFlyAnimFrames = [NSMutableArray array];
    for(int i = 1; i <= 2; ++i) {
        [heroSpriteFlyAnimFrames addObject:
         [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
          [NSString stringWithFormat:@"heroFrame%d.png", i]]];
    }

    CCAnimation *heroSpriteFlyAnim = [CCAnimation animationWithFrames:heroSpriteFlyAnimFrames delay:0.03f];

    _heroSprite = [CCSprite spriteWithSpriteFrameName:@"heroFrame1.png"];  

    _heroSpriteFlyAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:heroSpriteFlyAnim restoreOriginalFrame:NO]];
    [self runAction:_heroSpriteFlyAction];

    [_heroSpriteSheet addChild:_heroSprite];


    return self;
}

- (void) dealloc{
    self.heroSprite = nil;
    self.heroSpriteSheet = nil;
    self.heroSpriteFlyAction = nil;
    [super dealloc];
}

@end
Chewie The Chorkie
  • 4,896
  • 9
  • 46
  • 90

2 Answers2

2

This is not 100% related to your problem .. but you have another issues with your properties.

You define your property as retain, and you release it in the dealloc function, but actually you never retain the object.

_heroSprite = [CCSprite spriteWithSpriteFrameName:@"heroFrame1.png"];

at this position the _heroSprite variable contains the sprite with autorelease enabled... you don't retain it.

Of course you don't loose it, because it will get retained by this line:

[heroSpriteSheet addChild:_heroSprite];

but it will get released when the child is removed from the sheet.

so this is unnecessary in dealloc: self.heroSprite = nil; and [_heroSprite release]; would even crash your code.

As said before, the code works, but when you look over it later, you might get confused.

You should declare the proberty as (nonatomic, assign) or retain it properly with

self.herosprite = [CCSprite spriteWithSpriteFrameName:@"heroFrame1.png"];
Bastian
  • 10,403
  • 1
  • 31
  • 40
1

Trying changing your property in the DebugZoneLayer class from:

@property(nonatomic, retain) CCSprite *hero;

To:

@property(nonatomic, retain) HeroClass *hero;
Michael Fredrickson
  • 36,839
  • 5
  • 92
  • 109