2

I'm using Sprite Kit to create my first iOS app, and I'm stumbling over what seems to be a pretty basic problem.

I'm trying to animate the contents (fillNode) of a SKCropNode (cropNode). The code below sets up the SKScene just fine (I see the illustration masked correctly, placed over the background image in the right location)...

SKSpriteNode *logoBG = [[SKSpriteNode alloc] initWithImageNamed:logoBackground];
logoBG.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
[self addChild:logoBG];

SKCropNode *cropNode = [[SKCropNode alloc] init];
cropNode.maskNode = [[SKSpriteNode alloc] initWithImageNamed:logoMask];
SKSpriteNode *fillNode = [[SKSpriteNode alloc] initWithImageNamed:logoImage];

[cropNode addChild:fillNode];
fillNode.position = CGPointMake(0,300);
cropNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
self.logoContent = cropNode;
[self addChild:self.logoContent];

...but I can't access the masked illustration to animate its position (I want it to start off outside the mask and slide into position):

CGRect screenBound = [[UIScreen mainScreen] bounds];
CGSize screenSize = screenBound.size;

SKAction *moveUp = [SKAction moveByX: 0 y: 100 duration: 5];
SKAction *moveSequence = [SKAction sequence:@[moveUp]];
[self.logoContent.target_illustration runAction: moveSequence completion:^{ // '.target_illustration' = the SKSpriteNode that I want to animate; cropNode.fillNode
    SKScene *titleScreen  = [[TitleScreen alloc] initWithSize:self.size];
    SKTransition *fade = [SKTransition fadeWithDuration:(1)];
    [self.view presentScene:titleScreen transition:fade];
}];

I can only animate the whole logoContent rather than its child nodes.

Any ideas where I'm going wrong?

MassivePenguin
  • 3,701
  • 4
  • 24
  • 46

2 Answers2

5

Just for reference if anyone wants to know how to mask, here is a simple snippet

- (void) cropNodes
{
    // the parent node i will add to screen
    SKSpriteNode *picFrame = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(100, 100)];
    picFrame.position = CGPointMake(200, 200);

    // the part I want to run action on
    SKSpriteNode *pic = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
    pic.name = @"PictureNode";

    SKSpriteNode *mask = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(80, 50)];

    SKCropNode *cropNode = [SKCropNode node];
    [cropNode addChild:pic];
    [cropNode setMaskNode:mask];
    [picFrame addChild:cropNode];
    [self addChild:picFrame];

    // run action in this scope
        //[pic runAction:[SKAction moveBy:CGVectorMake(30, 30) duration:10]];

    // outside scope - pass its parent
   [self moveTheThing:cropNode];
}

- (void) moveTheThing:(SKNode *) theParent
{
    // the child i want to move
    SKSpriteNode *moveThisThing = (SKSpriteNode *)[theParent   childNodeWithName:@"PictureNode"];
    [moveThisThing runAction:[SKAction moveBy:CGVectorMake(30, 30) duration:10]];
}
DogCoffee
  • 19,820
  • 10
  • 87
  • 120
  • The issue I had was due to the runAction being called in the didMoveToView method, while the logoContent node (and its named children) were being created in a createSceneContents method (called from didMoveToView); because of the scope, I couldn't access the named illustration node. Your solution works fine when the runAction is called in the same scope. – MassivePenguin Oct 09 '13 at 07:32
  • You didn't want to use the childNodeWithName method ? – DogCoffee Oct 09 '13 at 07:56
  • I tried it, and couldn't get it working. Blame my lack of Obj-C experience for that! – MassivePenguin Oct 09 '13 at 08:19
  • all you can do is try ... could just be a SK bug that it didnt work. I'll add an answer, see if it works – DogCoffee Oct 09 '13 at 08:41
  • Yep, your code does work... the issue I had was that my animation action was in a different scope to the nodes (they were created in a function). Moving the node creation to the same function as the animation call works, as does calling `[self.logoContent.children[0] runAction: moveSequence completion:^{`. – MassivePenguin Oct 22 '13 at 06:57
  • I wanted to move the mask rather than the masked pic. But the mask isn't found in the childNodeWithName:, but it can accessed directly. Using the example: [cropNode.maskNode moveBy:CGVectorMake(30,30) duration:10]. – VariableSquid Aug 14 '14 at 09:34
  • In my case it masks entirely all image, no spaceship visible at all – Neil Galiaskarov Jun 03 '15 at 14:20
2

Got it!

[self.logoContent.target_illustration runAction: moveSequence completion:^{

should be

[self.logoContent.children[0] runAction: moveSequence completion:^{

My illustration now moves as directed :)

MassivePenguin
  • 3,701
  • 4
  • 24
  • 46
  • Ah, thank you! I'd made the exact same mistake. You just saved me eons of confusion. Albeit 2 years ago. – Smikey Oct 29 '15 at 17:02