Archive for the ‘programming’ Category

How I developed and released a mobile game in 45 hours

Tuesday, December 4th, 2012

icon_96_transparentDeveloping a game always takes longer than expected. I made an experiment and tried to develop a simple but descent game quickly, while keeping tracks of time spent on each feature. I also wanted short development times to see if I can make a profitable game, even if I were paid for it (I’m not doing this for a living, just for fun).
This experiment ended with the game Hashi Puzzles: Bridges & Islands, available right now for Android and iPhone/iPad (free download).

Simple design

In order to release the game quickly, I had to have a safe design, without too much risks. I therefore came up with the idea of implementing a game of Hashiwokakero (Wikipedia), a logic game made by the inventors of sudoku. I know the “gameplay” has already been tried and it’s fun: I won’t need to spend time iterating or tweaking the design.
As I’m not an artist, this is also a good choice because it is graphically simple. I initially planned to do all the art myself, but my brother (Vincent) nicely offered his help when I gave him an early build of the game. He therefore made the game icon and logo. He also worked with a tight deadline (1 day).
To have a complete and polished game, I added levels, level packs, hints and a progression (inspired by the great game Flow (Google Play, AppStore)).
I also integrated ads that are removed when the player purchases any of the six purchasable level packs. Purchases are made with in-app payments.
The game has no music, and only very basic sound in the menu (actually, the code used to play the validation sound in the mainmenu is in my framework so it was faster to keep it than to remove it).
The game is translated in French and English. [By the way, if you can speak any other language, feel free to contact me as I'd love to port the game in other languages. The game has very few texts, as you can see on the editable texts sheet, and a simple description on the stores].
With the design in place, experience gained from a released mobile game (Don’t Feed the Trolls), and an engine ready (cocosd-x), I can start the actual development of the game.

45 hours

I worked on the project part-time, mostly in the evening when my kids are sleeping ;) .
The android version of the game was made and released after 45 hours of work distributed in 11 days. I don’t count the time spent thinking about it in the shower, though :)
I then spent another 5 hours to port, build and submit the iOS version. In addition to creating the project, I added a feature on iOS that I didn’t implement in my previous game: the ability to use iAd as well as AdMob as advertising sources.
It also took 5 hours for the Amazon App Store Kindle version (it’s in review right now and should be available in a few days). It was the first time I implemented the in-app API for Amazon, that’s why it took a bit longer than it should have.
My brother spent a total of 5 hours on the art (on the last day).

Total breakdown per feature and sub-feature

Here is the time spent per feature:
feature
I included everything in this chart : my work, the artist’s work and the ports to iOS and Amazon. This is a total of about 60 hours. We can see the distribution is quite even between each feature.
It’s more interesting to see a sub-feature breakdown:
subfeature
A few comments about this chart:

  • I develop as much as possible on Windows, with Android being my main real device test target. Therefore, I grouped together windows and android in a platform specific category because most of the specific behavior is done on windows if possible (portrait orientation for instance).
  • The tutorial took quite some time to implement but it was done twice. After the first playtest with my wife, I realized the tutorial was not understandable at all and I changed it entirely.
  • Optim is performance optimization so that the game can run on lower end devices. I first made everything working, and then optimized it, mostly by reducing draw calls with the techniques I describe in this article.
  • Most of the time was spent building the UI of the menus. I have three screens:
    • the main menu with three buttons
    • the pack selection screen with a vertical smooth scrolling
    • a level selection screen with horizontal scrolling with pages

    I already did these kind of menus in my previous game, but it still required some work to put it all together correctly in Hashi Puzzles.

  • In the core gameplay section, the longest part was obviously the level generation part. In order to have only interesting levels, I had to tweak the level generation for some time. I also had to develop a solver to help the generation. However, the puzzle solver allowed me to develop the “hints” feature very quickly.

Conclusion / Tips

Developing this game was very intersting and I (objectively? :) ) think the game is good even if it was developed in only 45 hours. There are a few features that I did not implement to save time, and that I might implement later on:

  • Different theme/colors (estimation: 1h30)
  • Player statistics (estimation: 0h30)
  • Improved art (estimation: 3h)
  • “Smart hints” (hints are currently just brining attention to specific islands, I could be way better with text explaining the hint) (estimation: 2h30)
  • Detection of isolated islands to tell the player (estimation: 2h)

I will probably make an article about the revenue of the game in a month or two.
Please try the game (Android, iOS), share it with your friends and rate it if you like it!
Feel free to comment here or on twitter if you have any questions about the game or the experiment!

Building for Android with Cocos2d-X (NDK+JDK) in one step

Friday, October 5th, 2012

One Step to Better Code

Recently, I’ve read once again the old but awesome article “Joel Test : 12 steps to better code” (do it now if you haven’t). When developing Don’t Feed the Trolls, I always had a few steps to build a new android version of the game. I made a few scripts but I still had multiple steps. My workflow was:

  1. Copy the resources in the android assets folder
  2. Compile the C++ code with Gygwin
  3. Launch eclipse
  4. Use option Android / Build Signed Package in Eclipse
  5. Type two passwords for signature

I recently improved this workflow, and now it is:

  1. Double click the “build_android.bat” file

Much better!
Here are details of the script.

1. Copying the resources

It’s simple batch script that copies the resources from the multiplatform “Resource” folder (used in cocos2d-x templates) to the assets folder used on Android.

