Book Image

Marmalade SDK Mobile Game Development Essentials

By : Sean Scaplehorn
Book Image

Marmalade SDK Mobile Game Development Essentials

By: Sean Scaplehorn

Overview of this book

Modern mobile devices are capable of supporting video games of amazing quality but there are so many different devices and platforms how can you support them all? The answer is to use the Marmalade SDK to write your code once and deploy it to all popular mobile platforms at the touch of a button.Marmalade SDK Mobile Game Development Essentials will provide you with everything you need to know to transfer your existing C++ videogame programming knowledge to mobile devices. From graphics and sound to input methods and actual deployment to device, this book covers the lot.Learn how to make use of keys, touch screen and accelerometer inputs for controlling your game.Take the pain out of supporting a varied range of target devices, both across multiple platforms and multiple specifications.Step by step from "Hello World" to a complete game, this book will show how to use the Marmalade SDK to develop games for mobile devices.Learn how to make dazzling 2D and 3D games complete with fully animated characters, music and sound effects that can be deployed to all the leading mobile platforms, whilst ensuring it can run on a wide range of possible devices, from low specification to high end.If you want to join the exciting world of mobile videogames then Learning Mobile Game Development with Marmalade will show you how to do so, fast!
Table of Contents (17 chapters)
Marmalade SDK Mobile Game Development Essentials
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Creating a Marmalade project


With Marmalade installed, we can now get down to doing some coding, and what better place to start than with the classic example of a "Hello World" program.

Creating the "Hello World" project

To begin a new project, we must first create an MKB file, which is Marmalade's own project file format. We use MKB files to specify all the source files, libraries, and build options needed to build our project.

The MKB file is actually used to generate a Visual C++ project file, but whenever we want to add or remove a source file to our project, we must do so by editing the MKB file and regenerating the Visual C++ project file from it using Marmalade's make file builder script, which we'll be looking at in just a moment.

In addition to source files, the MKB file also allows you to list all the other datafiles and resource files that your application will need in order to run, as this information will be needed when it comes to deploying your application on different mobile platforms.

Marmalade does come with a small tool called the LaunchPad, which can be used to create a new project, but in the interest of learning how a Marmalade project is put together, we will go about creating everything from scratch instead.

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.

The MKB file for the "Hello World" project

Let's make a start on our "Hello World" project. Create a new directory to hold the project files, and then create a file called Hello.mkb in this directory and enter the following into it:

#
# Main MKB file for Hello project
#

# Modules used by this project
subprojects
{
  iwgx
}
 
# The files that make up the project (source, data etc.)
files
{
  [SourceCode]
  (source)

  Main.cpp
}

# Settings to configure the deployment process 
deployments
{
  name="Hello"
  caption="Hello World"
}

The first section of Hello.mkb is the subprojects section, which lists all the additional code modules used by our application. In this instance, a code module is a library that can be added to our project either as a group of C or C++ source files or, alternatively, as pre-compiled, linkable object files accompanying header files. In the previous example, there is just one, iwgx, which is the Marmalade code module responsible for rendering graphics.

All the higher level modules within Marmalade are referenced in this manner, and you can also use this system to create your own modules to enable code re-use across projects. To create a subproject module we use an MKF file, which amounts to a little more than an MKB file with a different file extension! When we add an entry to the subprojects list, the Marmalade makefile builder script will search for a suitable MKF file that describes each subproject. We'll see detailed examples of how to do this later in the book.

The next section is labeled files, and this is where we list all the source code files for our project. It is possible to split your source files up into different directories. To make it easy, you simply put the directory name in brackets ((source) in our example) and then list all the source files in the directory below.

It is also possible to group the related files together into subsections, which we do using square brackets ([SourceCode] in our example). Any source files below this will be added to that section and will then appear in a separate folder in the Visual C++ Solution Explorer. There is no need for the directory and group names to match, and indeed you can have more than one directory in a group if you so wish.

Finally we have the deployments section, which is where various settings are made that control the process of deploying our application to different device types.

In our example we are making two settings. The name setting provides the filename of our final executable and is also used in file and directory names created for us by Marmalade, while caption sets the name that will appear under the application's icon when installed on a device.

Both the aforementioned settings are examples of general settings that apply across all device types, but there are also a great many other settings available, which are specific to particular platforms, such as iOS or Android. A full list of these can be found in the Marmalade Documentation help file that is installed as part of the Marmalade SDK, and we'll also be looking at this in Chapter 8, Supporting a Wide Range of Devices, of this book along with the additional sections of the MKB file that have not yet been shown for this example.

The use of whitespace in the MKB file is pretty much up to your own personal preference. Though most of the Marmalade examples tend to indent entries within blocks, tabs or spaces can also be used.

Comments can also be added using the hash (#) character. Everything after the hash character till the end of the current line is then considered a comment.

The source file for the "Hello World" project

We may now use the MKB file for our project but we still can't do anything with it yet, as we've told Marmalade that there is a source file called Main.cpp, which doesn't exist yet. If we were to try and use the MKB file to build the project, we would get an error reported about this missing file, so let's create it.

You will recall that we said that our Main.cpp file would reside in a directory called source in the MKB file, so first create this new subdirectory in the project directory. Now, create a file called Main.cpp in the source directory and enter the following into it:

//---------------------------------------------------------
// Learning Mobile Game Development with Marmalade
// Chapter 1 - Hello
//---------------------------------------------------------
 
// Marmalade SDK includes
#include "IwGx.h"
#include "s3eConfig.h"
#include "s3eDevice.h"
 
//---------------------------------------------------------
// Main entry point
//---------------------------------------------------------
int main()
{
  // Initialise Marmalade modules
  IwGxInit();
 
  // Set a default message, then check the ICF file to see if
  // a proper message has been specified
  char lMessage[S3E_CONFIG_STRING_MAX] = "Hello!";
  s3eConfigGetString("APP", "Message", lMessage);

  // Set screen clear colour to black
  IwGxSetColClear(0, 0, 0, 255);

  // Draw text at double default size
  IwGxPrintSetScale(2);
 
  // Loop until we receive a quit message
  while (!s3eDeviceCheckQuitRequest())
  {
    // Allow device to process its internal events
    s3eDeviceYield(0);
 
    // Clear the screen
    IwGxClear();
 
    // Display our message on screen
    IwGxPrintString(10, 10, lMessage);
 
    // Flush IwGx draw buffers to screen
    IwGxFlush();
 
    // Swap screen double buffer
    IwGxSwapBuffers();
  }
 
  // Terminate Marmalade modules
  IwGxTerminate();

  return 0;
}

The code should be fairly simple to follow, but here is a quick breakdown.

First we reference the include files to allow us to use the parts of Marmalade that are necessary for our application, and then we create our main entry point function main. This is equivalent to the main() function in a standard C or C++ program, except that it takes no parameters as Marmalade does not accept command-line parameters. It's quite hard to specify command-line parameters on mobile devices, so there really isn't any need!

The first thing our application needs to do is initialize Marmalade's rendering module with a call to IwGxInit(), which will initialize the screen and set up standard behavior such as double buffering of the display.

Next we allocate a character buffer that will contain the message that we will be displaying on screen. We initialize it to a default message to make sure that there is something to be shown, but we then use a call to the s3eConfigGetString function to see if another message has been specified in the application's configuration file, which will be explained in more detail shortly.

The following call to IwGxSetColClear sets the desired screen background color to black, and then the call to IwGxPrintSetScale tells Marmalade to display text using its built-in font (which is quite small in size) at double its default resolution.

We now enter our main processing loop that will continue until the s3eDeviceCheckQuitRequest function returns a true value, which will happen if the user quits the application or if the device sends a quit request to the application for any reason.

The first line of our main loop is a call to s3eDeviceYield. This is a very important function that must be called at regular intervals during our application, to allow the device's OS to perform important tasks such as handling events—user inputs, incoming phone calls, and so on. Under most circumstances, a single call to this function in the main loop is sufficient.

The value passed to s3eDeviceYield is the maximum time (in milliseconds) that our application will yield to the OS for. Normally this value is set to zero, which yields long enough for the device to process the events, but will return control to our application as soon as all the events have been processed.

Next, we call IwGxClear to clear the screen and then use IwGxPrintString to display a message on the screen. IwGxFlush causes the Marmalade engine to then process all our drawing requests to yield a final screen image that we can then display to the world using IwGxSwapBuffers.

Finally, outside the main loop, we call IwGxTerminate to shut down Marmalade's rendering engine, and finally return zero to indicate that our application was completed without any errors.

Building the "Hello World" project

Now that we have set up our project and written the necessary code, it is finally time to build it. To do this open a Windows Explorer window and navigate to the folder containing Hello.mkb, and then just double-click on the file. You might see a brief flash of a command-prompt window, but after a short delay, Visual C++ should automatically start up with our project.

The act of double-clicking the MKB file actually causes the Marmalade makefile builder script to be executed. This is actually a script written in the Python language, which takes the MKB file and outputs a Visual C++ solution file and other required elements. A file association is automatically set up when installing Marmalade, so you can either double-click the file, or alternatively use the command prompt to create your project by changing to the project directory and entering Hello.mkb.

Before we go on to compile and run the project though, let's take a quick look at what Marmalade has created for us.

If you look in the project directory, there should be two new directories, which are described in the following sections.

The build directory

One of the directories created by the MKB file will be named build_hello_vcxx, where the "xx" part is dependent on the version of Visual C++ you are using.

This directory is Marmalade's working directory and is where all the object files created during building are stored. It will also be the home to our deployment packages when it comes to making device builds.

A Visual C++ solution file created from the MKB file also lives in this directory, and while you can use these files to switch between projects, you should never add files or change project settings using the options in the Visual C++ IDE.

Note

Always make project changes to the MKB file, then either close Visual C++ and double-click the MKB file to rebuild the solution, or alternatively perform a build inside Visual C++ to update the solution file with any changes. You should not make changes directly within the Visual C++ IDE as they will be lost the next time that the MKB file is used to recreate the project file.

The data directory

The MKB file will also generate a directory called data, and this is where Marmalade requires you to place any files that your application will need to load, such as images, 3D model data, sound files, and others. While you can create this directory and these files yourself, and it will not cause a problem, we might as well let the makefile builder do it for us!

If you take a look inside the data directory, you will see that the build process has also created two more files called app.icf and app.config.txt. These files are used to configure your application and are explained in the following sections.

The app.config.txt file

This file provides a list of all the application-specific settings that can be made in the app.icf file, along with a description of what each setting does and how it is used. There are two reasons for using this file:

  1. Adding entries to this file keeps your project settings documented in a single place, so other coders can check this file to see what a particular setting does.

  2. Any setting contained in the app.icf file that is not documented in the app.config.txt file will generate a runtime error message when you try to specify or access it in your program.

Additionally, the app.config.txt file also requires you to define a group name for your settings, which is specified by using square brackets.

If you look at the s3eConfigGetString function call in the "Hello World" project code, you will see an example of this. This call is trying to access a setting called Message from the group APP, so let's add this into the app.config.txt file now, to stop any asserts from firing when running our application. Edit the file and add the following lines to the bottom of it:

[APP]
Message      The message we want to display on screen
The app.icf file

The app.icf file is used to add the configuration settings to your application, and as already stated these must be either documented in your project's app.config.txt file or must alternatively be defined in a similar file within one of the subprojects used by your application.

Adding a configuration setting is simply a matter of adding the setting name followed by an equals sign and then the value you wish to use. You must also ensure that you add the setting to the correct group, using the same square bracket notation used in the app.config.txt file. Here's an example:

[APP]
Message="Hello World"

The settings made in the app.icf file can then be accessed in code using the s3eConfigGetInt and s3eConfigGetString functions.

The app.icf file also has another couple of tricks up its sleeve, as settings can also be made that are specific to a certain platform or even specific to an individual device. Here's how you achieve this:

  • To limit the application to a particular platform add the line {OS=platform}, and any settings following this will only apply to that device platform. The value used for platform is normally just the name of the operating system, for example, ANDROID, BADA, or WINDOWS, although it is worth mentioning that you should use IPHONE to refer to iPhones, iPods, and iPads! If in doubt, you can use a call to s3eDeviceGetString(S3E_DEVICE_OS) to discover the value that you need to use for a particular operating system.

  • To limit the application to a particular device or devices, add the line {ID=platform id}, and any following settings will only be applied when run on the specified device. The platform value is the same as that used previously, while the id is an identifier for a particular device. The format of the id value depends on the operating system, but you can discover what value to use for a particular device by calling s3eDeviceGetString(S3E_DEVICE_ID). It is also possible to provide a comma-separated list of id values if you need the settings to apply to more than one device.

Note that both of these settings will continue to take effect until a new OS or ID value is specified. If you wish to return to applying all the settings globally, just add {} after your last OS- or ID-specific setting.

Tip

It is good practice to ensure that your OS- or ID-specific sections always terminate with {}, as not doing so can lead to a major head-scratching session when you deploy to device and find that some setting you have just changed doesn't appear to be taking effect.

To illustrate the use of {} , let's add some settings to the "Hello World" project app.icf file. Open the file and add the following lines to the bottom of it:

[APP]
{OS=ANDROID}
Message="Hello Android!"
{}
 
{OS=BADA}
Message="Hello Bada!"
{}
 
{OS=IPHONE}
Message="Hello iOS!"
{}

{OS=QNX}
Message="Hello BlackBerry!"
{}
 
{OS=WINDOWS}
Message="Hello Windows!"
{}

You should be able to see from this that we have specified a different message string for each different platform type that we wish to support.

Building and running in the Windows simulator

Now it's time for us to see the "Hello World" project in action. It is just a simple matter of compiling the code in Visual C++ and running it.

To compile the code, simply select Build | Build Solution or press the F7 key. Visual C++ will compile and link the Main.cpp file.

Now we can execute the program. Select Debug | Start Debugging or simply press F5. The Marmalade Windows Simulator will be launched, which will in turn load and execute our program. The following image shows what the "Hello World" project should look like when run in the Windows Simulator:

You will notice that the Windows Simulator contains a number of menu options. These allow you to make the Windows Simulator run in as close a manner to any device you choose as possible. The best way to see what you can change is to explore the menu options yourself, but here are a few of the more useful things you can do:

  • Accelerometer: Testing accelerometer inputs on Windows would be impossible without Configuration | Accelerometer.... This brings up a dialog box that allows you to use the mouse to rotate a 3D image of a phone, to simulate the accelerometer input.

  • OpenGL ES version: The Windows Simulator option Configuration | GL... allows you to emulate different versions of OpenGL ES, which makes it easy to see what your game may look like on different types of hardware. It also allows you to disable OpenGL ES support entirely, which will then force Marmalade to use its built-in software renderer.

  • Screen resolution: Mobile devices have a wide range of supported screen resolutions, so Configuration | Surface... allows you to select any size for the screen that you desire.

  • Emulation of device suspend and resume: It is easy to forget that the primary function of many devices is actually that of a telephone rather than of a gaming platform, which means your application could potentially be interrupted at any time by an incoming call. Marmalade takes care of most of the fiddly details of handling this automatically, but there may still be situations when you need to do something special under such circumstances. The Windows Simulator allows you to test whether your application responds correctly by way of Events | Simulate Suspend and Events | Simulate Resume.