Making SpriteSheets Work cocos2d

148 Views Asked by At

So I’ve been working on my cocos2d game for a little while now just using a static one frame sprite because I hadn’t gotten the graphics for the full spritesheet yet. Now I have the spritesheet, and am having trouble implementing it.

The way I currently make my “Player” (the sprite) is by having a separate player class, shown below

Player.h

@interface Player : CCSprite{
CCAction *_WalkAction;
}
@property (nonatomic, assign) CCAction *WalkAction;
@property (nonatomic, assign) CGPoint velocity;
@property (nonatomic, assign) CGPoint desiredPosition;
@property (nonatomic, assign) BOOL onGround;
@property (nonatomic, assign) BOOL forwardMarch;
@property (nonatomic, assign) BOOL mightAsWellJump;
@property (nonatomic, assign) BOOL isGoingLeft;

-(void)update:(ccTime)dt;
-(CGRect)collisionBoundingBox;

@end

And Player.m (I won’t show the full thing, because it’s pretty long, it just defines everything about the character)

-(id)initWithFile:(NSString *)filename {
if (self = [super initWithFile:filename]) {
    self.velocity = ccp(0.0, 0.0);
}
return self;
}

  //THIS IS ONLY A FRACTION OF MY UPDATE METHOD, THE REST OF IT IS ALL SETTING VELOCITY AND WHATNOT FOR MY PHYSICS ENGINE, BUT THIS IS THE ONLY RELEVANT PART
-(void)update:(ccTime)dt {
if (self.forwardMarch) {
        self.velocity = ccpAdd(self.velocity, forwardStep);
 //[self runAction: _WalkAction];
    }    
}

Now in my GameLevelLayer.m I init the sprite like this (This is where we get filename from from the init in player.m):

//In my init
map = [[CCTMXTiledMap alloc] initWithTMXFile:@"level1.tmx"];
    [self addChild:map];

 player = [[Player alloc] initWithFile:@"banker1.png"];
    player.position = ccp(100, 50);
    [map addChild:player z:15];

So that all works perfectly fine. The problem comes when I try to turn that sprite into a sprite with a spritesheet. So I try to do this in player.m

-(id)initWithFile:(NSString *)filename {
if (self = [super initWithFile:filename]) {

    self.velocity = ccp(0.0, 0.0);

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

    CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"BankerSpriteSheet_default.png"];
    [self addChild:spriteSheet];

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

        CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];
        self = [CCSprite spriteWithSpriteFrameName:@"banker1.png"];

//HERE IS WHERE self.WalkAction IS DEFINED

        self.WalkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
        [spriteSheet addChild:self];
    }

}
return self;
}

//And then run it in my update method

if (self.forwardMarch) {
        self.velocity = ccpAdd(self.velocity, forwardStep);
    [self runAction: _WalkAction];

}

Just for reference, self.forwardMarch is a bool that is set every time the user pushes the button to move the player, so whenever its true I move the player like this.

But when I try this I get the error

'NSInvalidArgumentException', reason: '-[CCSprite setWalkAction:]: unrecognized selector sent to instance 0x88fab50'

Any Help is appreciated.

I also posted this on the cocos2d forums if you like their code display system more (color coded and whatnot) http://www.cocos2d-iphone.org/forums/topic/making-spritesheets-work/

EDIT:

Okay so I have made a little progress, but I'm still a bit stuck. I've defined the batchnodes and all the actions in the init of GameLevelLayer.m

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

    CCSpriteBatchNode *spriteSheet = [CCSpriteBatchNode batchNodeWithFile:@"BankerSpriteSheet_default.png"];
    [self addChild:spriteSheet];
    [player addChild:spriteSheet];

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

        CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];
        player = [[Player alloc] initWithSpriteFrameName:@"banker1.png"];
        player.WalkAction = [CCRepeatForever actionWithAction:[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:NO]];
        //[spriteSheet addChild:player];
    }

    //player = [[Player alloc] initWithFile:@"koalio_stand.png"];
    player.position = ccp(100, 50);
    player.scale = 0.2;
    [map addChild:player z:15];

And then in my Player.m I run

[self runAction: self.WalkAction];
//I've also tried [self runAction: _WalkAction]; The result is the same

I used NSLogs to find out that the above section ([self runAction: self.WalkAction]; is being called but not finishing. This is where my crash happens, but there is NO ouput to the console as to why there is a crash.. literally just says (lldb)

1

There are 1 best solutions below

5
CodeSmile On

The problem is one line above the actual error. You assign self with the result from [CCSprite spriteWith...] which replaces the existing self and replaces it with a CCSprite. Instead change the init line to self = [super initWithSpriteFrameName:..]