rmdir /S /Q "D:\gamedev\Games\swg21\Dev\android\assets"
mkdir "D:\gamedev\Games\swg21\Dev\android\assets"
xcopy "D:\gamedev\Games\swg21\Dev\Resource" "D:\gamedev\Games\swg21\Dev\android\assets" /S /H
del "D:\gamedev\Games\swg21\Dev\android\assets\snd\*.wav"

I first delete the existing files. Then I create the directory and copy all my resources. Finally, I remove wav files, as these are used only on the windows version. My multiplatform Resource folder contains sound in formats for all platforms.

2. Compiling the C++ source code

The native C++ code is compiled in cygwin. I spent a lot of time trying to figure out how to run a script from a batch and having it return immediately (with an error code). For the record, I was missing the –login parameter to the bash command. Here is the command I use:

cd "d:\gamedev\cygwin\bin"
bash --login "./swg21.sh"

The swg21.sh is a bash script placed in my home folder, calling cocos2d-x build_native script.

cd /cygdrive/d/gamedev/games/swg21/dev/android
./build_native.sh

build_native.sh is a bash script calling ndk-build after setting up proper environment variables.

3. Compiling the java and creating the signed apk

This was the main step I wanted to optimize from my previous workflow. Running Eclipse just to build a version was really slowing down the whole process. For that part, you have to use ant, as explained in the Google documentation.

cd "D:\gamedev\Games\swg21\Dev\android"
call ant release

The problem was that I was still asked to enter my password to sign the apk. This is fixed by editing the ant.properties file, as shown below (Credit goes to NickT from stackoverflow):

key.store.password=password
key.alias.password=password
key.store=path/to/your.keystore
key.alias=alias

4. Dropbox

I use dropbox to transfer apk to my Android device. Therefore, I need to copy the file to my dropbox folder.

copy "D:\gamedev\Games\swg21\Dev\android\bin\swg21-release.apk" "C:\Users\Win7\Dropbox\temp\swg21.apk"

5. Error checking

Steps 2 and 3 can fail (compile errors). I added some batch script to change the screen color to green when it’s successful, and red if not. Here is the final build_android.bat with error management.

@echo off
@echo "============================================ COPY RESSOURCES"
rmdir /S /Q "D:\gamedev\Games\swg21\Dev\android\assets"
mkdir "D:\gamedev\Games\swg21\Dev\android\assets"
xcopy "D:\gamedev\Games\swg21\Dev\Resource" "D:\gamedev\Games\swg21\Dev\android\assets" /S /H
del "D:\gamedev\Games\swg21\Dev\android\assets\snd\*.wav"

@echo "============================================ COMPILE NDK"
cd "d:\gamedev\cygwin\bin"
bash --login "./swg21.sh"
IF %ERRORLEVEL% NEQ 0 GOTO FAIL
GOTO SUCCESS
:FAIL
COLOR 40
GOTO END
pause
:SUCCESS

@echo "============================================ COMPILE JDK+Sign"
cd "D:\gamedev\Games\swg21\Dev\android"
call ant release
IF %ERRORLEVEL% NEQ 0 GOTO FAIL

@echo "============================================ COPY FILE TO DROPBOX"
copy "D:\gamedev\Games\swg21\Dev\android\bin\swg21-release.apk" "C:\Users\Win7\Dropbox\temp\swg21.apk"
COLOR 20
:END
pause

Improvements and Conclusion

I’m glad I did this script and don’t understand why I didn’t do it earlier. I now build a new Android apk almost every night.
If you’re working on a team, you might also add source control scripts to get the latest version of your code/resources automatically. Also, my projects path are hardcoded, I should set “swg21″ (the project name) in a command line parameter and use relative paths. I’ll probably do it when I’ll use this script for a second project.
I’ll also do the same thing for iOS when my current project will be closer to release (I’ve read it’s not that trivial to do, we’ll see).
Feel free to share and comment this article here or on twitter.

A simple but useful Finite State Machine (FSM) in C++

Thursday, October 4th, 2012

Why?

When developing games, I often need FSMs. Most of the time, they are simple with only a few states. Some examples of state machines I used in previous or current games:

  • Tutorial: each state represents a step in the tutorial
  • UI : The animated elements are using a FSM to transition from “on-screen” to “off-screen” going through a “moving” state.
  • Game State : Playing, Paused and End-of-level screens

Some complex FSMs are often used in AI. I used some in this prototype.

Features

I realized that I always implemented the same methods when adding a FSM into an object, therefore I took a few minutes to implement a simple class I could re-use easily. Here are the features of this FSM:

  • The states are represented by an enum (easy to debug)
  • To run the FSM, just call SetState and UpdateFSM( float delta_time )
  • Get the current state using GetState()
  • Many transitions are based on timing. Therefore, I implemented a GetTimeInCurState() method
  • Perform your specific actions in methods BeginState, EndState and UpdateState

Source Code (.h)

// (c) Francois Guibert, www.frozax.com (@Frozax)
#pragma once

template<typename T>
class fgFSM
{
public:
	fgFSM() : _time_in_cur_state(0.0f), _cur_state(-1)
	{
	}

	virtual void BeginState( T state ) {}
	virtual void UpdateState( T state ) {}
	virtual void EndState( T state ) {}

	void SetState( T state )
	{
		EndState( (T)_cur_state );
		_cur_state = state;
		_time_in_cur_state = 0.0f;
		BeginState( (T)_cur_state );
	}

	void UpdateFSM( float delta_time )
	{
		if( _cur_state != -1 )
		{
			_time_in_cur_state+=delta_time;
			UpdateState( (T)_cur_state );
		}
	}

	float GetTimeInCurState() { return _time_in_cur_state; }
	T GetState() { return (T)_cur_state; }

private:
	float _time_in_cur_state;
	int _cur_state;
};

Usage

First create the enum you will use for the states, such as:

enum EState
{
	STT_OFF = -1, // optional, -1 is the initial state of the fsm
	STT_WALK,
	STT_RUN,
	STT_STOP,
	STT_EAT
};

And inherit from the class fgFSM:


class ObjectUsingFSM: public fgFSM<EState>
{
public:
	// ...
	void UpdateState( EState t );
	void BeginState( EState t );
	void EndState( EState t );
	// ...
};

Improvements, Closing Words

That’s it, feel free to use the code in your games/projects. This is very simple but often more than enough. The other feature you might need one day is having a GetPreviousState() or even a GetNextState() usable in EndState().
Questions? Contact me on twitter @frozax or comment here.

Optimizing Graphics Performance on iOS and Android

Tuesday, May 22nd, 2012

The main device is used during the development of Don’t Feed the Trolls is an Acer Iconia Tab A500. It’s quite powerful and I never met performance issues with it.

Of course, I tested the game on many other iOS and Android devices. I was surprised to discover strong performance issues on a HTC Desire.

In this article, I will explain the reasons of these low performances and how I fixed them. I will also give you tips on how to find out where are the potential problems.

Problem 1 : in-game, the game was slower and slower when getting closer to the end of the level

O03. Screenshot - Slap Party Game ModeOf course, the difference at the end of the level is that many bears and trolls have been displayed so the problem probably has to do with that. However, there was never more than 3 or 4 characters visible at the same time.

Also, to avoid memory allocation during gameplay, I pre-allocate all the character sprites used in the level at the start of the level. So the problem was not memory related. Finally, the game code dealing with inactive or invisible characters was doing nearly nothing.

I finally found out the problem is caused by characters that disappeared. They are displayed, but fully transparent. I used a CCFadeOut action to hide the sprites. At the end of the CCFadeOut, the object was still displayed, but with an opacity of 0. An easy fix is to hide the sprite (CCHide action) at the end of the fade out to avoid a useless draw call.

Fix 1 : Make sure you do not have invisible sprites (completely transparent or with very low opacity). Destroy or hide them instead.

Problem 2 : the main menu is very slow

05 - Screenshot - Menu - Achievements ListMy menus have many animated transitions, for instance when you choose the “achievements” menu, the game mode selection screen leaves to the left, while the achievements screen comes from the right. There is also a credits screen, a level selection screen (for the classic mode) and a difficulty selection screen (for the versus mode). All these screens are built once when loading the main menu. They are simply off-screen when not displayed to the player.
The performance problem was therefore obvious: all the offscreen items were slowing down the whole program. I thought cocos2dx or the device itself would not display offscreen items but I was wrong. Simply hiding these items improved the performance greatly. In the achievements list (see screenshot on the left), I hide every line and sprite as soon as it’s out of the screen. It requires specific code but it’s really worthwhile.

Fix 2 : Do not have elements displayed off screen. Remove them from the scene or hide them instead.

Problem 3 : the main menu is slow when the rankings are displayed

07 - Screenshot - Menu - RankingsIn the main menu, when the rankings are displayed (see screenshot on the left), the fps drops heavily. Obviously, this is caused by the quantity of text. Cocos2dx optimizes the texts by using a single OpenGL draw call to display a string, instead of drawing each character one by one. It’s good but not enough in my case. I initially used a simple (and logical) approach and had one CCLabelBMFont per element of the rankings. There are up to 10 lines with 3 elements per line (position, name, score), and two headers. That’s a total of 32 draw calls here, only for texts. I updated the code so that all the rankings texts are now displayed with a single draw call (see below for implementation details). The game is now running smoothly.

Fix 3 : Use as few draw calls as possible by grouping sprites together

How to reduce draw calls with Cocos2d-x?

The easiest way to reduce draw calls is to use a CCSpriteBatchNode. If you have multiple sprites using the same texture, they can be displayed in one call if they share the same CCSpriteBatchNode parent. Hopefully, as I use texture pages, my sprites are nearly all in the same texture (see How to pack your textures). Here are some examples of optimizations I did in Don’t Feed the Trolls:

  • All the elements of the UI (timer bar, troll head, red cross…) now share the same CCSpriteBatchNode (up to five draw calls removed)
  • The bears are displayed with two sprites, the trolls with three sprites. Each character is now displayed as a CCSpriteBatchNode (one or two draw calls removed per character)
  • In the main menu, the rankings background is using the same sprite twice, they now share the same CCSpriteBatchNode (one draw call removed)

For the fonts, the CCLabelBMFont is a CCSpriteBatchNode itself (derivation). However, I have so much text in the rankings that it still slows down the game (Problem 3). I made some code to regroup all the texts of the rankings together under one CCLabelBMFont. As I used different scale, colors, and alignment, it’s not trivial and can’t be done automatically with a single CCLabelBMFont. I decided to have the CCLabelBMFont class positions the letters properly, and then move each letter under a “master label”, and finally deleting the original label. Here is the raw code I used (_mega_label is the node that contains all the text, bmf is the label we want to add to the mega label (temporary object)) :


	// copy the label to mega_label and delete it
	CCArray *children = bmf->getChildren();
	if( children )
	{
		// loop through all characters
		while( children->count() )
		{
			CCNode *ch = (CCNode*)(children->objectAtIndex( 0 ));
			// remove characters from current label (retain it before removing it)
			ch->retain();
			bmf->removeChildAtIndex( 0, true );
			Vector2 char_pos = ch->getPosition();
			// compute proper position taking scale into account
			char_pos.x = char_pos.x*scale + p.x;
			char_pos.y = char_pos.y*scale + p.y;
			ch->setPosition( char_pos );
			ch->setScale( scale );
			// add it to label
			_mega_label->addChild( ch );
			// Don't Feed the Trolls specific : I keep a list of animated sprites
			// (they have there opacity animated)
			// I do it manually instead of using an action
			if( is_local_player )
			{
				// need an animation, add the sprite to a specific list
				_animated_sprites.push_back( (CCSprite*)ch );
			}
			ch->release();
		}
	}
	// free the original label
	bmf->release();

How to find out where to optimize?

You don’t need to optimize everything, just the slow sections of your game. Here is how I found out where to optimize:

  • I display on screen the draw call count. To do that, I hacked into cocos2d-x code and simply added a global counter before each call to glDrawArray or glDrawElements. I used a #define to easily remove this code in released versions of the game. Be careful to ignore the sprites used to display the debug text itself.
  • I also have a function that goes recursively inside a CCNode and count visible/hidden nodes, nodes with low opacity (less than 10) and so on. Very handy to detect items not visible because they are out of the screen or with a very low opacity.
    Here is the code used, adapt it to your needs:

    
    int nb_nodes, nb_visible_nodes, nb_rgba_nodes, nb_not_letters_nodes,
    	nb_not_letters_visible_nodes, nb_low_opacity_nodes;
    
    // recursive function counting
    // please note that I'm using an old version of cocos2d-x, with
    // convertToLabelProtocol and convertToRGBAProtocol: I found the
    // new version with RTTI a terrible idea and reverted it
    void DEBUGCountNodes( CCNode *n, bool parent_visible, bool is_letter )
    {
    	nb_nodes++;
    	bool we_are_visible = n->getIsVisible() && parent_visible;
    	bool father_is_label = is_letter;
    	bool we_are_label = is_letter || (n->convertToLabelProtocol() != NULL);
    
    	if( we_are_visible )
    		nb_visible_nodes++;
    	if( we_are_visible && !father_is_label )
    		nb_not_letters_visible_nodes++;
    	if( !father_is_label )
    		nb_not_letters_nodes++;
    
    	if( n->convertToRGBAProtocol() )
    	{
    		// count low opacity nodes (if below 10/255)
    		if( n->convertToRGBAProtocol()->getOpacity() < 10 && we_are_visible )
    			nb_low_opacity_nodes++;
    		nb_rgba_nodes++;
    	}
     	// recursive part
    	if( n->getChildren() )
    	{
    		for( unsigned int i = 0; i < n->getChildren()->count(); i++ )
    		{
    			DEBUGCountNodes( (CCNode*)(n->getChildren()->objectAtIndex(i)),
    				we_are_visible, we_are_label );
    		}
    	}
    }
    
    // initial function to call, usually with the initial node of your sprite
    // hierarchy (mine is called _main_node)
    string fgGame::DEBUGCocosNodes( CCNode *start )
    {
    	if( start == NULL )
    		start = _main_node;
    	nb_nodes = nb_visible_nodes = nb_rgba_nodes = nb_not_letters_nodes =
    		 nb_not_letters_visible_nodes = nb_low_opacity_nodes = 0;
    	DEBUGCountNodes( start, true, false );
    	char str[256];
    	sprintf( str, "All:%d/%d NoTxt:%d/%d LowOp:%d", nb_visible_nodes, nb_nodes,
    		nb_not_letters_visible_nodes, nb_not_letters_nodes, nb_low_opacity_nodes );
    	return str;
    }
    

The great thing with this logging is that you can run it on the Windows build.

Conclusion

Make sure you test your app on a few less powerful devices. If you keep in mind the tips in this article and display debug information from time to time, you should easily be able to optimize the slowest code of your game.
From my tests, I found out that trying to have a maximum of 30 draw calls is a good way if you want to achieve 50 or 60 frames per second on nearly all medium-end devices. Of course, this is heavily empirical and you’ll have to do you own tests.

I hope this helped, feel free to comment and talk about your optimization techniques in the comments, on twitter or on facebook.

And don’t forget to try and rate Don’t Feed the Trolls (Free download, iTunes, Google Play)!

How to create a shake action in Cocos2d-x (with source code)

Monday, February 27th, 2012

While working on my next game Don’t Feed the Trolls, I was looking for a “shake effect”. When the player feeds a troll, I want the whole screen to shake to improve visual feedback.
A shake effect is very easy to implement, so I quickly hacked in my code to see if it was un interesting feature. After a quick test on the Android version of the game, I could see it really does improve the game. So I wrote a proper cocos2d-x action to integrate the effect in a clean way. I’m releasing the code here hoping other developers will find it useful for their own games.

The effect

The shake is a small random movement. It can be applied to any cocos2d node (CCNode). In Don’t Feed the Trolls, I applied the effect to my top-most node, therefore the whole screen is shaking.

The action

I derived my CCShake class from CCActionInterval. The action is initialized with two parameters:
- time : the duration of the effect.
- strength : the distance of the shake movement. You can have different strengths in X and Y if you wish.
You create the action with CCShake::actionWithDuration and send it as a parameter of CCNode::runAction.


// Shake node_to_shake for 5 seconds.
node_to_shake->runAction( CCShake::actionWithDuration( 5.0f, 10.0f ) );

When the action is completed, the node is moved back to its starting position.

Source code

The code is free for personal and commercial use. If you plan to use it, feel free to credit me, send me an email and/or follow me on twitter/facebook. This is of course not compulsory.

Header: CCShake.h


#ifndef __SHAKE_H__
#define __SHAKE_H__

#include "CCActionInterval.h"
using namespace cocos2d;

class CCShake : public CCActionInterval
{
	// Code by Francois Guibert
	// Contact: www.frozax.com - http://twitter.com/frozax - www.facebook.com/frozax
public:
	CCShake();

	// Create the action with a time and a strength (same in x and y)
	static CCShake* actionWithDuration(ccTime d, float strength );
	// Create the action with a time and strengths (different in x and y)
	static CCShake* actionWithDuration(ccTime d, float strength_x, float strength_y );
	bool initWithDuration(ccTime d, float strength_x, float strength_y );

	virtual void startWithTarget(CCNode *pTarget);
	virtual void update(ccTime time);
	virtual void stop(void);

protected:
	// Initial position of the shaked node
	float _initial_x, _initial_y;
	// Strength of the action
	float _strength_x, _strength_y;
};

#endif //__SHAKE_H__

Source: CCShake.cpp

// Code by Francois Guibert
// Contact: www.frozax.com - http://twitter.com/frozax - www.facebook.com/frozax
#include "cocos2d.h"
#include "CCShake.h"

// not really useful, but I like clean default constructors
CCShake::CCShake() : _strength_x(0), _strength_y(0), _initial_x(0), _initial_y(0)
{
}

CCShake* CCShake::actionWithDuration( ccTime d, float strength )
{
	// call other construction method with twice the same strength
	return actionWithDuration( d, strength, strength );
}

CCShake* CCShake::actionWithDuration(ccTime duration, float strength_x, float strength_y)
{
	CCShake *p_action = new CCShake();
	p_action->initWithDuration(duration, strength_x, strength_y);
	p_action->autorelease();

	return p_action;
}

bool CCShake::initWithDuration(ccTime duration, float strength_x, float strength_y)
{
	if (CCActionInterval::initWithDuration(duration))
	{
		_strength_x = strength_x;
		_strength_y = strength_y;
		return true;
	}

	return false;
}

// Helper function. I included it here so that you can compile the whole file
// it returns a random value between min and max included
float fgRangeRand( float min, float max )
{
	float rnd = ((float)rand()/(float)RAND_MAX);
	return rnd*(max-min)+min;
}

void CCShake::update(ccTime time)
{
	float randx = fgRangeRand( -_strength_x, _strength_x );
	float randy = fgRangeRand( -_strength_y, _strength_y );

	// move the target to a shaked position
	m_pTarget->setPosition( ccp( randx, randy) );
}

void CCShake::startWithTarget(CCNode *pTarget)
{
	CCActionInterval::startWithTarget( pTarget );

	// save the initial position
	_initial_x = pTarget->getPosition().x;
	_initial_y = pTarget->getPosition().y;
}

void CCShake::stop(void)
{
	// Action is done, reset clip position
	m_pTarget->setPosition( ccp( _initial_x, _initial_y ) );

	CCActionInterval::stop();
}

Possible improvements

This is really a simple class, for a simple effect. You can improve the effect in many ways. For instance, we could animate the strength of the shake over time.

That's it !

Have fun with it, feel free to discuss the source code in the comments, twitter or facebook.

Why and how to pack your textures for iOS/Android

Sunday, December 4th, 2011

Introduction

When I developed Don’t Feed the Trolls on X360 (using XNA), I did not optimize the textures files of the game : the game was very simple, the final hardware (X360) is very fast, so it was not necessary. I arranged the sprites so that I could get their coordinates in-game very easily. Every “troll” sprite for instance is the same size, so most of them are filled with transparent pixels. A lot of space is wasted. Have a look at the sprite sheet for the characters that I use on X360.

X360 Don't Feed the Trolls Characters Sprite Sheet

The characters texture on X360 is 2048×1024. I could easily have it into a 1024×1024 but it was a lot easier if I could have all the sprites of the same kind in a row (for example, all the bear heads are on the top row). I also made a few other sprites sheets for UI, birds, tutorial for instance.

For the first draft of my Android port, I first concentrated on the gameplay and integrate this sprite sheet as is. Of course, I quickly realized I had to spend some time to optimize as obviously, constraints on mobile and X360 are different.

Why packing your textures?

Why is proper texture packing important for games, especially on mobile? Packed textures use less pixels, and from this simple fact, the game is greatly improved in many ways:

Memory

Less pixels takes less memory. Mobile have big memory constraints and saving memory from the ressource is great. Texture ressources are often the biggest ressources.

Loading

There are less files to open, and less pixels to read, this will therefore be faster to load.

Runtime performance

When packing your textures in atlases, more sprites will share the same texture. In runtime, the GPU will then have less textures changes to make and this will therefore speed up your game. This will improve performance if you draw the sprites using the same texture in a row.

It will allow you to reduce your texture sizes. Some Android devices are performing very slowly with 2048 pixels-wide textures.

Game size

The downloadable package size will be smaller too. This is great, especially for people using 3G or with limited bandwidth that won’t download big games.

How to pack?

I first thought of packing my sprites manually but quickly searched for a tool to assist me in that tedious task. There are a few tools available to automatically pack your sprites, and I am currently using TexturePacker, and I’m very happy with it (please note that I got a free copy of TexturePacker from the developer). It’s easy to use and has a lot of functionnalities, such as:

  • Auto-refreshes the packed texture in the tool when I add images to my folders
  • Export in one click
  • Support cocos2d and therefore cocos2d-x which I am using (and many more formats).
  • Removes useless transparent pixels around sprites
  • Efficient packing

All the features are listed here.

Here is a sample of a packed sprite sheet for the Android version of Don’t Feed the Trolls made with TexturePacker:

Packed sprite sheet for Don't Feed the Trolls Android/iOSInstead of 2048×1024, this is just 1024×1024, and most importantly, I have all my characters, the UI elements, and some background elements in the same, smallest texture!

Generic code

I did some code so that resource loading does not have to deal with packs or single sprites. That way, I can send a version without packs to the artist and he can test his ressource live. In cocos2d-x, this is very easy. You first need to load your pack(s) with CCSpriteFrameCache ::addSpriteFramesWithFile( file_name ). And then, read the ressource from the file if it’s not found in the packs. I did it like this:

CCSprite *GetSprite(const char *file_name )
{
 CCSprite *psprite = new CCSprite( );
 psprite->autorelease();
 // Search in the cache, first
 CCSpriteFrameCache *sfc = CCSpriteFrameCache::sharedSpriteFrameCache();
 CCSpriteFrame *psf = sfc->spriteFrameByName( file_name );
 if( psf != NULL )
 {
  psprite->initWithSpriteFrame( psf );
  return psprite;
 }
 CCLog("WARNING : %s not in a PACK!", file_name );
 psprite->initWithFile( file_name );
 return psprite;
 }
sprite->autorelease();
// quite ugly wait to skip dlg/img directory
if( file_name[3] == ‘/’ )
{
CCSpriteFrame *psf = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName( &file_name[4] );
if( psf != NULL )
{
psprite->initWithSpriteFrame( psf );
return psprite;
}
}
fgLog(”FROZAX : %s not in a PACK”, file_name );
psprite->initWithFile( file_name );
return psprite;

Conclusion

Packing your textures is very important on mobile platform, but hopefully, great tools make that task very easy and straighforward.

Do you pack your ressources? Do you do it by hand? Which tool do you use?

Follow me on twitterfacebook or google+ for more game development information.

Android Game Development : from Java to C++ (with cocos2d-x)

Saturday, November 12th, 2011

Introduction

In a previous post (here), I was talking about my progress with libgdx, a Java library for Android (and other platforms). Shortly after writing this article, I realized that there is a big disadvantage that I forgot to talk about. It’s so big that it made me stop using libgdx : It is not portable on iOS. I knew this from the beginning but didn’t really think about using anything else than Java. I finally realized that while porting from one language to another is easy, it can take a lot of time.

Cocos2d-x

I searched for multiplatform libraries (Android and iOS). As the game I’m porting (Don’t Feed the Trolls) was developed with XNA, I looked at C# solutions. There is at least one but it’s too expensive. I’ve been doing C++ indie/casual games in the past and I develop in C++ in my day job, so this is the obvious choice. I like the efficiency of languages such as C# or Java (easy to write and debug), but if I want to avoid porting the game another time for the iPhone, I should to use C++. There are quite some libraries in C++ (such as Marmalade). I finally decided to use cocos2d-x. This is a C++ port of the famous cocos2d library for iPhone which is in Objective C. Cocos2d-x has an active community, some multiplatform games have been released already, it’s free and open source. All good stuff!

C++ on Android

I am mostly working using the Windows build of the library but I also did some work on Android. Mixing C++ and Java (using JNI : Java Native Interface) is doable, but really not user friendly. Debugging is terrible, building is slow, you have to install tools such as cygwin, use makefiles (how old school!), and so on. It really does not seem the right solution at first. However, once everything is set up correctly, it’s working fine. Cocos2d-x has good tutorials about this. I develop with Visual C++ 2010 Express on the Windows build, I have all the great tools to debug generic problems. The only real troubles are when you have android-specific bugs in the C++ code but it’s really not frequent. And there are a few ways to debug it with gdb and gdb-server (I never had to use it yet). When you have a crash, there is a very useful tool in the NDK called addr2line (here’s how to use it) that allows you to get the callstack. It’s usually enough to understand and fix the bug. You also can still use old-school debugging techniques such as logging to the output ;) Hopefully, most of my bugs are multiplatform, or in Java code, so I can fix them easily.

Java is still needed

To develop Android-specific code, you still need Java. For example, I use Java for AdMob integration, In-App Purchases or the Facebook SDK for instance. Setting up Java functions called from C++ is not very intuitive, so I opted for a very simple and centralized way: I have one Java function that can be called from C++ with two String parameters. In the Java code, I read these parameters that contains all I need to know to call the specific Java code.

Conclusion

Even though libgdx is really a great lib, after a few weeks working on C++, I’m confident that I made the right choice with cocos2d-x. I did not start developing on iPhone already but it should be quite fast compared to porting Java to C++ (or worse, Objective-C!). I have a working Android version of my game and the performances seems good.

Which language do you use to build your multiplatform mobile games? Do you know other good C++ solutions? Feel free to comment!

Follow me on twitter, facebook or google+ for more game development information.

Android Game Development with libGDX

Tuesday, September 27th, 2011

androidAfter selling games on PC, Mac and Xbox 360, I want to develop games on mobile plaforms, and I will start with Android. I chose Android instead of iPhone for two reasons:

  • It’s cheaper: my Mac is a PowerPC and you need a Mac Intel for iPhone development. Also Android phones are cheaper than iPhones.
  • Java is similar to C# : I have C# games ready to be ported to mobile. As Android uses Java, it’s a great platform for me to port those games.

My last X360 game, Don’t Feed the Trolls is a great fit for mobile: quick gameplay sessions and not requiring too much processing power or memory. I therefore decided to port it to Android.

libgdxI started to look for available 2D game libraries on Android and after hesitating between AndEngine and libGDX, I chose libGDX. I will describe here some features and my thoughts about this library.

What I like

Complete API

It’s a simple but complete API. We often see libraries with only rendering support, but with libGDX, you can do rendering (2D and 3D), audio, file management and input (touchscreens). There are also a few useful utility classes and tools (more on this below).

Box2D

box2dThere is also a port of Box2D, the physics library used in Spring Up Harmony (PC, X360). If I ever want to port Spring Up Harmony to Android (probably), the physics part should be easily portable.

Open Source

I like to have access to the source code of libraries I use. I find it reassuring and when debugging, it’s good to be able to step into libraries source code.

Activity

activityThere is currently quite a lot of updates and bug fixes, by the creator of the lib (Mario Zechner) and by community.

Bitmap Fonts

font_small_cropThere is a tool available to create bitmap fonts. This is very similar to the tool I used on XNA (SpriteFont2 Texture Tool) so porting my existing code was very easy.

Desktop Version

If you ever used the Android Emulator of the SDK, you are probably aware that it’s terribly slow and not really usable. I didn’t buy my Android Device yet, but can still work on the game and test it properly because libgdx also compiles for desktop java.

Don't Feed the Trolls for Android running with the Desktop version in libGDX

Don't Feed the Trolls for Android running with the Desktop version of libGDX

Texture Packer

This is another great tool, used to pack many textures in one. I usually don’t care much about texture size and texture memory waste when developing on X360 but this is important on mobile devices due to their limitations. Some features of this tool:

  • Grouping small textures in textures pages (power of two).
  • Strip transparent pixels on the borders of textures. This required quite some tweaks and update in my own fgDrawSprite class and rendering functions to manage properly, but this is really a great way to save memory and disk space.
  • Has an incremental option to avoid generating everything when updating only some resources.
  • Can be called from the game itself in the desktop version. A good practice is to automatically call the packer in the desktop version, and use the generated assets in both Desktop and Android.

This is really a time saver tool.

What I don’t like

Lack of documentation

There is no good and centralized documentation. You need to look for information on the forums, in the source code and/or on blog articles. Due to the activity of the library, I sometimes find out that I’m using old stuff that is not supposed to be used, because it’s deprecated and has been replaced by something else. The parameters of some API functions are not always properly documented too. For instance, I had trouble using a rendering function and found out that the rotation parameter was an angle in degrees (it’s usually in radians in the libraries I used before).

Reverted Y-Axis

coordsI found this very strange but in all the 2D APIs I used, the coordinate system used the point (0,0) as the top-left corner, with X going right and Y going down. In libgdx, the Y axis is going up, and the 0,0 is bottom-left. I had to change some rendering functions to take this into account.

Android Specific

Doing Android specific code is not very clean because the lib is supposed to work on desktop and Android. I guess this is also because of Java, and I wished we could have some preprocessing to condition Android specific code. There are many workarounds, because the Android application overloads the Desktop application. So you can create empty methods on Desktop that are overloaded only in the Android project with Android specific code. I hope this won’t get too messy when I’ll work on very specific and touchy stuff such as in-app purchases.

What I don’t know

Performance

I don’t own an Android device yet and did not test other API, so I can’t really talk about the performance of the API. According to users, it is faster than most other APIs.

Conclusion

Using libGDX is a good and easy way to start developing Android games. For now, I’m happy with this library and you can see on the screenshot above that development is going well. I will probably release a few games with it.

If you tested different Android libs or have anything to add, feel free to comment about it.

You can find out more about Frozax Games or me on twitter, facebook or g+.

Useful C# and Visual Studio tips you might not know

Tuesday, May 31st, 2011

While working on my next game, I tried to keep notes of interesting tips I used. They are related to C# and Visual Studio.

Overriding ToString()

When debugging or prototyping, you often need to display complex objects on the screen on in the debugger output. A handy way to do this when dealing with complex classes is to override the ToString() member. Here is an example:

class ComplexClass
{
   int _number = 0;
   string _string = "My String";

   public ComplexClass( int n, string s )
   {
      _number = n;
      _string = s;
   }

   public override string ToString()
   {
      return String.Format( "{0} / {1}", _number, _string );
   }
}

ToString() is also used by the debugger in the Watch dialog.

