1

i am trying the sprite kit for the first time. just to state the obvious, I've been through the doc's but i can't quiet grasp the idea of creating multiple buttons yet. i can create the buttons alright. and they appear in my view, but i can't attach the function to them in order to point to different views. here is the code I'm using for creating the buttons and so on:

#import "Levels.h"
#import "MyScene.h"
#import "MyScene1.h"

@interface Levels ()
@property BOOL contentCreated;
@end

@implementation Levels

- (void)didMoveToView: (SKView *) view
{
    if (!self.contentCreated)
    {
        [self createSceneContents];
        self.contentCreated = YES;
    }
}

- (void)createSceneContents
{
    self.backgroundColor = [SKColor blueColor];
    self.scaleMode = SKSceneScaleModeAspectFit;
    [self addChild: [self button]];
    [self addChild: [self button1]];
    [self addChild: [self button2]];
    [self addChild: [self button3]];
}

- (SKLabelNode *)button
{
    SKLabelNode *button = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    button.text = @"Level 1";
    button.fontSize = 42;
    button.position = CGPointMake(CGRectGetMidX(self.frame),250);
    button.name = @"button";
    return button;
}
- (SKLabelNode *)button1
{
    SKLabelNode *button1 = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    button1.text = @"Level 2";
    button1.fontSize = 42;
    button1.position = CGPointMake(CGRectGetMidX(self.frame),200);
    button1.name = @"button1";
    return button1;
}
- (SKLabelNode *)button2
{
    SKLabelNode *button2 = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    button2.text = @"Level 3";
    button2.fontSize = 42;
    button2.position = CGPointMake(CGRectGetMidX(self.frame),150);
    button2.name = @"button2";
    return button2;
}
- (SKLabelNode *)button3
{
    SKLabelNode *button3 = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    button3.text = @"Level 4";
    button3.fontSize = 42;
    button3.position = CGPointMake(CGRectGetMidX(self.frame),100);
    button3.name = @"button3";
    return button3;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *button = [self nodeAtPoint:location];
    SKNode *button1 = [self nodeAtPoint:location];
    SKNode *button2 = [self nodeAtPoint:location];
    SKNode *button3 = [self nodeAtPoint:location];
    //if fire button touched, bring the rain
    if (button != nil)
    {
        button.name = nil;
        SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5];
        SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25];
        SKAction *pause = [SKAction waitForDuration: 0.5];
        SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25];
        SKAction *remove = [SKAction removeFromParent];
        SKAction *moveSequence = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]];
        [button runAction: moveSequence completion:^{
            SKScene *spaceshipScene  = [[MyScene alloc] initWithSize:self.size];
            SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.5];
            [self.view presentScene:spaceshipScene transition:doors];
        }];
    }

    if (button1 != nil)
    {
        button1.name = nil;
        SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5];
        SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25];
        SKAction *pause = [SKAction waitForDuration: 0.5];
        SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25];
        SKAction *remove = [SKAction removeFromParent];
        SKAction *moveSequence1 = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]];
        [button runAction: moveSequence1 completion:^{
            SKScene *spaceshipScene1  = [[MyScene1 alloc] initWithSize:self.size];
            SKTransition *doors1 = [SKTransition doorsOpenVerticalWithDuration:0.5];
            [self.view presentScene:spaceshipScene1 transition:doors1];
        }];
    }
    if (button2 != nil)
    {
        button2.name = nil;
        SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5];
        SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25];
        SKAction *pause = [SKAction waitForDuration: 0.5];
        SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25];
        SKAction *remove = [SKAction removeFromParent];
        SKAction *moveSequence2 = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]];
        [button runAction: moveSequence2 completion:^{
            SKScene *spaceshipScene2  = [[MyScene alloc] initWithSize:self.size];
            SKTransition *doors2 = [SKTransition doorsOpenVerticalWithDuration:0.5];
            [self.view presentScene:spaceshipScene2 transition:doors2];
        }];
    }
    if (button3 != nil)
    {
        button3.name = nil;
        SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5];
        SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25];
        SKAction *pause = [SKAction waitForDuration: 0.5];
        SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25];
        SKAction *remove = [SKAction removeFromParent];
        SKAction *moveSequence3 = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]];
        [button runAction: moveSequence3 completion:^{
            SKScene *spaceshipScene3  = [[MyScene alloc] initWithSize:self.size];
            SKTransition *doors3 = [SKTransition doorsOpenVerticalWithDuration:0.5];
            [self.view presentScene:spaceshipScene3 transition:doors3];
        }];
    }
}
@end

