Thursday, June 12, 2014

HowTo: Implement a Delegate Pattern to communicate between a SpriteKit Scene and the parent ViewController

Welcome to Part 10 of my blog series about game development.


Today I'll show how to use a delegate pattern to communicate with the ViewController which contains our Scene. You can download the project from GitHub: v0.7 if you haven't completed part 8.

One of the most important characteristics of this pattern is 'Inversion of control'. The goal of this principle is to remove dependencies between objects. The main idea is that a 'delegator' object 'delegates' the execution a task to a 'delegate object'. You can find multiple definitions and tutorials about the Delegate Pattern. Therefore I'll not explain the pattern itself, but show how you can use it for the following Situation:



After creating a new SpriteKit project you typically have a ViewController which has a reference to a SKScene object:

The ViewController presents the screen and starts the game. This works fine as long as the game lasts. But what can you do, if the game is over?


Here comes the Delegate Pattern:   


First of all you have to specify a protocol with the methods 'gameStop' and 'gameOver' in 'GameScene.h':

@protocol GameSceneDelegate <NSObject>

@required
-(void) gameStop;
-(void) gameOver;

@end

The Scene object needs a property to store the reference of the Delegate in 'GameScene.h':

@property (nonatomic,strong id<GameSceneDelegate> delegateContainerViewController;


The ViewController which will act as Delegate has to implement the protocol:

@interface GameViewController : UIViewController <GameSceneDelegate>

set the delegateContainerViewController property for the Scene:

-(void)viewWillAppear:(BOOL)animated{
    ...
    // Present the scene.
    [skView presentScene:gameScene];
    gameScene.delegateContainerViewController=self;
}




GameScene and GameViewController have to call/react on the protocol methods:




Add this method to GameScene.m to notify the GameViewController with 'gameStop' and 'gameOver':

// React on Alert
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (alertView.tag==1) {
        if (buttonIndex==1) {
            // Notify Delegate
            [self.delegateContainerViewController gameStop];
        }
    } else if (alertView.tag==2) {
        // Notify Delegate
        [self.delegateContainerViewController gameOver];
    }

}


The GameViewController has to react on 'gameStop' and 'gameOver'. For example by navigating to another ViewController. Add this two methods to GameViewController.m:

-(void) gameStop {
    [self performSegueWithIdentifier: @"BackToStart" sender: self];
}
-(void) gameOver {
    [self performSegueWithIdentifier: @"AddHighScore" sender: self];
}

'performSegueWithIdentifier' navigates to another ViewController as specified in the iPhone and iPad storyboards. The only missing thing is to name the segues in the storyboards with 'BackToStart' and 'AddHighScore':









As always you can download the complete project from GitHub: v0.8

That's all for today. In my next post I'll try something with SWIFT.


Cheers,
Stefan

No comments:

Post a Comment