Showing posts with label Tutorials. Show all posts
Showing posts with label Tutorials. Show all posts

Sunday, September 30, 2012

Tutorial 19 - Integrating Game Centre (Part 1)

19.1 Game Center

   
Game Center is Apple’s social gaming network. Integrating Game Center functionality into your Codea App has to be done in Xcode. There are three main areas that we need to concern ourself with to implement Game Center:

  1. Players;
  2. Scores; and
  3. Achievements.

All of your metadata for Game Center functionality is set up and managed in iTunes Connect, allowing you to test your Game Center features before submitting your app to the App Store. You use iTunes Connect to enable your app for Game Center testing, and set up your leaderboards and achievements. Then use the Game Kit framework in your app to add Game Center functionality.
   
Apple suggests that you should consider scores and achievements as part of your initial game design (as opposed to tacking it on at the end). This is a legitimate observation in most cases, for example passing other players in DoodleJump is arguably why it is so popular.
  
Be aware that once your Game Center assets are published to the live servers, some assets become more difficult to change because they are already in use by players and on live versions of your game. For example, leaderboard scores are formatted using the leaderboard assets you created. If you change your scoring mechanism and change your leaderboard assets to match, older scores would still be posted on Game Center and would be inconsistent with the newer scores. For this reason, some assets you create cannot be modified after the game ships.
    

19.2 Why Bother?

   
Many iOS games use Game Center, but not all of them use every feature. Apps can choose to include any or all of the following features supported by Game Center:
  • Leader-boards – compares scores with the player's friends and with other players from around the world
  • Achievements – shows goals that can be accomplished by the player and also allows the player to compare with friends' achievements
  • Multiplayer – the game can host matches in real time, either between the player's friends or by "auto-matching" with random players from around the world.
Some of the reasons that you may want to include Game Centre are:
  1. Improve the longevity and replayability of your game by adding challenges (aka Achievements) or multiplayer capability.
  2. Being able to see usage of your Apps via leaderboard activity.
  3. Improve the discoverability of your Apps through players challenging their friends and the new facebook "like" button.
  4. Allows players to rate your App from Game Center (if your App is rubbish this may not be a good thing).
To setup Game Centre there is code that we need to add to the App and then metadata which we need to add to iTunes Connect for the App. This tutorial will deal with the App side changes.
      

19.3 Step 1 - Authenticate the Player

     
To demonstrate the implementation of Game Center, we will use the MineSweeper App developed in previous tutorials. We are assuming that you are familiar with the Codea runtime and have got your App running in Xcode. If you haven't then read Tutorials 12 and 13 first. 
     
    
To start, open up your App in Xcode. The first thing we need to do is to link the GameKit framework. In the navigator area of Xcode 4, select the project name in the top left, it should be “CodeaTemplate”. Next, select the current target (“MineSweeper” in our case), and then select the “Build Phases” tab. Expand the “Link Binary With Libraries” option, and then click the “+” button to add a new framework. Type “g″ into the search box, and select the GameKit.framework framework that appears in the list. Click “Add” to link this framework to  your project. So far so good.

Once again in the Project Navigator pane, Under Classes -> Supporting Files, click on the CodifyAppDelegate.h file and add:
  
#import <GameKit/GameKit.h>
  
Your App will now recognise the Game Center methods and variables. If we weren't using Codea, setting up Game Center is pretty simple, to illustrate:
 
Click on CodifyAppDelegate.m and add the following to the end of the didFinishLaunchingWithOptions method:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Existing code here...

    // Authenticate Player with Game Center
    
    GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
    
    // Handle the call back from Game Center Authentication
    
    [localPlayer authenticateWithCompletionHandler:^(NSError *error)
    {
        if (localPlayer.isAuthenticated)
        {
            // Player was successfully authenticated.
            // Perform additional tasks for the authenticated player.
        }
        else if (error != nil)
        {
            NSLog(@"error : %@", [error description]);
        }
    }];

    // ...and back to the existing code.

    Return YES;
 
}

This is the code for pre-iOS 6 (since I have an iPad 1) devices. If you are developing for iOS 6, note that authenticateWithCompletionHandler is deprecated (use localPlayer.authenticateHandler instead).
  
Running this code in the Xcode simulator should present you with the pop up shown in Figure 1. Log in with your usual App ID to test.
  
Figure 1. Game Center Sign In.
  
