65427

creating buttons in skview to point to different scenes

Question:

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.

Answer1:

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]; }]; }

Answer2:

I wrote an answer creating a class specific for being used as buttons. It is available <a href="https://stackoverflow.com/questions/20010331/correct-way-to-creat-button-in-sprite-kit/21831287#21831287" rel="nofollow">here</a> 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.

Recommend