How To Make a Letter / Word Game with UIKit: Part 3/3

This third and final part of the series will be the most fun of them all! In this part, you’re going to be adding a lot of cool and fun features By Marin Todorov.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

What’s On the Menu

The gameplay is complete, but the player can only play Level 1, and cannot choose to solve more difficult anagrams. So your last task for this tutorial is to add a game menu.

Inside ViewController.m, near the top of the file, change the private interface declaration line to look like this:

@interface ViewController () <UIActionSheetDelegate>

This declares that your class conforms to the UIActionSheetDelegate protocol. You need to do this because you’ll be presenting the difficulty choices with a UIActionSheet.

Add the following method in ViewController.m:

#pragma mark - Game manu
//show the level selector menu
-(void)showLevelMenu
{
    UIActionSheet* action = [[UIActionSheet alloc] initWithTitle:@"Play @ difficulty level:"
                                                        delegate:self
                                               cancelButtonTitle:nil
                                          destructiveButtonTitle:nil
                                               otherButtonTitles:@"Easy-peasy", @"Challenge accepted" , @"I'm totally hard-core", nil];
    [action showInView:self.view];
}

The above method simply shows a UIKit action sheet with the three difficulty levels:

  • Easy-peasy
  • Challenge accepted
  • I’m totally hard-core

These levels are loaded from the three .plist level config files.

You would like to show the game menu as soon as the game appears on the screen, so add the following implementation of viewDidAppear: in ViewController.m:

//show tha game menu on app start
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self showLevelMenu];
}

This calls showLevelMenu to display the menu to the user.

Now you need to decide what to do when the player selects a level. It’s not hard – just load the .plist file, call dealRandomAnagram, and everything should work by itself!

Give it a try. Add the following method to ViewController.m:

//level was selected, load it up and start the game
-(void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    //1 check if the user tapped outside the menu
    if (buttonIndex==-1) {
        [self showLevelMenu];
        return;
    }
    
    //2 map index 0 to level 1, etc...
    int levelNum = buttonIndex+1;
    
    //3 load the level, fire up the game
    self.controller.level = [Level levelWithNum:levelNum];
    [self.controller dealRandomAnagram];
}

This implements one of the methods in the UIActionSheetDelegate protocol.

  1. It checks if the passed buttonIndex equals -1. If so, that means the player tapped outside the menu, in which case, just show the menu again.
  2. Find the level number by adding 1 to the given buttonIndex. You do this because you numbered your level files level1.plist, level2.plist, etc., but buttonIndex, like other indices in Objective-C, starts at 0.
  3. Finally, you create a new Level instance for the selected level, assign it to the game controller and call dealRandomAnagram on the game controller.

Woop, woop!

Build and run the project. You’ll see that you have things a bit mixed up – the game appears with an anagram already loaded, while the player still sees the menu:

To make matters worse, if you choose an item from the menu, it displays it on top of the existing anagram!

an_needs_clearing

To fix the first problem, scroll inside ViewController.m, find these two lines inside viewDidLoad and delete them:

self.controller.level = level1;
[self.controller dealRandomAnagram];

In the same method, but a bit above, also delete this line:

Level* level1 = [Level levelWithNum:1];

These were all test code chunks that you no longer need.

Build and run again. Now the player sees the menu first, and when they choose the difficulty level the game starts. Nice!

But now, when the game is over the player cannot go back to the menu screen. And if they do, we already saw that the new anagram will display right on top of the old one!

You could make the ViewController be a delegate of GameController, so that when the game is over GameController could send a message straight to ViewController. That would be overkill for this situation, however. And since you want to know tricks for flexible game design with UIKit, why don’t you add a block to show the game menu that gets executed upon game completion.

Open up GameController.h and add the following:

//just under the imports at the top and above the interface declaration
typedef void (^CallbackBlock)();

//with other properties
@property (strong, nonatomic) CallbackBlock onAnagramSolved;

You first declare a new block type that does not take arguments or return a result. This makes your property declaration code look cleaner. You then create a property that gives your GameController access to a block of the newly-defined type.

Now switch to GameController.m. First, add the following helper method that you’ll call between levels:

//clear the tiles and targets
-(void)clearBoard
{
    [_tiles removeAllObjects];
    [_targets removeAllObjects];
    
    for (UIView *view in self.gameView.subviews) {
        [view removeFromSuperview];
    }
}

The method removes all tiles and targets from the controller and the view. You’ll use this to fix the problem you saw earlier, where new anagrams are displayed on top of old ones.

Inside checkForSuccess, find the line [stars removeFromSuperview];. This is when the final win animation ends. Just below that line, but still inside the block where it is located, add:

//when animation is finished, show menu
[self clearBoard];
self.onAnagramSolved();

Here you call clearBoard to clean up between levels, and then you call the callback block stored in onAnagramSolved.

And finally, add the end-game code block! Switch for the last time to ViewController.m and at the end of viewDidLoad, add:

__weak ViewController* weakSelf = self;
self.controller.onAnagramSolved = ^(){
    [weakSelf showLevelMenu];
};

Very simple and elegant! You create a weak reference to the ViewController instance, then you set the game controller onAnagramSolved block to call showLevelMenu.

Build and run one last time:

Your finished letter / word game with UIKit!

Congratulations, you have made a complete and polished letter / word game with UIKit!

Where to Go from Here?

Here is a link to the final source code for the tutorial.

You made it! It was a long tutorial, but you learned a ton of cool stuff.

The game is complete, but there are all sorts of ways you could expand it. Here are some ideas off the top of my head:

  • Think about how to make this game (or your own) multi-player via Game Center.
  • You could also simply implement leaderboards via Game Center.
  • Add more explosions, more levels and more anagrams.
  • Implement score tracking for different players. You could load and save scores from a plist or JSON file.

That’s all for today. Thanks for sticking with this tutorial, and do leave a comment!

Contributors

Over 300 content creators. Join our team.