?? operator

I discovered the ?? operator a few months ago. I don’t use it much but could be useful in some cases. It allows you to replace the following code:

if( a != null )
   b = a;
else
   b = c;

by

b = a ?? c;

New class template

When you create a new class (using the right-click on the project, Add, New Item…), the file created is not empty but already has a template and a few using statements. You can edit this template easily. For instance, I added a “using fg;” with my own game library to this template. The template is found in the Visual Studio directory: {Program Files}\Microsoft Visual Studio 10.0\Common7\IDE\VCSExpress\ItemTemplatesCache\1033\class.zip. There are templates for anything and you will probably want to edit a few of them.

new does not always allocates

In C#, even when using the new operator, you might not allocate memory. For instance, the following line:

Vector2 point = new Vector2( 10, 20 );

does not allocate memory, because Vector2 is not a class, but a structure. The rule is as simple as that: a class allocates memory (and returns a pointer) and a struct does not allocate memory. It’s simple, but often misunderstood, especially if you come from C++.

Add As Link source file

Recently, I re-used source files from a previous project for a new one. I used the Add Existing Item option but Visual C# creates a copy of the source file in the current project directory instead of referencing the old file. I want to reference the old file so that it can be modified in both projects. To avoid that, you must select the hidden Add As Link option, by clicking the small arrow next to the Add button of the dialog box.

add_as_link

Overloading the [] operator

I often have objects containing a list of items. For instance, in Spring Up Harmony, I have a Ball Manager used to manage and draw the balls. I found it very handy to overload the [] operator to access elements of the list inside the manager from the outside directly.

List<Ball> _balls = new List<Ball>();
public int Count { get { return _balls.Count; } }
public Ball this[int i] { get { return _balls[i]; } }

That’s it!

I hope you found some of the tips useful!

Feel free to share more tips in the comments!

Follow me on twitter or facebook to get notified of new posts.

How to recover a file in Google Chrome cache (gzipped or not)

Saturday, May 14th, 2011

Exceptionally, this article is slightly off-topic and will not be related to game development.

I wished I could find an article like this one a few hours earlier, therefore I’m writing it myself, hoping to help people fixing the same problem I had.

The context

Earlier today, I was logging onto my ftp to download the latest log of Spring Up Harmony hiscores history in order to gather up-to-date piracy statistics. As the log files can grow quite large, I regularly download it locally and remove the server copy. Then, I use all my local copies to generate new stats, similar to the one shown in my 96% Piracy blog article.

The mistake

I was probably not really focused, but instead of transferring from my site to my local computer, I transfered the other way round and lost all my logs of the last 4 days! Argh! I’m sure the next time I will examine the “Are you sure you want to overwrite this file?” popup carefully.

The failed strategies

Here is a list of actions I made trying to recover data:

  • As I looked at my stats log online a few hours earlier, I hoped that I kept a tab open in my browser but I didn’t.
  • I checked the automatic backup of my hosting provider, but the daily backup was made 20 hours ago. That’s already a few days recovered, but I hoped to recover more of it.
  • I looked into Chrome cache folder, only to find 285 Mb of strangely-named binary files. That will not get me anywhere.
  • I looked for a free app to access chrome cache but the only one I found only told me which binary file contained my log file (ChromeCacheView).

However, this last app gave me hope because it displayed information about the name and date of the file I was looking for. Only 3 hours from the mistake. Losing 3 hours of log would be acceptable.

The Solution

Looking on google, I found that Chrome has an interesting integrated cache viewer that could have helped me from the beginning. By typing about:cache in the address bar, you access a list of cached files. You can also type a direct url if you know the file in the following form: chrome://view-http-cache/http://example.com/file.htm. I thought I found the solution and quickly accessed my log file. However, Chrome does not simply give you a way to get the cached file but instead displays raw data with HTTP headers and data received from the server. For my file, it gave me something like that (click for full size):

chrome_cache

As you can see in the red circle, it’s pretty obvious that the binary data displayed below is gzip data, and not plain text sadly. However, the presentation in Chrome is not really handy to get the real binary data because it contains on the left the addresses and on the right the binary form. The useful part is the hexadecimal version on the middle.

An article on Alex Korn site gives a php script he used to extract the file content section of Chrome cache into a text file. It won’t be that simple in my case because my content is binary but it’s a good start. Alex Korn had his text file directly visible. The first time I ran this php script, I had errors extracting the gzip file (corrupted data). After a closer look it’s because of the reg exp used in the preg_match_all. Some data on the right side (binary) could match the reg exp and inject invalid bytes. I replaced the reg exp by using spaces (\s) instead of whitespaces (\b) and added code to directly decode the gzip data. This is the full script I used:

// cache.log is a copy of chrome cache page with only the file content section
$cacheString = file_get_contents("cache.log");
$matches = array();
preg_match_all('/\s[0-9a-f]{2}\s/', $cacheString, $matches);
$f = fopen("t.bin","wb");
foreach ($matches[0] as $match)
{
  fwrite($f,chr(hexdec($match)));
}
fclose($f);

ob_start();
readgzfile("t.bin");
$decoded_data=ob_get_clean();
echo $decoded_data;

And that did it, I finally recovered my file!

Conclusion

I know this article is really specific but as I said in the beggining, I really hope people looking for this information will find it here instead of spending as much time as I did figuring it out.

You can follow me on twitter or facebook, and feel free to comment this article here.