If you haven't enabled your game for Game Center, once you log in you will get the error shown in Figure 2.
  
Figure 2. Game Center not enabled Error.

The problem is that we need to be able to submit scores and achievements from within our Codea App and Codea doesn't know about Game Center. However, one of the gun coders, @juaxix over on the Codea Forums has built a bridge between Objective C and Lua. We will extend this and use it to enable Game Center for MineSweeper. So delete the authentication code above if you added it to your App and we will show you the correct way to bring Game Center functionality to your Codea App.

In the next tutorial we will show you how to add leader boards and achievements in iTunes Connect. We will need these before we can make the changes required to our Lua and Objective C code.

Saturday, September 29, 2012

Tutorial 18 - Saving and Loading Complicated Tables



18.1 Recap

   
Tutorial 18 brings together elements from a number of the previous Tutorials. It is an example of where asking the right question makes finding the answer much simpler. Our aim is to be able to load and save level data from our Tower Defence level generator. Most of the data we need is stored in a table. The tricky part is that Codea only allows us to save data as strings at the moment (some smart folks over at the Codea Forum have worked out how to jam data into image files and save those).
  
Tutorial 16 examined a technique for saving simple table structures like a one dimensional array. Initially we thought that saving a more complicated table wouldn't be that tough. All we needed was one of the existing Lua table to string parsers like Pickle / UnPickle. WRONG!
    

18.2 Limitations of Table Serialisation Parsers

  
We discussed Lua tables in Interlude 6. They are simple in concept but capable of representing very complicated structures. Tables can contain all the simple Lua types (booleans, strings, nil, and number), functions, other tables, closures, etc. The most complete table to string parser that we could find was Data Dumper. But even Data Dumper can not handle tables that contain:
  • Both light and full userdata
  • Coroutines
  • C functions
And of course our level data contains userdata (e.g. vec2 is represented using userdata). So where to from here?
    

18.3 The Modified Cell Class

   
This is where asking the right question makes all the difference. Looking at which data we actually need to save, it becomes apparent that we don't need to save the entire table (including functions) as this can all be reconstituted. All we really need from the Grid table is what is contained in each cell. So rather than trying to convert a two dimensional array of cell objects (which contain userdata) into a string, we extend the cell class to provides its contents (state) as a string. We also provide the inverse function which sets the cell state from a string so we can load the level back in. The extended cell class is shown below.
  
  
Once we can get the grid cell contents out as a string it is easy to write a function to create a simple two dimensional table holding each of these strings. Data Dumper makes short work of converting this table to a string which we can save to global data. Even better, Data Dumper saves the table in a format that loadstring can use to rebuild the original table. The updated Main class for dGenerator details these save and load functions.
  

We updated the File Manager class from Tutorial 17 to allow us to select the file to be loaded. As part of this update we got rid of the submenus because we didn't need them and they meant that the user had to do an extra tap to load. In addition, Delete was right next to Load which is poor design. One slip of the finger would be potentially disastrous (particularly because there is no confirmation for delete and no undo). The other improvement to this version of File Manager is we truncate keys and values which are larger than the ListScroll widths. You can see the upgraded version in the screenshot below. The About menu item doesn't do anything at this stage.
     

18.4 Loading & Saving Data

   
Tapping the Save button on the main screen of dGenerator will call the saveLevel() function in Main(). The function starts off by saving the simplified table data in saveGrid. It then generates the key which contains a header "dGen" (to indicate when loading if it is the right data type), the game name and level number, a boolean indicating if the start cell has been selected and its co-ordinates and then a boolean indicating if the end cell has been selected and its co-ordinates. Finally we use Data Dumper to convert saveGrid to a string and save the key and value to global data.
  
Loading a level is the reverse. Tapping the Load button on the dGenerator main screen will call the loadLevel() function in Main. This prints out some debug data but its only compulsory action is to set the App state to stateFileManager. This will draw the File Manager instead of the main screen and handle its touches.
  
Once the user has navigated to global data and selected an appropriate key containing level data, tapping load on the File Manager menu bar will call the loadFile() function in Main. This function splits the key back into its component parts using the explode() helper function and then uses loadstring() to create a function which rebuilds the data table. The createGrid() function was updated so that it can be loaded using this data table.
  
And that is all there is to it. You can use this link to download the entire code including the updated classes.
  
Next up we will look at adding creeps to your levels in a number of waves.