1.2 Tutorials: iPhone/SmartFoxTris

» Introduction

In this tutorial you'll learn how to build a multiplayer "Tic-Tac-Toe" game in iPhone using the SmartFox Objective C iPhone API. We won't however go into the iPhone SDK specific things too much and rather focus on how to use the SmartFox API, for further reference about how to do things in iPhone SDK please see the documentation included with the iPhone SDK. The code for the game will build on the previous tutorial "iPhone/Simple Chat", so we won't explain the topics covered in there, how to connect, how to login, how to handle chat, etc, either.

We'll start by loading the iPhone project iPhoneSmartFoxiPhoneClient_TicTacToe.xcodeproj.

» Lobby - Game Room List

There are two additions in the lobby from our previous tutorial. We can create a new game room with the New Game button and we can view a list of current game rooms.

In order to update the list of current rooms, we call

[rooms reloadData];

in following events

- (void)onRoomAdded:(INFSmartFoxSFSEvent *)evt {
- (void)onRoomDeleted:(INFSmartFoxSFSEvent *)evt {

to trigger the Rooms tableView interface element to load itself. When triggered, it will call numberOfRowsInSection to get the number of elements and cellForRowAtIndexPath to get the element at an index.

We get the number of rooms,

and info about the rooms,

in the callback functions.

» Creating a new game room

When the player taps the New Game button, we make a transition to the Create Game screen with the call:

[appDelegate switchToView:@"INFSmartFoxiPhoneClient_TicTacToe_CreateGameViewController" uiViewController:[INFSmartFoxiPhoneClient_TicTacToe_LobbyViewController alloc]];

Create game screen:

We then create the game with the following function:

» Joining an existing game room

When the player taps an existing room in the rooms list, the didSelectRowAtIndexPath event is raised.

We join the room with the following code:

In this code, we first find the clicked room. Then we check the room to see if it is password protected. If it is, we show an AlertPrompt to the user for entering the password. If it is not a private room we directly request joining to the room.

» Gameplay

We make the necessary initializations in the - (void)viewDidLoad event. This event is raised when a new view is added and activated in our application window.

The following code is taken from the - (void)viewDidLoad handler. We initialize some variables and store references to the clickable tile items.

We create the player room variable:

Here is where we notify our arrival into the room, and also where we can control the game flow.

To understand why, you have to check the onRoomVariablesUpdate handler:

he code above handles three possible cases:

1) we are the first user to enter the room, so we need to wait for our opponent;
2) we are playing the game but our opponent leaves the room or gets disconnected;
3) the second player has entered and we can start the game.

If only one player variable exists in the room we will show a small dialog box that will tell the user to wait his/her opponent.
This will also hanlde the case in which one of the two players exits from the room during the game. Also the game board is cleared and the moveCount is set back to zero.

If both player variables exist in the room we can set the _global.gameStarted to true, remove the dialog box and initialize the game. Player one will always move first in the first game, then the first move will be done by the client who won the previous game.

The control is then passed to the waitMove method:

The simple code above shows the turn message based on the player Id and then the application will wait for user interaction.

When a user clicks on one of the squares in the game board this code is executed:

We have two nested if(s) to check: if it's the user's turn and finally if the clicked item was not yet taken.

Each square has a "status" property that can have 3 different values:

» " ": if never clicked before
» "R": if it contains a red ball
» "G": if it contains a green ball

If the board cell is free we create ball with the user's color and invoke the moveDone method.

The moveDone function uses the sendObject API method to send the move data to our opponent:

Tapped tiles x and y values are passed to the sendObject function together with a property called "type" that can have two values:

» "move", when we're sending a game board move;
» "restart", when we're restarting the game at the end of it.

After each move is peformed the checkBoard function will loop through the board to see if there's a winner and in such case it will stop the game showing the win/lose message.

If no winner is found the nextTurn function is called:

What this does is pretty strightforward: the whoseTurn variable is inverted and then we go back to the waitMove.

At this point the game flow should be clear:

1) wait for player move;
2) check if there's a winner;
3) if no winner is found switch the active player and go back to 1 else the game is over.

Now that we've seen how the player move is sent to the opponent is time to check the code that handles the reception
of a move from the other player(s):

If the "type" property is set to "move", we display the opponent move in our board to keep all client's boards in sync.

MoveCount is incremented and the checkBoard and nextTurn methods are called, just like we did previously.

You will be able to send a "restart" command when the game finishes and you will be presented a dialog box were you can return
in the main chat area or continue playing.

The restartGame method will clear all current game values and start a new game:

When the game ends the "gameEnd" window is shown and you will be able to start a new game or just leave the room.

» Conclusions

We have analyzed some of the techniques for building a simple multiplayer turn-based game and what you have learned so far can be applied to many different types of games, not just board ones. Also the limit of two users in very game room can be expanded for games with 4, 6, 8 or more players.


doc index