using the code above when i press the first button the scene shows up, then freezes and oh well the project would crash. i guess it has something to do with the way i declared the buttons. if i comment out the button 1 through 3 in - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method, it does load the scene fine and no crash. can some one please help me out with this. i know i am not declaring the other three buttons the right way, but i just can't seem to be able to implement them properly.

Adrian P
  • 6,479
  • 4
  • 38
  • 55
  • Is [button runAction: moveSequence1 completion: .. ] supposed to be [button1 runAction: moveSequence1 completion: ..] and same for button2 and button3? – AndyOS Feb 21 '14 at 21:19
  • @AndyOS 1, I just named them that way thinking it would make a difference. If I just change the name of the buttons to button 1,2,3, every time I press any of the buttons, all of them move and then the scene crashes. I'm open to change that code or the whole thing as long as I can get it to work. Any ideas? – Adrian P Feb 21 '14 at 23:02

2 Answers2

3

You should only assign the node once in - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event and then check which node it is, based on its name:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];

    if ([node.name isEqualToString:@"button"]) {
        [self runButtonActionOnNode:node];
    }
    else if ([node.name isEqualToString:@"button1"]) {
        [self runButtonActionOnNode:node];
    }
    else if  ([node.name isEqualToString:@"button2"]) {
         [self runButtonActionOnNode:node];
    }
    else if ([node.name isEqualToString:@"button3"]) {
         [self runButtonActionOnNode:node];
    }
}

I've also put your action code into a method, to cut down on duplication:

-(void)runButtonActionOnNode:(SKNode*) node{
    node.name = nil;
    SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5];
    SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25];
    SKAction *pause = [SKAction waitForDuration: 0.5];
    SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25];
    SKAction *remove = [SKAction removeFromParent];
    SKAction *moveSequence = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]];
    [node runAction: moveSequence completion:^{
         SKScene *spaceshipScene  = [[MyScene alloc] initWithSize:self.size];
         SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.5];
         [self.view presentScene:spaceshipScene transition:doors];
    }];
}
AndyOS
  • 3,607
  • 3
  • 23
  • 31
  • thanks a lot. works like a charm. it saves me a lot of time and removes the redundancy. thanks again man. + 1 and accepted. :) – Adrian P Feb 22 '14 at 14:31
1

I wrote an answer creating a class specific for being used as buttons. It is available here and allows you to set images for the selected and normal states of the button, as well as the methods to be called for touch up inside events and touch down inside events. I think it will be easier for you to create your buttons as instances of this class, and then assign the part the moves to a new scene inside separate methods and set them as the actions called for the events. You don't even have to mess with touchesBegan when you use this class.

Community
  • 1
  • 1
Andrew97p
  • 565
  • 6
  • 11
  • I saw the class you made. Pretty nifty. How would you go about implementing the buttons in skview and referencing the class? By the way up voted your post. – Adrian P Feb 22 '14 at 03:13
  • @XCodeMonkey `#import "SKBButtonNode.h"` and create the node. `SKBButtonNode *button = [[SKBButtonNode alloc] initWithImageNamedNormal:normalImage selected:selectedImage]; button.position = position; [button setTouchUpInsideTarget:self action:@selector(actionToBeCalledWhenButtonPressed)];` Then you would define the method `actionToBeCalledWhenButtonPressed` it should return `void` – Andrew97p Feb 22 '14 at 18:51
  • thanks, I will definitely try that since I am still exploring the spritekit. +1 for a good handy Class bro.:) – Adrian P Feb 23 '14 at 06:01