user1843954
user1843954

Reputation: 31

SpriteKit Animation Issue

I am having an issue with the sprite animation in my game.

In the current code posted below, the sprite will show on the screen but does not do the walking animation; it is only a static frame of one of the images in the walk cycle.

The init function:

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize: size]) {
        self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];

        // Create the game nodes
        // Background
        _backgroundNode = [self createBackgroundNode];
        [self addChild: _backgroundNode];

        // Foreground
        _foregroundNode = [SKNode node];
        [self addChild: _foregroundNode];

        // Add the Player
        _thePlayer = [self createPlayer];
        [_foregroundNode addChild:_thePlayer];
        [self walkingQueen];

    }
    return self;
}

Function creating the player / filling in the animation array:

-(SKSpriteNode *)createPlayer
{
    SKSpriteNode *playerNode = [SKSpriteNode node];
    //SKSpriteNode *_player = [SKSpriteNode node];

    NSMutableArray *walkFrames = [NSMutableArray array];
    SKTextureAtlas *queenAnimatedAtlas = [SKTextureAtlas atlasNamed: @"QueenSprites"];

    SKTexture *walk1 = [queenAnimatedAtlas textureNamed:@"queen7"];
    SKTexture *walk2 = [queenAnimatedAtlas textureNamed:@"queen8"];
    SKTexture *walk3 = [queenAnimatedAtlas textureNamed:@"queen9"];

    walkFrames[0] = walk1;
    walkFrames[1] = walk2;
    walkFrames[2] = walk3;

    _queenWalkingFrames = walkFrames;

    /*
    int numImages = 9;
    for (int i = 7; i <= numImages; i++) {
        NSString *textureName = [NSString stringWithFormat:@"queen%d", i];
        SKTexture *temp = [queenAnimatedAtlas textureNamed: textureName];
        [walkFrames addObject: temp];
    }
    */
    //_queenWalkingFrames = walkFrames;

    SKTexture *temp = _queenWalkingFrames[0];
    SKSpriteNode *_player = [SKSpriteNode spriteNodeWithTexture:temp];
    _player.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    //[self addChild:_player];
    //[self walkingQueen];

    [playerNode addChild:_player];
    [self walkingQueen];

    return playerNode;
}

And the function for starting the walk animation:

-(void)walkingQueen
{
    for (int i = 0; i < _queenWalkingFrames.count; i++) {
        if (_queenWalkingFrames[i] == NULL) {
            NSLog(@"ERROR!");
        }
    }

    [_thePlayer runAction:[SKAction repeatActionForever:
                        [SKAction animateWithTextures:_queenWalkingFrames
                                         timePerFrame:0.1f
                                               resize:NO
                                              restore:YES]] withKey:@"walkingInPlaceQueen"];

    //return;
}

I played around with the code a bit and the animation DOES work IF I ignore the concept of layers (background / foreground layers) and stick the creation of the player into the init function (basically taking what's inside the createPlayer() and sticking it inside initWithSize()).

I do need to have the layers for my game and everything seems like it should work; had no idea that moving a few lines of code into its own function block would create such an issue. The check inside the walkingQueen() function did not return any errors so I assume my array has been filled with the sprite images.

Upvotes: 0

Views: 239

Answers (2)

user1843954
user1843954

Reputation: 31

Re-wrote the createPlayer() function. Correct implementation is much simpler and as follows:

-(SKSpriteNode *)createPlayer
{
    NSMutableArray *walkFrames = [NSMutableArray array];
    SKTextureAtlas *queenWalkingAtlas = [SKTextureAtlas atlasNamed:@"QueenSprites"];

    SKTexture *walk1 = [queenWalkingAtlas textureNamed:@"queen7"];
    SKTexture *walk2 = [queenWalkingAtlas textureNamed:@"queen8"];
    SKTexture *walk3 = [queenWalkingAtlas textureNamed:@"queen9"];

    walkFrames[0] = walk1;
    walkFrames[1] = walk2;
    walkFrames[2] = walk3;

    _queenWalkingFrames = walkFrames;

    SKTexture *temp = _queenWalkingFrames[0];
    _thePlayer = [SKSpriteNode spriteNodeWithTexture:temp];
    _thePlayer.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    return _thePlayer;
}

Basically doing as the post above suggested, get rid of the ivars, use the function ONLY to fill the array with the appropriate images. Then, in the init function, call createPlayer(), add it to the foreground layer, and then call walkingQueen().

Upvotes: 0

CodeSmile
CodeSmile

Reputation: 64477

    _thePlayer = [self createPlayer];

This means _thePlayer is nil until after the createPlayer method returns. Thus in the walkingQueen method _thePlayer is nil and the actions don't run.

Replace this:

SKSpriteNode *playerNode = [SKSpriteNode node];

with

_thePlayer = [SKSpriteNode node];

and use _thePlayer instead of playerNode. You can also skip returning and assigning it, it's an ivar after all.

Upvotes: 1

Related Questions