Make App Pie

Training for Developers and Artists

SlippyFlippy 1.1: Making a High and Low Score Indicator

icon2_120This is the first of my improvements to the SlippyFlippy penguin game.  While this may not make sense since I have not posted all the game code yet, it might help those trying to come up with some of these solutions for their own games. While playing against  some of my friends on our different devices, we found we need a different score for the hard mode and easy mode. In the hard mode, the game ends if the penguin contacts the top or bottom walls.  In the easy mode the penguin bounces off the top and bottom walls.

There is a bit of a real estate problem about putting two scores on the screen.  The solution is to fade in one high score, then fade it out, then fade the other one in, then fade that one out. This repeats forever.

My current code for changing the label looks like this:

highScoreLabel.text = [NSString stringWithFormat:@"High Score: %li",(long)highScore];

It’s just setting the labels text.  This shows up at setup and game over. Since it shows up in two places, I’ll make a method for the animation. Before I do, I need to find and store the high score. I look at the game over code in update:

if (highScore < score ){
highScore = score;
highScoreLabel.text = [NSString stringWithFormat:@"High Score: %li",(long)highScore];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:highScore forKey:@"highScore"];
[defaults synchronize];

}

If we have a high score, we do two things. We first display the new high score, and secondly we save the new high score to NSUserDefaults.  I introduced an new NSInteger called highScoreHard. With this addition, there are two situations instead of one where we need to process a high score, so the if has to reflect both:

if ((highScore < score && isEasyMode) || (highScoreHard < score && !isEasyMode)){

The BOOL isEasyMode is set when we select the mode we want to use. If we are in easy mode and there is a new high score, or if we are in hard mode and we have a new high score,  we need to post a new high score. We can now use isEasyMode to post the score to the right place:

if (isEasyMode)
highScore = score;
else
highScoreHard = score;

Our last change to the game over code is to add another key entry to the NSUserDefaults entries under defaults.

[defaults setInteger:highScoreHard forKey:@"highScoreHard"];

If we stub our animation method in makeHighScoreAnimate  for the moment, this snippet of code changes to:

if ((highScore < score && isEasyMode) || (highScoreHard < score && !isEasyMode)){
if (isEasyMode)
highScore = score;
else
highScoreHard = score;

[self makeHighScoreAnimate];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:highScore forKey:@"highScore"];
[defaults setInteger:highScoreHard forKey:@"highScoreHard"];
[defaults synchronize];

}

We now need to read the high scores when we start the app in initwithSize:.  We have another entry in defaults with a new key. That segment of code in initwithSize: looks like this now:

//grab the last high score from persistent memory
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
highScore = [defaults integerForKey:@"highScore"];
highScoreHard = [defaults integerForKey:@"highScoreHard"];
[self makeHighScoreAnimate];

We have one more thing to do and that is make the animation code.

-(void)makeHighScoreAnimate{
//remove the old high score animation, if there
[highScoreLabel removeActionForKey:@"highScoreAnimate"];

//makes strings for the two scores
NSString *highScoreLabelText = [NSString stringWithFormat:@"Easy High: %li",(long)highScore];
NSString *highScoreLabelHardText = [NSString stringWithFormat:@"Hard High: %li",(long)highScoreHard];
//Create the animation sequence and run it forever.
SKAction *highScoreAnimateSequence = [SKAction sequence:@[
[SKAction runBlock:^{highScoreLabel.text = highScoreLabelText;}],
[SKAction fadeInWithDuration:1.00],
[SKAction waitForDuration:3.0],
[SKAction fadeOutWithDuration:1.0],
[SKAction runBlock:^{highScoreLabel.text = highScoreLabelHardText;}],
[SKAction fadeInWithDuration:1.00],
[SKAction waitForDuration:3.0],
[SKAction fadeOutWithDuration:1.0],
]];
SKAction *highScoreAnimate = [SKAction repeatActionForever:highScoreAnimateSequence];

//put the action in the label
[highScoreLabel runAction:highScoreAnimate withKey:@"highScoreAnimate"];
}

We remove the old high score first. If there is no SKaction there, it will do nothing.  To make the coding easier to read,  we make two strings highScoreLabelText and highScoreLabelHardText to hold the two high scores and titles.  We make an SKAction sequence, which is an array of SKActions. If you have something other than an SKAction that you want to do, you can add it in a runBlock: method, as we did with changing the titles.  I then take the sequence and repeat it forever.

I run the SKAction to the highScoreLabel and give it a key so I can remove it when I need to change it.  Now when I build and run, the two high scores fade in and out.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: