symbian os workshop - 123seminarsonly.com€¦ · • microsoft debugging tools: needed to debug...

48

Upload: tranhuong

Post on 08-Aug-2018

228 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:
Page 2: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 2/48

Introduction

In this tutorial you will get to know some of the basics of developing for mobile

phones using C++. All the examples target Symbian OS and the Series 60 UI platform.

Instead of long, theoretical explanations, a more practical approach is used.

First, you will learn how to create your own mobile project. Then, you will add the

prewritten game logic of a small Arkanoid-like game called “Mopoid”. This provides an

interesting way to get to know important aspects of developing for Symbian OS,

including:

• defining and using menus,

• handling and displaying text,

• loading and showing images,

• writing and reading data to/from files,

• using a timer for periodic events,

• ... and many more smaller, but equally important topics.

You will see the results of your actions right away. Whenever some Symbian OS

specifics comes into sight (like memory handling), a short explanation will give you a

brief overview of why it is this way and how to work with it.

Of course, only the surface of all those topics can be scratched, as each of them would

easily fill a tutorial of their own of this size. However, this tutorial will give you a basic

understanding of how developing for mobile phones using C++ works, and it is a good

starting point for your own projects.

I hope that you have fun working your way through the tutorial and that you will get a

nice game out of it!

- Andreas Jakl

Page 3: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 3/48

Contents

Step 0 - Preparation ........................................................................................................... 5

Getting started ................................................................................................................ 5 Choosing an IDE ........................................................................................................... 6 Choice of the Series 60 SDK........................................................................................ 7

Step 1 - Defining the Symbian OS SDK........................................................................ 8

Step 2 - Creating a new project ........................................................................................ 8

Step 3 - Testing the project .............................................................................................. 9

Troubleshooting: .......................................................................................................... 10

Step 4 - Defining strings ................................................................................................. 11

Step 5 - Defining the menu ............................................................................................ 12

Step 6 - Displaying the about box ................................................................................. 14

If something doesn’t work... ....................................................................................... 16

Step 7 - Getting the application to the mobile phone! ............................................... 17

Step 8 - Adding the game engine to your project........................................................ 18

Unzipping the file......................................................................................................... 18 Distributing the game data.......................................................................................... 18 Adding the source files to your project..................................................................... 18 Adding additional libraries to the project definition file......................................... 19 Defining new text ......................................................................................................... 20 New game...................................................................................................................... 20 Adding graphic and sound files.................................................................................. 20 Testing............................................................................................................................ 22 Troubleshooting ........................................................................................................... 22

Step 9 - Loading images .................................................................................................. 22

C and T classes ............................................................................................................. 23 ConstructL..................................................................................................................... 23 Loading bitmaps ........................................................................................................... 24 Deleting images ............................................................................................................ 26

Step 10 - Displaying the graphics..................................................................................... 27

Handling transparency................................................................................................. 28 Drawing a bitmap......................................................................................................... 28

Step 11 - Handling keys..................................................................................................... 29

Page 4: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 4/48

Step 12 - Displaying text ................................................................................................... 31

Setting a font ................................................................................................................. 31 Reading text from the resource file ........................................................................... 32 Formatting and displaying the text ............................................................................ 32 Aligning text .................................................................................................................. 32

Step 13 - Reading and writing files .................................................................................. 34

Preparation .................................................................................................................... 34 Setting the file name..................................................................................................... 34 Opening the file ............................................................................................................ 35 Creating the stream ...................................................................................................... 35 Writing the data ............................................................................................................ 35 Closing the file .............................................................................................................. 36 The Cleanup Stack ....................................................................................................... 36 Loading .......................................................................................................................... 37 Cleanup when your application is uninstalled .......................................................... 38 Building from the command line ............................................................................... 40

Step 14 - Setting the application icon.............................................................................. 40

Step 15 - Handling being in the background ................................................................. 42

Step 16 - Periodic Events.................................................................................................. 44

Keeping the backlight on ............................................................................................ 44 Using a timer ................................................................................................................. 45 Stopping the timer........................................................................................................ 45

Step 17 - Final notes .......................................................................................................... 46

About the author .......................................................................................................... 46 Contact........................................................................................................................... 46 Copyright ....................................................................................................................... 47

Step 18 - Exercises ............................................................................................................. 48

Alternative key handling.............................................................................................. 48 Define more levels ....................................................................................................... 48 Saving the game progress ............................................................................................ 48

Page 5: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 5/48

Step 0 - Preparation

Download the following components:

• ActivePerl: needed by the Symbian OS tool chain to compile your project –

http://www.activestate.com/

• Symbian OS SDK: this tutorial uses the Series 60 SDK 1.2 for Symbian OS,

Nokia Edition to provide the best compatibility with older Series 60 devices –

http://www.symbian.com/developer/sdks_series60.asp

• Microsoft Debugging Tools: needed to debug applications in the emulator

through Borland’s C++BuilderX –

http://www.microsoft.com/whdc/devtools/debugging/

• Visual C++ Toolkit: only needed if you don’t have Visual Studio 6 or .net

installed. It’s free and needed to compile the projects for the emulator. Go to

http://www.microsoft.com/downloads/ and search for “Visual C++ Toolkit” to

download it.

• Borland C++BuilderX Mobile Edition (v1.5): get it for free by filling out the

short survey at http://info.borland.com/survey/cbx15_mobile_edition.html

Install the components in the order listed above. Allow all installations to add the

programs to the system’s path variable, in case they ask! It’s recommended that you

install the Series 60 SDK to its default location at C:\Symbian\ !

Getting started

Should your application crash in the emulator, there is a way to make it display a more

helpful error message. To activate this feature, create an empty file called “ErrRd” in

the “C:\Symbian\6.1\Series60\Epoc32\Wins\c\system\Bootdata” directory of

your Series 60 SDK. That’s it.

When you first start your copy of C++BuilderX Mobile Edition, it needs to be

registered. Choose the activation file option, and locate the file that Borland sent you

after you filled out its survey and registered for its development network.

Page 6: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 6/48

Choosing an IDE

The Symbian OS build tools are actually command line-based and would work without

any IDE. However, development is more comfortable if you use one. There are several

choices, each with advantages and disadvantages1:

Fast; efficient compilation and debugging; some tools for Symbian OS available

Microsoft Visual C++ 6

Old; no real support for Symbian OS code development

Fast; modern and good IDE; Widespread Microsoft Visual Studio .net

Not directly supported by the Symbian OS SDKs – makes development for Symbian OS even more complicated; expensive

Symbian OS at least partially integrated Metrowerks CodeWarrior

Not so cheap; IDE more difficult to master at the beginning

Supports visual design of menus and dialogues; Symbian OS related features; currently free!

Borland C++BuilderX Mobile Edition 2

Slow and clumsy IDE; Symbian OS integration should go farther.

Very good IDE; free! Eclipse

No support for debugging; Symbian OS not really integrated yet.

As you can see, there is no obvious ‘best’ way to develop Symbian OS C++

applications. For this tutorial, Borland’s C++BuilderX was chosen, because it is free

and it takes away much of the initial complexity when starting with Symbian OS, even

though the IDE itself still needs a lot of improvement.

Please note: The list above is based on personal impressions. CodeWarrior could also

be a very good choice, especially now that its mobile edition was bought by Nokia and

will be actively improved in the future.

1 All products are trademarks of their respective owners.

2 Will be referenced as “C++BuilderX” in this tutorial.

Page 7: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 7/48

Choice of the Series 60 SDK

The Series 60 SDK for Symbian OS is available in higher version numbers, which target

newer Series 60 phones. Up to now, the devices have always been backward

compatible, so an application developed for Symbian OS v6.x mobile phones (using the

SDK v1.2) also works on newer Symbian OS v7.0s and v8.0 phones.

While applications compiled using the SDK v2.0 (which mainly targets the Nokia 6600

with Symbian OS v7.0s) should still work on older devices, this can be a bit

problematic. If the source code is compiled by even newer SDKs, the files are not

backward compatible on a binary level any more.

Which version of the SDK you use is entirely your choice. If you only want to develop

for newer phones, or if you want to do new things that were not possible before, go

with (at least) the SDK v2.0. Loading images and sounds has been specifically

improved. Internet (HTTP) connections are easier to handle as well.

If you want to develop a commercial application that should reach the broadest

possible audience, you shouldn’t exclude older Series 60 phones. By choosing to target

Series 60 you already restrict your potential market. If you limit your target audience

even more by making your program only compatible to the newest phones, you will

have an even harder time selling it.

Page 8: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Step 1 - Defining the Symbian OS SDK

It’s time to start working! Open Borland’s C++BuilderX Mobile Edition. Go to

“Tools” → “Symbian SDK Configuration”. Create a new SDK configuration, using the

SDK Template of the SDK you have installed, in this case: “Symbian Series 60 1.x

(Microsoft version)”. At least for the SDK v1.2, do not use the Borland SDK

version, otherwise compiling the project won’t work! Set the path as shown in the

screenshot, and choose an appropriate name like “Series 60 1.2”.

Fig. 1 – Defining the Symbian OS SDK in Borland's C++BuilderX.

Step 2 - Creating a new project

Create a new project: “File” → “New...” → “Series 60” → “Series 60 GUI Application”.

Fig. 2 – Creating a new Symbian C++ project.

Enter “Mopoid” as its name (don’t use a different name for this project, otherwise

some includes of the prewritten files we will include later on won’t work). Place it in the

“C:/Symbian/dev” directory and let C++BuilderX create a project subdirectory, so

that all your projects will be kept separated from each other.

© 2005 Mopius Page 8/48

Page 9: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 3 – Defining properties of the project (Step 1).

Go to the next step. Enter the same name for the project, “Mopoid”. As we want to do

a game, choose “Full Screen” as view type.

The default UID3 proposed by C++BuilderX should NOT be used. Change the UID

to something between 0x01000000 and 0x0FFFFFFF – Symbian reserved those IDs

for testing projects. Every application installed on a phone has to have its own unique

UID. Therefore, if you want to release your game to the public, send a mail to

[email protected] containing your name and how many UIDs you need (5

should be sufficient for the beginning). They will send you the UIDs as soon as

possible.

Fig. 4 – Defining properties of the project (Step 2).

Step 3 - Testing the project

Your workspace should look similar to the screenshot in Fig. 5. Now is the time to test

your project to see if everything is configured correctly. Press the “Run Project“ button

(F9).

© 2005 Mopius Page 9/48

Page 10: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 5 – This is what the default workspace of Borland's C++BuilderX looks like.

If everything works well, the emulator will show up after some time. Deactivate the

memory resident virus scanner if you have one running to make this process a bit

faster. Your own application will be located at the bottom of the menu, so move down

using the cursor keys to select it.

If you don’t want to do this every time you test your game, select it, press the left

softkey (“Options”), choose “Move” and move it to the upper left position of the

menu. It will stay there even if you close the emulator and start it again.

When you start the “Mopoid” application, you will only see a white screen. This is

because we chose to create a full screen application, which does not have a visible

status or menu bar. When you press the left softkey, a default menu will show up. In

the next steps we will adapt it to our needs.

Troubleshooting:

If Microsoft’s VisualStudio.net or Microsoft’s toolkit is installed on your PC and

Borland C++BuilderX uses this compiler for the Series 60 SDK v1.2, you may get this

error message:

LNK2019: unresolved external symbol __ftol2

© 2005 Mopius Page 10/48

Page 11: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 11/48

To solve this problem, open the file

“C:\Symbian\6.1\Shared\EPOC32\Tools\cl_win.pm” in a text editor, search for

the line that contains “/W4” and change it to “CLFLAGS = /nologo /Zp4 /W4

/QIfist” (you’re adding the “/QIfist” parameter to the options).3

Should C++BuilderX display errors like this during the build process:

Can't locate E32env.pm in @INC [...]

one possible solution is to put the following two paths at the beginning of your path

environment variable:

C:\Symbian\6.1\Shared\epoc32\gcc\bin;C:\Symbian\6.1\Shared\epoc32\tools;

If this doesn’t help, make sure that Perl is installed and do a repair install of the

Symbian OS SDK, basically making sure that the SDK is installed after Perl on your

system.

Make sure that you close the emulator window after you are finished with testing your

project! If you want to compile and the emulator is still running in the background, you

will get several error messages!

Step 4 - Defining strings

By default, the “MopoidContainer.akn” file should be active. If it is not, open it

through the project window on the left: “Mopoid.cbx” → “Symbian project (bld.inf)”

“Mopoid.mmp” → “Designs” → “MopoidContainer.akn” (double click).

To make our own menu items, we first have to define the text that we want to use. On

Symbian OS, text is normally defined in resource files. This makes it easier to localize

applications, as mobile phones are global and you will probably want your game to be

available in more than one language. Switch to the “String Table” designer:

3Thanks to Simon Woodside for this tip – see http://simonwoodside.com/weblog/2004/07/18

Page 12: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 6 – switching to the string table designer.

In the game we want to have a simple menu that allows us to start a new game, display

an about box and quit the game. Therefore, define the following four strings:

Fig. 7 – Adding new strings to the resource file of the application.

For the message in the about box (“r_aboutmessage”), you will first have to increase

the “Max Length” to something like 60, so that you have enough room for your

message. Use “\n” to tell the system where to start a new line. Always press enter after

you finished writing the text to a cell, to make sure that C++BuilderX keeps your new

text.

Please note: For this tutorial, enter the names exactly as described. In a later step, you

will add some prewritten source files to your project, which assume several name

definitions.

Step 5 - Defining the menu

It’s time to use our strings in the game. Switch to the Menu designer. You will see that

C++BuilderX has already created two menu items for you. We need one more, so

select the menu item tool on the left pane, and click into the menu to add a new item at

the bottom of it:

Fig. 8 – Adding a new menu item using the design tool.

© 2005 Mopius Page 12/48

Page 13: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Now we’ll adapt the menu items so that they use the text we’ve just defined.

Select “iMenuItem1” by clicking on it. In the panel on the right, change its name to

“iMenuItemNewGame”. For its text, just choose our resource “r_startgame” for the

ID. Leave the command at its default value of “1001”.

Please note: It’s important that you press Enter after modifying a value. If you just

switch away, it’s possible that your input isn’t saved.

Fig. 9 – Setting the properties of a menu item.

Then, change the name of “iMenuItem2” to “iMenuItemAbout”; choose “r_about”

for its Text-ID. The command “1002” is fine. Also check the second flag,

“EEikMenuItemSeparatorAfter”. This will create a small line below this menu item,

visually separating the third (Exit) command from the other items.

Last one is the menu item to quit the game. Change its name from “iMenuItem3” to

“iMenuItemExit” and use “r_exit” for the Text ID. This time, we will not keep the

standard command ID, but use the “EAknCmdExit” command. This command will

also be sent to your application if the operating system wants to shut it down, for

example when the phone does not have enough memory left. Therefore it is required

that every application always responds to this event and instantly shuts the application

down.

If you try your game now, you will see that the “Exit” menu item will already work fine!

When testing the game in the future, always quit your application using the exit

command and don’t just close the emulator. The reason is that the environment of the

emulator will automatically do a memory check and inform you if you have a memory

leak. If you just shut down the emulator, you will only discover it many hours later,

making it a lot more difficult to find the reason.

© 2005 Mopius Page 13/48

Page 14: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Step 6 - Displaying the about box

Up to now, we’ve created a small application with its own menu, without writing a

single line of code. For displaying the about box, the first line of code has to be written.

Switch to the “Non-visual” design view:

Fig. 10 – Adding an about box to the application.

Select “CAknInformationNote” in the tools panel (left). This is a simple small window

that will contain your text and a small, predefined icon. Next, click anywhere in the

white middle section to create the note. In the properties window on the right, change

its name to “iAknAboutNote” and choose the “r_aboutmessage” as the text ID.

Now we’ve defined the about box, to display it we just have to connect it to the about

menu command. Switch back to the menu designer, choose the “About” menu item.

Fig. 11 – Calling the about box through selecting the menu item.

In the properties section on the right, switch to “Events”. Double click in the empty

text box next to “OnViewCommand”. C++BuilderX automatically creates a function for

you that will be called when the user selects this menu item and places you there. But

before writing any code, switch back to the “MopoidContainer.akn” and change the

name of the function the IDE has just created to

“OniMenuItemAboutViewCommandL”, basically adding an “L” at the end of the name.

© 2005 Mopius Page 14/48

Page 15: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Why will be explained soon. Press enter and C++BuilderX should take you to the

function again; this time it has the corrected name.

Fig. 12 – The code for displaying the about box.

Now, write the code seen in line 175 of the screenshot above in

“MopoidContainer.cpp”. This is a call the function that C++BuilderX has already

created for us, directly above.

© 2005 Mopius Page 15/48

When you try the program now, the about box will already work fine. But let’s take a

closer look at why we added the “L” at the end of the function name.

You will note that the function (“ExecuteiAknAboutNoteL()”)

also has an “L” at the end of its name. Why is this? The reason is

that memory is allocated in this function (for creating and

displaying the dialogue box – also note the “ELeave” in its c

line), and that this process can fail. Currently, mobile phones have very limited

resources. Therefore, it is very important to take care of what happens when the

operating system is unable to provide the resources that your application needs.

reation

Fig. 13 – The about box in the Series 60 emulator (SDK v1.2).

Page 16: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 16/48

These events, as well as other errors (like file not found), are handled by a system which

is similar to try/catch of Java and modern C++. An error is passed up in the call

hierarchy, until someone takes care of it. To make the possibility of a leave visible to

the developer, it is a standard convention in Symbian OS to append an “L” at the end

of the function name.

The function that displays our about message leaves if not enough memory is available.

Normally, you don’t (and shouldn’t) take care of this problem and let the system display

the appropriate error message. Handling every error yourself would make your code

huge.

If there is an error, the event will automatically be passed up to the next function in the

call stack. This means that the “OniMenuItemAboutViewCommandL()” function can

also leave. Therefore, we added the “L” to the end of its name.

So far, so good. However, C++BuilderX also created a command dispatching function

called “DispatchViewCommandEvents()” with the note “NOTE: This routine is

managed by the C++BuilderX IDE - DO NOT MODIFY”.

Note that the “L” is missing at the end of it. If we added it manually, C++BuilderX

would no longer recognize this function. If we go another step up in the call stack,

you’ll get to the “HandleCommandL()” (“L”!) function of the “MopoidView.cpp” file.

That’s the function the operating system calls when the user selects your “About”

menu item!

So, because of the inflexibilities of the IDE, we already have a tiny bit of code that does

not conform to the Symbian OS coding conventions. In this case, we will just ignore it,

as the “L” is not for the system, but just a helpful thing for us developers. But it was a

good excuse to explain the basics of the leave system to you, and to show you the

limitations of C++Builder’s automatically generated code.

If something doesn’t work...

... and you would like to find out why, the file “Mopoid.Step7.zip” is a working

project of what you have done up to now. From now on, a zip file of the reference

project will be available after each step!

Page 17: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Step 7 - Getting the application to the mobile phone!

Normally the emulator works really well. But you might still get into situations where

the code works fine in the windows emulator, but simply crashes on the phone. The

most prominent examples are static member variables, which work fine in the emulator,

but do not work on the mobile phone!

As debugging directly on the mobile is difficult and doesn’t always work, it will be

difficult finding the reason for the crash when your phone just reports “System error”.

However, if you regularly try your application on your phone, it will be easier to locate

the problem.

To tell the IDE that you want to build for the device, you have to switch the target

platform of the compilation process to “ARMI” (the processor on your Series 60 phone

is an ARM processor) and the type to “UREL” (Release version). To build your project,

choose “Project” → “Make Project ‘Mopoid.cbx’” (Ctrl+F9).

Fig. 15 – Compiling for release instead of debug.

Fig. 14 – Changing the build

target of the application.

After this process has finished, a file called “Mopoid_ARMI_UREL.sis” will reside in

the directory “C:\Symbian\dev\Mopoid\group”. Transfer this file to your phone and

install it.

You can either do this using the PC Suite that came with the phone, or just send it to

the device through Bluetooth or IrDA link (if available) by right-clicking on the file,

“Send to...” → “Bluetooth device”. For more instructions on how to install a file, read

the manual that came with your phone.

If everything works fine, don’t forget to switch back to the “WINS / UDEB” build

configuration when you continue development!

© 2005 Mopius Page 17/48

Page 18: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 18/48

Step 8 - Adding the game engine to your project

Developing a whole game takes a lot of time, and in this tutorial we want to explore the

basics of development for Symbian OS, instead of using a lot of time to create game

routines. Because of this, we will import some prewritten files into our project and add

several important and interesting features.

Please note: it is possible to create a game with a more beautiful object oriented

structure. However, the provided files were written in a way to make it easy to

understand the Symbian OS related issues, and not to provide a perfectly structured

program.

Many of the steps below will be important when you develop your own project. You

will also most likely want to add graphic and sound files, add existing source files and

so on.

Unzipping the file

Unzip the file “Mopoid.Step8.Update.zip” to your “C:\Symbian\dev\” directory.

Make sure that you keep the directory structure of the archive! Overwrite all files. If

there is no warning that files are overwritten, you didn’t extract it to the right directory.

Distributing the game data

The archive contains a new directory called “data”, which includes graphics and

sounds for our game. When you execute the application in the emulator, it will look in

an own directory for any files. Call the “.\data\dobitmaps.bat” file to automatically

create the corresponding directory and copy all data files there. If your Series 60 SDK is

not installed in the default location (“C:\Symbian”) or if you are using a different SDK

than v1.2, you will first have to adapt the directory names in the batch file.

Adding the source files to your project

Next, you have to tell the IDE that you want to add some new source files to the

project. Right-click on the “Sources” item of the project window, and choose “Add

sources...”

Page 19: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 16 – Adding additional source files.

Select and add all files from the “./src/” directory which are not already part of your

project:

Fig. 17 – The files to add.

Adding additional libraries to the project definition file

Your final game will do a lot of things – load and play sounds, display PNG graphics

and access files. These functions require some libraries provided by the SDK. The only

thing you have to do is to add them to the project. Double-click on “Mopoid.mmp” in

your project definition window. This is the Symbian OS project definition file that

contains references to all source files and libraries that are needed for your project (and

some other stuff).

Scroll to the bottom of the file and add the following lines below all other library

definitions:

LIBRARY efsrv.lib // For loading data files

LIBRARY bitgdi.lib // For drawing

LIBRARY mediaclientimage.lib // For loading png files

© 2005 Mopius Page 19/48

Page 20: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 20/48

LIBRARY mediaclientaudio.lib // For loading and playing audio

LIBRARY estor.lib // For writing to & reading from files

Defining new text

A real game needs a lot of text. Define the following strings in the string table, as

described in Step 4. Add a space after the text items with a “:” at the end, as the

number will be appended to the text!

Name Text

r_score Score:

r_level Level:

r_pause Game Paused

r_gameover Game Over

r_finished You made it!

r_lifelost Life Lost!

r_lives Lives:

r_pressjoystick Press Joystick

r_highscore High Score:

r_enterlevel Entering Level:

r_title mopoid

New game

The start new game command has to be connected with the start game function of the

game engine. Create a new event function for the “Start New Game” menu item like

you did for the about box. This time, don’t change the function name to contain the

“L” suffix – the start game function doesn’t leave. Insert the following text into the

new “OniMenuItemNewGameViewCommand()” function:

iGameEngine->StartNewGame();

Adding graphic and sound files

Several .png and .wav files have been prepared so that the game has a nice look and

Page 21: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

feel. You have to add them to the project, so that they will be copied to the mobile

phone! To do that, switch the build configuration to ARMI UREL using the blue

gearwheels. You should now see an entry called “Package File” in the project pane.

When adding the files, you have to take care, as C++BuilderX has a small bug...

Fig. 18 – Adding additional files to the package.

Right-click on “Package File” and choose “Add File to Package...”. You will get to a

dialogue window. Choose the first file of the “/data/” directory of our Mopoid

project (“ball.png”). Do not click on OK yet, or you will have to remove the file from

the package and start again.

Fig. 19 – Add the filename to the target path!

Add the file name (“\ball.png”) to the target path in the second text box! When

you’re done, click on OK.

The target path defines the location and name of the file on the device. If the file name

isn’t specified, the phone will not be able to copy the file! It would be great if the IDE

added the file name itself.

The “!” at the beginning of the line means that the user can choose where he wants to

install the application; more on that later.

The bug in C++BuilderX 1.5 is: after you have added a file, you can’t modify the target

path any more. The IDE does let you change it, but when you click on OK, it will

© 2005 Mopius Page 21/48

Page 22: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

discard your changes without notifying you. Therefore, do not forget to add the file

name right when adding the file!

Do this for all .png and .wav files, and the levels.dat file. When you’re finished, your

project pane should look like this:

Fig. 20 – All files are now part of the project.

Testing

Switch back to “WINS / UDEB”. When you run your game now, it should still work.

However, the screen will just be black with only one line of text on it. In the next few

steps we will add all the parts that are missing!

Troubleshooting

This chapter was rather risky, combining your project with the prepared source files

only works if you really did everything exactly as described in the earlier steps. If you

have any problems and the project doesn’t work any more, use the reference project

from “Mopoid.Step8.zip”!

Step 9 - Loading images

Symbian OS C++ has built-in support for “.mbm” files. These are collections of RLE-

compressed bitmap files. Advantages are: they are fast to load and easy to handle,

however they take a lot of space on the mobile device. A game uses a lot of graphics,

with this system it would get huge.

Therefore, it’s better to use .png or .jpg files. Unfortunately, no predefined loading

routines are available, and it’s rather complicated to do it manually. Also,

decompressing those files takes some time, therefore it works asynchronously, in its

© 2005 Mopius Page 22/48

Page 23: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

own thread. In Symbian OS v7.0s, an alternative way to load images is possible, but if

you want your game to reach the broadest possible audience, you will have to stick to

the ‘old’ functions (for now).

Developing and explaining the whole process of loading an image would be a tutorial

of its own, therefore a finished class has been provided – “PngLoader.cpp”. A second

file, provided by Nokia (“bitmapmethods.cpp”) helps with some common tasks.

Some more functions have been added to make it even more useful. You can simply

add those two files to your own future projects!

In the Mopoid project, a class is responsible for loading and storing all those images. If

an image is needed somewhere else, it can get the image by sending the ID of the

requested image to a function of the CSpriteHandler class.

C and T classes

What about the “C” at the beginning of the class name? In short,

this means that this class will always be constructed on the heap,

and it will most of the time own other (heap) objects. When the

destructor of our “C” class is called, those objects have to be destroyed.

The second most important type is “T” classes. It is basically like a simple data type, a

class of this type can’t have a destructor. For example the basic data types in Symbian

have a “T” prefix (TInt, TReal, ...)

ConstructL

Open the SpriteHandler.cpp file to see the source code of our bitmap manager

class. You will note that the constructor is empty, and you write your code in a function

called ConstructL(), which is called by NewL().

The reason for this lies in the memory situation of mobile phones. If you develop a

typical application for the PC, you will (in most cases) not have to worry about free

memory. Here, the situation is different. It can happen that the available memory runs

out, and that creating an instance of a class fails.

However, when you allocate memory in the constructor and this process fails, the

allocated memory will be orphaned. That’s bad. Therefore, code executed in a C++

© 2005 Mopius Page 23/48

Page 24: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 24/48

constructor should never leave! However, the sprite handler should provide the

graphics right after the class is created.

The solution is simple – a two phase construction. Just move (at least) all memory

allocating code to the ConstructL() class method. You can then create the object as

usual, and then in the next line call this function. This gives you the opportunity to

handle leaves correctly.

Especially if you need to create an instance of your class more than once, you’d have to

write the code for these steps (allocation and calling ConstructL()) multiple times. To

prevent this, the two phased construction is usually handled by a static NewL() or

NewLC() function. As a general rule, NewL() has to be called when the object you want

to create is assigned to a member variable. NewLC() will leave the object on the cleanup

stack, useful for automatic variables. This will be discussed later on. For now, let’s

move on to implementing the bitmap loading!

Loading bitmaps

First, we have to define the filename of the graphic file we want to load. This is done

by:

_LIT(KBmpPanel, "panel.png");

This line creates a named object (KBmpPanel) that stores the string “panel.png”

directly into the application binary. Strings are handled differently in Symbian OS C++

compared to standard C++. Again the reason for this is the limited amount of memory

in mobile devices. In Symbian OS C++, strings are called “descriptors”, and they are

quite difficult to get used to. On the positive side, they use less memory than their C++

string counterparts.

Once we have loaded a bitmap, we need to store it somewhere. To view it, you have to

take a look at the header file of the sprite handler class. For whatever reason,

C++BuilderX doesn’t display those files in the project structure. Instead, you have to

open the source file, open its includes section in the file structure panel on the left, and

go to the include file from there:

Page 25: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 21 – How to get to the include file.

In the class declaration, you will find the following declaration of a private member

variable:

TFixedArray<CFbsBitmap*, MopoidShared::ENumSprites> iSprites;

Why is the variable called iSprites instead of sprites or m_sprites? This is

another Symbian OS C++ coding guideline. All member (instance) variables should

have “i” as their prefix. While we are at it, parameter variables should have “a” at their

beginning.

What about the type of the variable? This is basically a normal, fixed length C++ array

with additional range checking and some other useful functions (for navigating through

the array, getting its length, deleting each element and so on).

Go back to the Spritehandler.cpp file. Let’s fill our array with bitmaps. We do this

by calling a static method of our CPngLoader class that will do all of the work.

iSprites[ESpritePanel] = CPngLoader::LoadImageL(KBmpPanel, EColor4K);

Note that we tell the class to load the image as EColor4K. This means that the graphic

will have 4096 colours, and this equals the colour depth of earlier Series 60 devices like

the Nokia N-Gage or the Nokia 7650. Newer phones already support EColor64K (or

higher). However, for the graphics of a simple Mopoid game, we don’t need so many

colours anyway. ESpritePanel is the textual representation of an ID, called

enumeration, and is defined in “MopoidSharedData.h”.

Fig. 22 – The panel graphic

Fig. 23 – The mask of the panel.

We want our panel to have round corners, so we will also need a mask. The easiest

© 2005 Mopius Page 25/48

Page 26: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

method to get this would be to have a second graphic file which contains the black and

white mask image. However, as said before, loading .png files takes quite some time, so

it’s better to generate the mask ourselves. Use the following method, which is also part

of the source code provided with this tutorial:

iSprites[ESpritePanelM] = NBitmapMethods::CreateMaskL(iSprites[ESpritePanel], EFalse, 0);

This function will create a mask bitmap based on the colour of the top left pixel of the

source image. If you don’t want all pixels that have the colour of the top left pixel to be

transparent, you can use the second and third parameter to specify a colour which

should be masked as transparent.

Now, load the ball image in the same way as the panel image. The file name is

“ball.png”, the enumeration names for the ids are “ESpriteBall” and

“ESpriteBallM”.

The bricks are a bit different. They have a rectangular shape and don’t require a mask.

However, we have got several different colours for the bricks. Instead of loading the

images one by one, it’s better to combine all of the graphics into one file and then split

them up after loading this image. With this method, the image files will require less disk

space (overall), and even though the application will temporarily need more memory,

it’s a lot faster.

Fig. 24 – 3 brick graphics in 1 file.

Load the brick image using the following code:

_LIT(KBmpBrick, "bricks.png");

CPngLoader::LoadAndSplitImageL(KBmpBrick, &iSprites[ESpriteBrickNormal], 3, EColor4K);

This code loads the image file, splits it up into three images and stores them in the

iSprites array, beginning at the ESpriteBrickNormal position.

Deleting images

When you try to execute your application, it should already load the images, even

though you won’t see them. We have not written the code to display them yet. Now try

© 2005 Mopius Page 26/48

Page 27: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

to quit the application. You will see a warning like this:

Fig. 25 – Error message telling you about a memory leak.

This error message informs you about a memory leak somewhere in your application.

It’s quite difficult to find the offending code later on; because of that, remember to quit

your application in the emulator instead of just closing the emulator window.

In our case, we don’t free the memory allocated for the graphic files when the

CSpriteHandler object is destroyed. Fortunately, thanks to the TFixedArray class of

iSprites, this is easy to do. Writing the following code into the destructor of the class

will do all the work:

iSprites.DeleteAll();

Step 10 - Displaying the graphics

Just loading graphic files won’t help you much – you will also have to get them onto the

screen. In our application, the game engine class takes care of preparing the back buffer

image. This means that all graphics are drawn to an extra bitmap of the size of the

screen. When this process is finished, the whole bitmap is copied to the screen. This

prevents flickering, which would occur otherwise.

First, go to the ConstructL() method of the CGameEngine class. Uncomment the big

code block that does some size calculations with the graphics files that we have just

loaded. If you are interested, you can also take a look at the code, but it isn’t important

for us now.

The frame itself is drawn in the DrawFrame() method, which is further down in the

source code of the same class. Note that the function is defined as const, this means

that it’s not allowed to modify the member data of the game engine class.

© 2005 Mopius Page 27/48

Page 28: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 28/48

Handling transparency

Let’s take a look at the following line:

iBackBufferBmpGc->SetBrushStyle( CGraphicsContext::ENullBrush );

When drawing to a bitmap, Symbian OS provides both a “pen” and a “brush” through

the graphic context of an image, which handles drawing operations. An example: when

you draw a rectangle, the outline will be drawn using the settings you assigned to the

pen, and it will be filled by your brush.

We don’t use those drawing functions, but we have to take care of this behaviour as

well! If we define a solid brush and want to draw a bitmap that has transparent parts,

those parts will be filled with your current brush colour and its other properties! That’s

why we set the brush to a null brush, letting the background of a bitmap shine through

its transparent parts.

Drawing a bitmap

First, we’ll draw the ball. The first line is already here, it calculates the position of the

ball and puts it into a TPoint variable. This automatically provides an x and y

coordinate and is very useful.

Write this line directly after it:

iBackBufferBmpGc->BitBltMasked(ballSpritePos, iSpriteHandler-> GetSprite(MopoidShared::ESpriteBall), iBall.iSize,iSpriteHandler-> GetSprite(MopoidShared::ESpriteBallM), EFalse);

It calls the BitBltMasked() function of the back buffer bitmap’s graphic context,

which basically copies a masked source bitmap to a target bitmap. The first parameter is

the position, the second the source image, the third the size of the image we want to

copy, the fourth the mask to use, and the fifth whether to invert the mask or not.

To look up the parameters of the functions provided by Symbian OS APIs, take a look

at the Symbian OS help. Search for the “SDK Help” in your start menu under

“Symbian 6.1 SDKs” -> “Series 60” -> “Documentation”.

Now, scroll down a bit and do the same for the panel. For its position, use the value

stored in “iPanel.iPos”. The Enumeration IDs for the sprites are “ESpritePanel”

and “ESpritePanelM”. The size is: “iPanel.iSize”.

Page 29: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

As we have found out before, the bricks don’t need transparency. Generally you should

take care not to draw large transparent areas, as this slows performance.

The function to draw a bitmap without a mask (BitBlt()) is similar, and even a bit

easier to use. You only have two parameters, the position and the source bitmap. Put

the following line of code at the marked position inside the for loop, which loops

through the bricks grid to draw all visible bricks.

Fig. 26 – Our Mopoid game can now display graphics!

iBackBufferBmpGc->BitBlt(iGrid.ConvertGridToXY(x,y), iSpriteHandler->GetSprite(spriteId));

When you run your application now, it should already look quite decent:

However, there is no interactivity yet. To enable this, we have to handle key presses!

Step 11 - Handling keys

It’s quite easy to handle key presses in Symbian OS. The framework will automatically

call the “OfferKeyEventL()” method of your container class (CMopoidContainer).

The code, which was created by the C++BuilderX IDE, forwards this call to the

HandleKeyEvents() function (this wouldn’t be necessary in our case, as nothing else

has to handle key presses in our application).

The HandleKeyEvents() function gets two parameters – const TKeyEvent&

aKeyEvent and TEventCode aType. The first one (aKeyEvent) contains information

about the button that was pressed. The second parameter (aType) tells you what kind

of event happened.

In our Mopoid game, we want the panel to continuously move as long as the user

presses the direction key (in our case, he has to use the joystick). To get this behaviour,

© 2005 Mopius Page 29/48

Page 30: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 30/48

we have to set a flag when the key is pressed, and unset it when the user releases the

key again.

A special class that has been prepared (TKeyHandler) stores the direction that is

currently pressed by the user. It’s owned by our game engine class, which has to take

care of sending movement events to the panel.

The task we have to do now is rather simple; therefore we’ll only write the code for the

key down event. The prewritten source code already contains the rest. Search for the

part of the “if” statement that takes care of key down events (EEventKeyDown).

Inside, you will find a switch statement that takes care of the individual keys,

differentiated by their scan codes.

Here we’ll handle two additional cases: “EStdKeyLeftArrow” that will be called when

the player moves the joystick to the left and “EStdKeyRightArrow” for the other side.

To send the event to the key handler we mentioned previously, you have to call:

iGameEngine->iKeyHandler.LeftPressed();

Of course this is slightly different for the right side. When you take a look at the

HandleKeyEvents() function, you’ll notice that it has a boolean return value. This will

tell the system if the key press has been handled. If it hasn’t, it will be sent to the next

application that might be running in the background (Symbian OS is a multitasking

operating system!).

Because of that, we have to tell the system that we took care of this key press and that it

doesn’t have to send it to anyone else. Set the flag that’s defined at the beginning of the

function accordingly:

handled = ETrue;

Note that Symbian OS C++ uses its own definition of boolean values. The data type is

TBool and can have the values ETrue and EFalse.

Don’t forget to add a break statement after each case handled in the switch statement!

After you have written the code, test it in the emulator. You should be able to move the

panel, the ball bounces and you can already play the game! The code of this step is just

standard C code, but if you have problems take a look at the MopoidContainer.cpp

file of Mopoid.Step11.zip.

Page 31: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Step 12 - Displaying text

The game is still lacking an important part – it doesn’t display any status information

informing the player about his points, lives or level. We’ll add this now. Go to the

DrawFrame() method of the CGameEngine class.

Setting a font

Luckily, predefined functions take care of displaying the text, and are even able to align

it. But first, we have to tell the graphics context of the bitmap which font and colour to

use. Write the following code below the “// Hud” comment.

iBackBufferBmpGc->SetPenStyle(CGraphicsContext::ESolidPen);

iBackBufferBmpGc->SetPenColor(KRgbRed);

iBackBufferBmpGc->UseFont(CEikonEnv::Static()->AnnotationFont());

TBuf<30> tempStr;

Let’s analyze it step by step. The first line will already sound familiar, it defines the pen

style. In an earlier section, we explained that this is used for outlines of boxes. It’s also

used for the font outline, which is the font. In our case, we set the pen style to solid, so

that we actually see the text that we draw.

The next line defines the color. We use one of the default values, a plain red. If you’d

like to define your own RGB color, use this:

iBackBufferBmpGc->SetPenColor(TRgb(255, 128, 0));

The next line chooses one of the standard system fonts. Symbian OS provides more

complex font mechanisms, as well as the option to create and use your own fonts. For

a simple Mopoid game, we’ll stick to the easiest method and use the AnnotationFont.

It’s a medium sized, bold font.

The forth and last line creates a descriptor, which is the Symbian

OS equivalent of a string. It has a maximum length of 30 chars. A

TBuf is derived from a class called TDes, which provides several

functions to manipulate the string data. We’ll use those to set the

contents of the text. Note that the TBuf is created on the stack, which is very limited

on mobile devices. Therefore, don’t use it for strings that are longer than 256 chars. For

everything else, a heap based descriptor (HBufC) should be used.

© 2005 Mopius Page 31/48

Page 32: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 32/48

Reading text from the resource file

Next, we’ll read one of the strings that we have defined in the resource file (through the

string table of the C++BuilderX IDE). A static function of the CEikonEnv class takes

care of this and writes the string directly into the descriptor (which we have defined

before). The string resource got the name RS_R_SCORE. Normally it should only be

R_SCORE, however, C++BuilderX adds an additional RS_ in front of the name.

CEikonEnv::Static()->ReadResource(tempStr, RS_R_SCORE);

Formatting and displaying the text

The string we’ve read from the string table only contains a static text: “Score: ”. We

have to add the current score of the player at the end of the string. The AppendNum()

function provided by the descriptor handles this.

tempStr.AppendNum(iSettings.iScore);

Now, the text is ready to be displayed on the screen. We can print it at a specific x/y

position using the following code:

iBackBufferBmpGc->DrawText(tempStr, TPoint(5, 25));

Please note: the y coordinate of 25 specifies the lower border of the text, so 5/25 is

the lower left point of the text, not the upper left as you may have expected!

We also want to display the high score. Write the code for this yourself. Read the text

resource “RS_R_HIGHSCORE” into the same temporary descriptor. This will overwrite

the content currently stored, which we don’t need any more (it has already been printed

to the screen). Append the number that you can get through

“iSettings.iHighScore” and print the text at 5/38 (one line below the current

score).

Aligning text

Now the game will display the current score and the high score on the left side of the

screen.

We also want to display some information on the right side of it:

Page 33: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Level Text: RS_R_LEVEL

Value: iSettings.iLevel

Position: y: 28, x offset from the right side of the screen: 3

Lives Text: RS_R_LIVES

Value: iSettings.iLives

Position: y: 38, x offset: 3

Read and format the strings as before, only the printing is different. Luckily, Symbian

OS provides a function that aligns text:

iBackBufferBmpGc->DrawText(tempStr, TRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 25, CGraphicsContext::ERight, 3);

The TRect(...) defines a rectangle which is used to align the text. In our case, it’s the

whole screen. To optimize the program, you could define the Screen TRect only once

at the beginning of the function, and use the variable in all calls that need it.

SCREEN_WIDTH and SCREEN_HEIGHT are defines made by us. Series 60 is a

standardization of the user interface; therefore the screen size of all Series 60 phones is

the same (176x208). In the future, this will get more flexible and bigger screen sizes will

be introduced to Series 60. The third parameter specifies the y position, the fourth the

alignment and the last one the x offset.

The status messages work in a similar way. To activate them, uncomment the code

block below. If you take a quick look at it, you’ll see that it uses the TitleFont(),

which is bigger than the AnnotationFont. It also centers the status message.

When you start the game now, it should look like this:

Fig. 27 – The Mopoid game with text.

Great, isn’t it? To make the game really cool, there are still several things left to add...

© 2005 Mopius Page 33/48

Page 34: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 34/48

Step 13 - Reading and writing files

This section will be very important for your future projects. In our Mopoid game, we

will just save the high score to demonstrate how reading and writing files works.

Preparation

Open “MopoidGameEngine.cpp” and go to the “MopoidGameEngine.h” file. Before

the class declaration starts, you will see that we have already defined the file version

number and the file name:

#define MOPOID_FILE_VERSION_NUMBER 1

_LIT(KMopoidDataFile, "settings.dat");

Symbian OS C++ already provides some APIs to access files. First, the corresponding

header file has to be included. Add the following line at the top of the other system

include lines:

#include <s32file.h>

This includes all the functionality we need. We have already added the required libraries

(estor.lib, efsrv.lib) to our project definition (.mmp) in an earlier step.

Setting the file name

In our header file, we just stored the filename of our data file – the path has to be

added dynamically by the application. This can be done by adding the application path,

as we want our data file to be in the same directory where the user installed the game.

Go back to the “MopoidGameEngine.cpp” file and scroll down until you reach

SaveGameProgressL(). This code should be executed first in this function:

TFileName fullName(KMopoidDataFile);

CompleteWithAppPath(fullName);

#ifdef __WINS__

fullName[0] = 'C';

#endif

As you can see, we have to take care when our game is running in the windows

emulator. The environment will return that the application is installed on drive Z,

which is the ROM drive (where the system itself is installed on the phone). Apparently,

it’s compiled onto this (virtual) drive. It’s not writeable, therefore we have to adapt the

Page 35: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 35/48

drive to the standard C drive. On the device, you will get the real path and drive where

the application was installed.

Opening the file

There are multiple ways to write to a file. Here, we will use the most flexible one, which

is based on streams that are put into a store (i.e. the file). This also allows serializing

objects directly into the file and is very helpful if you need to save the game status of a

more complex game.

We use a direct file store, which doesn’t allow modifying the data. That doesn’t matter

for us, as we will replace all of its contents anyway. This code will open the file store:

CFileStore* store = CDirectFileStore::ReplaceLC( CEikonEnv::Static()->FsSession(), fullName, EFileWrite);

store->SetTypeL(KDirectFileStoreLayoutUid);

Note that we use the file server session from the CEikonEnv environment. A file server

takes care of the real writing and reading to and from files. The file server exists only

once for the whole system and you can’t create your own instance – it would just be

possible to connect to it. However, this is an expensive operation, so we will reuse the

file server session that the system uses to read our resource file.

Creating the stream

A store can contain multiple streams; one of them has to be the root stream. For saving

the high score, only one stream is needed. Multiple streams could be useful for saving

the data of individual players. The stream is created and returns its ID, which will be

used later on when we set this stream as the root of the store.

RStoreWriteStream stream;

TStreamId id = stream.CreateLC(*store);

Writing the data

Finally, we get to the point where the data is written to the file. We will write two

integer values to the stream. In Symbian OS, a TInt is defined as a 32-bit variable,

therefore we’ll use the WriteInt32L() function of the stream to write the data.

Page 36: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 36/48

// Write file version number

stream.WriteInt32L(MOPOID_FILE_VERSION_NUMBER);

// Write game progress

stream.WriteInt32L(iSettings.iHighScore);

It is not mandatory to write the file version to the stream. However, it has proven to be

very useful. Let’s assume the following situation – your customer has installed your

Mopoid game on his mobile phone. Later on, you release a new version, which also

saves the player name. Your customer downloads it and replaces the game on his

device. The old data file will not be deleted!

Then he starts up your new game version, which finds the (old!) data file and attempts

to load it, expecting to get the score and the player name. However, as the data file is

still from the old game, it doesn’t include the player name. It’s a lot easier to compare a

version number and handle the case correctly; for example you could also do an import

function...

Closing the file

You’re nearly finished. Just make sure that the data is written and close the file:

// Commit the changes to the stream

stream.CommitL();

CleanupStack::PopAndDestroy(); // stream

// Set the stream in the store and commit the store

store->SetRootL(id);

store->CommitL();

CleanupStack::PopAndDestroy(); // store

The Cleanup Stack

In the function that we have just written, the Symbian OS cleanup

stack is used. This is a very important part of developing in C++

for Symbian OS. The full scope of it is difficult to understand, but

is already covered by lots of literature. Therefore, here’s only a short summary:

Imagine this situation. In a method, you create an object on the heap, your variable is a

pointer to it. Should some function call leave before the method is over, your method

will be left immediately. The framework will clean up all the automatic variables.

Page 37: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 37/48

However, in this case you just have the pointer to an object, which will be destroyed,

but leave the object itself unreferenced in memory. That’s bad.

Therefore, objects that are used through automatic variables have to be pushed onto

the cleanup stack. If a leave happens, the framework will automatically clean up all

objects that are in the cleanup stack.

Normally, you’ll use the cleanup stack like this:

MyObject x* = new (ELeave) MyObject();

CleanupStack::PushL(x);

x->DoSomethingDangerousL();

CleanupStack::PopAndDestroy();

In the file example, we called two functions that had a “C” at the end of their name.

This indicates that they leave an object on the cleanup stack, which you have to clean

up when you no longer need the object. Therefore, two PopAndDestroy()s are used.

Please note that even though the framework will clean up the cleanup stack when a

leave occurs, you have to take care of correct cleanup during an error-free program

execution yourself.

Loading

Saving a file is only half of the story. Fortunately, loading works in a similar way. First,

complete the file name as seen before. Next, the store has to be opened again, this time

for reading.

CFileStore* store = CDirectFileStore::OpenLC(CEikonEnv::Static()->FsSession(), fullName, EFileRead);

After opening the root stream...

RStoreReadStream stream;

stream.OpenLC(*store, store->Root());

... we can read the data:

TInt versionNumber = stream.ReadInt32L();

if (versionNumber != MOPOID_FILE_VERSION_NUMBER) User::Leave(KErrNotFound);

iSettings.iHighScore = stream.ReadInt32L();

Page 38: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

You could improve the handling of a wrong version number, but for the first version

of the game it’s sufficient. Here we just leave with a not found error, meaning that we

were unable to find the correct setting information in the file. The call to this function

(in the ConstructL() of the game engine) traps the exceptions of the load function

and ignores a not found error, which also occurs if no file has been created yet. In the

case of a file not found error, the game simply sets the high score to the default value

of “0”.

Don’t forget about cleaning up after loading all your data!

CleanupStack::PopAndDestroy(2);

Cleanup when your application is uninstalled

Should the user ever decide to remove the game, all files have to be deleted from the

mobile device (this is also one of the requirements to get your application “Symbian

Signed”). The uninstallation is done by a program manger, and your own application

won’t be called when it’s being uninstalled. Therefore, you have to specify which files

will need to be removed right where we define how your application has to be installed.

Fig. 28 – The uninstall application has to remove the new data file as well.

Unfortunately, C++BuilderX is quite limited when it comes to defining your

installation file for your mobile phone, and it makes the task more complicated than it

would be without C++BuilderX.

Switch to build for the target device (ARMI / UREL) first using the blue gearwheels as

we already did in an earlier step. Right-click on the “Package File” in the project pane

and choose “Export PKG File”. This will create a very minimal “Mopoid.pkg” file in

the “./dev/Mopoid/group/” folder.

© 2005 Mopius Page 38/48

Page 39: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 29 – Exporting the package file.

Now, open the file with a text editor. It should look similar to this:

&EN

#{"Mopoid"},(0x01000001),0,1,0

(0x101F6F88), 0, 0, 0, {"Series60ProductID"}

"C:\Symbian\6.1\Series60\epoc32\release\ARMI\UREL\Mopoid.app"-"!:\system\apps\Mopoid\Mopoid.app"

"C:\Symbian\6.1\Series60\epoc32\release\ARMI\UREL\Mopoid.r01"-"!:\system\apps\Mopoid\Mopoid.r01"

"C:\Symbian\dev\Mopoid\data\ball.png"-"!:\system\apps\Mopoid\ball.png"

"C:\Symbian\dev\Mopoid\data\bounce.wav"-"!:\system\apps\Mopoid\bounce.wav"

"C:\Symbian\dev\Mopoid\data\bricks.png"-"!:\system\apps\Mopoid\bricks.png"

"C:\Symbian\dev\Mopoid\data\hit.wav"-"!:\system\apps\Mopoid\hit.wav"

"C:\Symbian\dev\Mopoid\data\levels.dat"-"!:\system\apps\Mopoid\levels.dat"

"C:\Symbian\dev\Mopoid\data\panel.png"-"!:\system\apps\Mopoid\panel.png"

It defines that the installation file only contains one language, English. The second line

contains the name of the application that will be displayed during the installation, its

UID that we set when we created the project, and the version number.

The third line defines that your application can be installed on all Series60 devices, even

on the old Nokia 7650 (which used v0.9 of the Series 60 SDK). If you develop an

application that isn’t backward-compatible, you have to use a different Series 60

Product ID.

Then, the package file defines that both your application and the resource file (which

contains strings and menu definitions) are copied to the device into the

“\system\apps\Mopoid\” folder. The “!” at the beginning means that the user can

choose on which drive to install the application. The internal, writeable memory of

Series 60 devices is drive “C”, the optional MultiMediaCard has the drive letter “E”.

OK, our application will create a new file when it’s running. It doesn’t have to be

© 2005 Mopius Page 39/48

Page 40: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 40/48

installed, but has to be removed when the game is uninstalled. How does it do that?

The following line does what we need:

""-"!:\system\apps\Mopoid\settings.dat",FN

FN means “FileNull”. The SDK help has a nice definition of what this line means:

A file which does not yet exist, so is not included in the sis file. It is created by the

running application and will be deleted when the application is removed. The name

assigned to the source file is unimportant and should be empty, i.e. “”. Note that such

files will not be deleted when upgrading to a later version. This ensures that such files as

.ini files, which store application preferences, are not lost in an upgrade.

Building from the command line

Unfortunately, C++BuilderX doesn’t care about the package file it has exported.

Therefore, from now on you have to make the installation file (.sis) from the command

line. First, make sure that your IDE is still set to compile for ARMI / UREL (blue

gearwheels). Compile the project using “Project” -> “Make Project ‘Mopoid.cbx’”.

Now, open a command window (“Start” -> “Execute” -> type in “cmd”) and switch to

the “C:\Symbian\dev\Mopoid\group” folder. To make this faster, maybe you should

install the “Command Window Here” PowerToy from Microsoft. Enter the following

command:

makesis Mopoid.pkg

This will assemble the .sis file using the information from your own package file, and a

“Mopoid.sis” file should now be available in the same directory. Try it on your mobile

phone! It makes sense to write a small batch file that contains the command above, so

that you don’t have to type it in every time you want to build for the device.

When you’re finished, don’t forget to switch back to compile for the windows debug

emulator again (WINS / UDEB)!

Step 14 - Setting the application icon

Some information, like the application icon and caption, are stored in an .AIF file

(Application Information File). In this step, we will create this for our project.

Page 41: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Go to “File” -> “New...” . Choose the category “Mobile C++”, select the “New

Symbian AIF Wizard” and click on OK. Accept the default values of the page showing

Step 1. Step two is more interesting, now you will add the icons that will appear in the

menu of your mobile phone.

Fig. 30 – Adding icon files to the game.

Add the bitmaps from the “aif” directory of the project in the order shown above –

always the icon bitmap file first, then its mask. Don’t forget to click the “Add” button

after selecting a file!

When you’re done with adding all four files, go to step three. Now you will add the title

of the game. As Mopoid only supports English, simply enter the caption “Mopoid” and

leave the language at “ELangEnglish”. Click on “Add”.

Fig. 31 – The English caption is now defined.

© 2005 Mopius Page 41/48

Page 42: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

Fig. 32 – Opening the resource file to fix a C++BuilderX bug.

After clicking on “Finish”, everything should normally be finished. However, there is

some kind of strange bug in the current version of C++BuilderX, because you won’t

see any icons if you compile the game now. To fix this, double click on “Mopoid.rss”

(found in the “Aif” folder) in the project pane to open it.

Find the line containing num_icons and change its value from 4 to:

num_icons = 2;

We only added two icons in different sizes, and their respective masks. C++BuilderX

should actually know those requirements, but apparently it doesn’t.

Step 15 - Handling being in the background

Symbian OS is a multitasking operating system. While your application is running,

many other events could send your application to the background or draw an alert on

top of it. Examples: an incoming call or message, a low battery warning, the user

sending your application to the background by pressing the red button, etc.

Fig. 33 – The game should be paused automatically

when it gets sent to the background.

© 2005 Mopius Page 42/48

Page 43: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 43/48

Even for a small game like Mopoid it’s very important to handle this event. The game

has to be paused so that it doesn’t continue while the user is unable to play. Also, it

should use as few system resources as possible by stopping the continuous screen

updating process. It’s also a good idea to save the game progress.

Symbian OS will send an event to your application when it gets sent to the background.

The function “HandleForegroundEventL()” of the active view is called.

C++BuilderX didn’t implement it when it created the code, so we’re going to do it now.

Open “MopoidView.cpp” and go to its header file. Note that the CMopoidView class is

derived from CAknView, which already defines HandleForegroundEventL(). As we

will implement the function, add the following definition at the end of the public

function definitions:

void HandleForegroundEventL(TBool aForeground);

The parameter aForeground specifies whether our application was sent to the

background, or if it gained the focus again. Switch back to “MopoidView.cpp” and add

the following function at the bottom of the file:

// Handle any change of focus

void CMopoidView::HandleForegroundEventL(TBool aForeground)

{

if (aForeground) // gained focus

{

// Don't resume the game - wait for user to resume it

iContainer->iGameEngine->iHaveFocus = ETrue;

}

else // lost focus

{

// Pause game

if (iContainer)

{

iContainer->iGameEngine->PauseGame();

iContainer->iGameEngine->iHaveFocus = EFalse;

}

}

// call base class event handler

CAknView::HandleForegroundEventL(aForeground);

}

Page 44: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 44/48

As you can see, depending on whether the application got or lost the focus, a status

variable of the game engine is modified accordingly. Note that it’s not good to resume

the game right when the application gets the focus again – it’s better to let the user start

the game when he is ready.

Our own implementation overrides the base implementation, which also has to be

called at the end of our function.

Step 16 - Periodic Events

The update of the game itself is done using an “Active Object”, the corresponding class

can be found in the “UpdateAO.cpp” file. This means that the game doesn’t have a

fixed frame rate and measures the time between the frames to find out how much the

ball and the panel have moved since the last frame.

This means that all values are calculated internally using floating point numbers.

Unfortunately, the processors in mobile phones don’t support floating point values, so

all this is emulated in software, which makes those calculations much slower than their

integer counterparts.

For many games it would be sufficient to use a fixed frame rate, with periodic callbacks

from a timer. The movements could then be fixed integer numbers, without the need to

do those more accurate calculations.

Keeping the backlight on

Mopoid still uses a fixed timer (which is actually also an active object that’s provided by

Symbian OS). It’s used to decrease the score of the player every five seconds, to make

the game more challenging. Another issue is that the phones switch off their backlight

if no key has been pressed for some time. This is bad when the user is still playing, and

just waiting for the ball to come down again. Therefore, we have to reset the user

inactivity timer of the phone every few seconds. This is done using the following call,

which you should add to the timer callback function (DoCallBack()) of the game

engine class:

User::ResetInactivityTime();

Page 45: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 45/48

Using a timer

What we have to do now is to activate the timer, so that this function gets called at all.

Scroll up a bit and you’ll find the “StartTimerL()” function of the game engine class.

The timer object has already been declared as a private member variable of the game

engine class:

CPeriodic* iPeriodicTimer;

Therefore, in the function mentioned above, we have to create the timer object and

start it:

iPeriodicTimer = CPeriodic::NewL(CActive::EPriorityLow);

iPeriodicTimer->Start(KTickInterval, KTickInterval, TCallBack(TimerCallBack, this));

Note that we use the static NewL() function of the CPeriodic object that Symbian OS

provides. We do this because iPeriodicTimer is a member variable, therefore the

object isn’t pushed onto the cleanup stack. If anything serious fails, the object will be

deleted by the destructor of the game engine.

In the next line we start the timer and tell it to do callbacks every 5 seconds

(KTickInterval is set to 5000000). The last parameter specifies the callback function

that the timer will call every five seconds. Its name is “TimerCallBack()” and it is

part of the game engine class (referenced by this). This function is already

implemented by the example code.

Stopping the timer

When the game is paused or ends, the timer has to be stopped (and deleted). This is

quite simple. The following source code goes into the StopTimer() function.

if (iPeriodicTimer)

{

iPeriodicTimer->Cancel();

delete iPeriodicTimer;

iPeriodicTimer = NULL;

}

The cancel function of the timer is called to stop it. Then the object will be deleted and

set to NULL so that everyone knows that the timer is no longer here. If we need it again,

it will just be created again.

Page 46: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 46/48

Step 17 - Final notes

The game is finished! If you wish, you can take a look at some other parts of the source

code that are not part of this tutorial. For example the sound playing routines are quite

interesting. The game also uses an external level file. You can edit it with a normal text

editor and quickly create your own levels. This file is read and parsed by the game.

About the author

This tutorial was written by Andreas Jakl. He is the founder of Mopius, a company

which creates innovative mobile products that let users experience what they have

never seen before.

The game “The Journey” is one of the world’s first mobile, location-based adventure

game. It was released as an open source game and has already been downloaded more

than 10,000 times. Its successor, “The Journey II”, extends the concept and creates a

huge and fascinating virtual world to be explored by the player. The two games have

received several awards, including “Most Innovative Game” (Mobile Fun Awards) and

a jury award of the “Austrian State Price”. The game has even been featured on TV.

Contact

To get more information or to get in contact with the author:

Mopius

Andreas Jakl

Widerinstr. 22

3100 St. Pölten

Austria / Europe

email: [email protected]

web: http://www.mopius.com/

tel.: +43 (0)676 / 722 82 78

Page 47: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 47/48

Copyright

This tutorial is copyrighted by Andreas Jakl. You are free to use the source code of the

Mopoid game (licensed as GPL) provided as part of this tutorial in your own projects.

If you would like to use this tutorial (or parts of it) for own courses, please contact us.

You are not allowed to republish it without explicit written permission by the author.

Republish by Symbian with permission.

Page 48: Symbian OS Workshop - 123seminarsonly.com€¦ · • Microsoft Debugging Tools: needed to debug applications in the emulator through Borland’s C++BuilderX – • Visual C++ Toolkit:

Symbian OS – Workshop

© 2005 Mopius Page 48/48

Step 18 - Exercises

If you want to do some tasks on your own, below are suggestions on how the game

could be improved:

Alternative key handling

Some Series 60 phones have a joystick that’s far from perfect. Those users might prefer

to control the panel using the number keys. Add an alternative key handling to allow

controlling the panel using the 4 (left) and 6 (right) keys. You can handle them in the

same switch case as for the joystick movements. Hint: handle the number keys by using

something like “case '4':”

Define more levels

The sample game comes with five levels – enough to try it out, but there could be

more. Take a look at how the levels are defined in the “levels.dat” file, find out

what kinds of bricks the numbers in the file define, how many lines make up one level.

Then add new levels and configure the game so that it knows about your additions.

Remember to execute “dobitmaps.bat” after you changed the “levels.dat” file, so

that it’s copied to the correct directory where the emulator will find it!

Saving the game progress

Especially when the game is longer, it’s important that the user can resume a game later

on. It should therefore be possible to save (at least) the current level and the score that

the player had when he entered the level. You’d have to save the score in a new

member variable.

To save this, extend the data file by a flag signaling whether a game is/was active, the

score the player had when he entered the level and the level he was playing.

When the player leaves the game and the game is active, set the flag to true and save the

game data. The next time the game is started, those values should be restored.