Showing posts with label tutorial. Show all posts
Showing posts with label tutorial. Show all posts

Saturday, 19 April 2014

LibGdx Google Mobile Ads SDK Tutorial

The number one ad service being used by Android and LibGdx developers at the moment is Google AdMob.

If you've not updated your app recently you should consider doing so soon. Google says:

Android (6.4.1 and earlier SDKs)
Deprecated. On August 1, 2014, Google Play will stop accepting new or updated apps that use the old standalone Google Mobile Ads SDK v6.4.1 or lower. You must upgrade to the Google Play version of the Mobile Ads SDK by then.

Ok, so we want to migrate to the new Google Play Services way of doing things - this blog post walks you through the process :)

Install this apk to see what we'll be building!

----------

Barebones Sample App

First thing I did was grab an up to date version of libgdx. They are now up to 0.9.9 stable, I'm sure there is a lot of awesome new stuff in there for me to investigate, but TheInvaderOne isn't really leaving me with a lot of time for Android these days so that'll have to wait!

Next I created a new libgdx project using gdx-setup-ui.jar (see this old post for a walkthrough), added a .gitignore file, and made my initial commit.


Eclipse Setup

In eclipse, import the barebones sample app (file > import > existing projects into workspace) - you should now have at least three projects in package explorer (core, android, and desktop).

Open the Android SDK Manager, download the latest SDK Platform and Google APIs (at time of writing: 4.4.2/API19), the 2.3.1/API9 SDK Platform, and from Extras - Google Play Services.

Locate the <android-sdk>/extras/google/google_play_services/libproject/google-play-services_lib/ directory on your machine (on my windows machine - C:\Program Files (x86)\Android\android-sdk\extras\google\google_play_services\libproject\google-play-services_lib) and copy into your working directory alongside the existing libgdx projects.

File > Import > Android > Existing Android Code, Next, Browse, navigate to the local copy of google-play-services_lib in your working directory, Ok, Finish.

Right-click your android project, select Properties, Android, scroll down and click Add, select the google-play-services_lib project, Ok.

A refresh and clean in eclipse probably wouldn't hurt at this point, so go ahead and do that.


AndroidManifest.xml

Ensure that the target in android project's project.properties file is at least 13, and the android:minSdkVersion in your AndroidManifest.xml is at least 9. Sadly this does mean users running ancient versions of Android will be excluded, but there's nothing we can do about this. There are very very VERY few devices still running versions below 2.3/API9, so at least you won't be excluding many users...

Add these two lines as children of the 'application' element:
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/><activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>

Add these two permissions as children of the 'manifest' element:
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Save changes, then refresh and clean in eclipse for good luck...


Banner Ad

See this version of the android project's MainActivity class for a reasonably straightforward banner ad implementation.


Interstitial Ad

This diff shows an interstitial ad implementation (ActionResolver interface lets us trigger interstitial actions from the core project while retaining the invaluable LibGdx cross-platform functionality).

----------

That's all there is to it!

As always, please feel free to leave comments below. I can't really offer support - TheInvaderOne and "Real Life Day Job" leave me very little free time these days, but other visitors will often leave helpful solutions, and if I find a spare moment every now and then I do try to answer any unresolved queries.

Anyway, I hope you have fun making your games - be sure to leave a note here if you release something on google play or the amazon market, I'm always happy to check out new games :)

PS - one final note if cloning from https://github.com/TheInvader360/tutorial-libgdx-google-ads, pay attention to the problems view in eclipse! You will need to create an empty 'gen' directory in both the google-play-services_lib and tutorial-libgdx-google-ads-android projects, and ensure you have the required android sdks installed. As is often the case with eclipse, a liberal amount of refreshing and cleaning will do no harm...

Saturday, 19 October 2013

LibGDX Google Play Game Services Tutorial


Google Play Game Services offers cross platform social leaderboards, achievements, and much more (realtime multiplayer, cloud saves, anti-piracy...). I've started implementing google play game services leaderboards and achievements in my LibGDX Android Games, and the purpose of this blog article is to walk through the process so you can do the same!

  • I've published an example project on Google Play check it out!
  • The example project is freely available on GitHub check that out too!
  • You can also get the complete (free) version of Super Jump a Doodle here!

Continue reading after the jump to find out how to add these features to your own games!


Sunday, 26 May 2013

Street Race Swipe LibGDX Scene2D Tutorial



I have been meaning to write a LibGDX Scene2D tutorial for some time now (ever since my Quack Attack FREE Duck Hunt Game got ridiculously popular). The problem has been finding the time, instead of writing blog entries I've been making games!

I had a great idea for a multitasking game, play four independent games at one time to train your brain and test your ability to multitask. The result was my 4 Games 1 Screen FREE Brain Training Game. I built this game as four separate games from the outset, with the intention of possibly building further on each minigame and releasing as standalone apps. The first of these standalone apps is Street Race Swipe Racing Game, which brings us neatly to the point of this article...


Street Race Swipe Racing Game is such a simple game at its heart that it seems like an excellent candidate for a tutorial article :) I remember being massively impressed by the example SimpleApp on the LibGDX wiki when first starting out, there was so little to it but it touched on all the basics of what is needed to make a game. I'm hoping this mini project will be almost as simple and just as helpful to others!

Tuesday, 31 July 2012

Pulling the level generation code into Run Bobo Run



I didn’t expect to be posting again for a few days, but it turns out smooshing the procedural level generation algorithm into the LibGDX project was really straightforward, so I figured I might as well post a little something about it today :)
I added the Level class that I posted previously, and just made a few little changes to it:
  1. I changed char[][] to int[][], no real reason for this, either would be fine
  2. I pulled in Bobo and Array<Block> from GameScreen
  3. I replaced the console print method with a method to translate levelLayout to blocks placed in the level
  4. Finally, a constructor pulls all this together to allow easy creation of a level with a Bobo in it
I could have included block creation in the generateLayout method (under the “levelLayout[row][col] = ’0′;” line) and left out the translateLayout method completely, but separating out layout generation and translation to world co-ordinates seemed like a good idea.
Here’s the full source for Level.java
 package com.mrdt.runboborun;  
 import java.util.Random;  
 import com.badlogic.gdx.math.Vector2;  
 import com.badlogic.gdx.utils.Array;  
 public class Level {  
  private Bobo bobo;  
  private Array blocks;  
  private Random randomGenerator = new Random();  
  private int levelHeight, levelWidth, pathWidth, pathOffset;  
  private int[][] levelLayout;  
  public Level(int levelHeight, int levelWidth, int pathWidth, int pathOffset) {  
  blocks = new Array();  
  generateLayout(levelHeight, levelWidth, pathWidth, pathOffset);  
  translateLayout();  
  bobo = new Bobo(new Vector2((GameScreen.WIDTH/2)-(Bobo.WIDTH/2), 0));  
  }  
  private void generateLayout(int levelHeight, int levelWidth, int pathWidth, int pathOffset) {  
  this.levelHeight = levelHeight;  
  this.levelWidth = levelWidth;  
  this.pathWidth = pathWidth;  
  this.pathOffset = pathOffset;  
  this.levelLayout = new int[levelHeight][levelWidth];  
  for (int row=0; row<levelLayout.length; row++) {  
   for (int col=0; col<levelLayout[row].length; col++) {  
   if ((col < pathOffset) || (col >= pathOffset+pathWidth))  
    levelLayout[row][col] = '0';  
   }  
   int stepModifier = (randomGenerator.nextInt(3)) - 1;  
   if ((pathOffset + stepModifier >= 0) && (pathOffset + stepModifier + pathWidth <= levelWidth))  
   pathOffset = pathOffset + stepModifier;  
  }  
  }  
  private void translateLayout() {  
  for (int row=0; row<levelLayout.length; row++) {  
   for (int col=0; col<levelLayout[row].length; col++) {  
   if (levelLayout[row][col] == '0') {  
    Block block = new Block(new Vector2(col*Block.WIDTH, -row*Block.HEIGHT));  
    blocks.add(block);  
   }  
   }  
  }  
  }  
  public Bobo getBobo() {  
  return bobo;  
  }  
  public Array getBlocks() {  
  return blocks;  
  }  
 }  

As a result of introducing the Level class, the GameScreen class needed a little tidying up.

Project is up on github, feel free to check the project out, have a play with it, and comment if you have any ideas or suggestions :)


          

Monday, 30 July 2012

Getting Started with LibGDX


Exciting times… By the end of this post we’ll have something that loosely resembles the beginnings of a game! Not only that, we’ll be able to run it on the desktop or if we like on android (either a real phone or the emulator).
It really will be just the beginning though… Today’s focus is on creating a game world comprised of block objects, adding a player controlled object (Bobo) to the world, and locking the camera onto Bobo such that the level ‘scrolls’ and Bobo always remains within sight. Later we’ll deal with collision detection, game winning states, scoring, etc, but for now let’s just take it one step at a time!

Getting Started with LibGDX

I’ll assume you already have your environment set-up. If not, follow the instructions here, and come back when you’re done :)
Ok, now generate a new shell libgdx project using the gdx-setup-ui.jar. These are the values I used:


Next, fire up eclipse, file > import, general > existing projects into workspace, set root dir to wherever you specified when creating the shell project (in my case D:\Workspace), make sure all three projects are ticked, then click finish. If it all went well you should see the three projects in project explorer. Right click the desktop project, opt to run as java application, click on the Main item in the dialog, then ok. The default hello world app should open, it looks a bit like this:


Assets

I created a couple of sprites to get us started, bobo.png and block.png (both 16x32px per original spec). These should be placed in the assets/data dir of the android project. While you’re at it, delete libgdx.png, you won’t be needing it again.

Manifest

Open AndroidManifest.xml (it should be in the root of the android project). For now, all we need to do here is change the android:screenOrientation value from “landscape” to “portrait”.

Bootstrap

I renamed MainActivity.java (android project src) AndroidStarter.java, and Main.java (desktop project src) DesktopStarter.java. Just personal preference thing. Nothing needs changing in the android starter, but in the desktop starter we should set cfg.width to 240, and cfg.height should remain as 320, this just means the app we preview on the desktop will default to the target resolution of 240×320.

Getting down to business

With the initial setup out of the way, we can now get on with the business of making our game.
We’re only implementing the GameScreen right now, but we’re aware that there will be more screens added later on, so we should probably plan for that from the outset. There’s a nice little article here on the subject, makes a lot of sense to me so let’s do it!
Open RunBoboRun.java, delete all the contents, and replace with the following:

 // In anticipation of further screens being added, I followed this suggestion:  
 // http://code.google.com/p/libgdx-users/wiki/ScreenAndGameClasses  
 package com.mrdt.runboborun;  
 import com.badlogic.gdx.Game;  
 public class RunBoboRun extends Game {  
     GameScreen gameScreen;  
     @Override  
     public void create() {  
         gameScreen = new GameScreen(this);  
         setScreen(gameScreen);  
     }  
 }  


The libgdx-users wiki article does a great job of explaining so I won’t bother going into it any further here.

Game Objects

There are a couple of very obvious game object candidates – the world is made up of Blocks, and Bobo moves around the world, let’s create a class for each…

 // A simple class for Block objects  
 package com.mrdt.runboborun;  
 import com.badlogic.gdx.math.Vector2;  
 public class Block {  
     public static final int WIDTH = 16;  
     public static final int HEIGHT = 32;  
     private Vector2 position = new Vector2();  
     public Block(Vector2 position) {  
         this.position = position;  
     }  
     public Vector2 getPosition() {  
         return position;  
     }  
 }  

There’s not a whole lot to the Block class. A couple of constants define the size (measured in pixels), a Vector2 is used to record its position in the world (set during construction), and there’s a position getter/accessor method. That’s all there is too it.

 // A simple class for Bobo, all straightforward apart from maybe update method.  
 // From obviam.net:  
 // We simply add the distance travelled in delta seconds to Bob’s current position.  
 // We use velocity.tmp() because the tmp() creates a new object with the same value  
 // as velocity and we multiply that object’s value with the elapsed time delta.  
 package com.mrdt.runboborun;  
 import com.badlogic.gdx.math.Vector2;  
 public class Bobo {  
     public static final int WIDTH = 16;  
     public static final int HEIGHT = 32;  
     private Vector2 position = new Vector2();  
     private Vector2 velocity = new Vector2();  
     public Bobo(Vector2 position) {  
         this.position = position;  
     }  
     public void update(float delta) {  
         position.add(velocity.tmp().mul(delta));  
     }  
     public Vector2 getPosition() {  
         return position;  
     }  
     public void setVelocity(Vector2 velocity) {  
         this.velocity = velocity;  
     }  
 }  


There isn’t much more to the Bobo class. In fact, looking at the two classes I think maybe there should be a parent Tile object that Block and Bobo extend, but let’s forget about that for now, we can always come back to this later if we like. So what is different about the Bobo class? Put simply, it’s capable of movement. Bobo has a velocity (a Vector2), the value of which is set via a setter/mutator method. On each update Bobo’s position is altered in accordance with his velocity. I pinched the update method from obviam.net, he explains it as follows – “We simply add the distance travelled in delta seconds to Bob’s current position. We use velocity.tmp() because the tmp() creates a new object with the same value as velocity and we multiply that object’s value with the elapsed time delta.”
So far so good. Time to implement the GameScreen!

GameScreen

I’ve said this many times already, but I’ll say it again… I’m learning as I go, and I may not be doing things the “right” way. This class should probably be split into smaller pieces, maybe I should have distinct renderer and controller classes, etc. For now I’m just working on making things work, I can worry about doing things the “right” way later on. When you’re making a game who cares if you did it the “right” way anyway, it just needs to work! With that out of the way, let’s have a look at the code:

 // This basic GameScreen class demonstrates:  
 //  How to create a game level comprised of multiple block objects  
 //  How to create a dynamic bobo object that moves around the level in response to user input  
 //  How to create a 2D camera that follows bobo on the y-axis  
 package com.mrdt.runboborun;  
 import com.badlogic.gdx.Gdx;  
 import com.badlogic.gdx.Input;  
 import com.badlogic.gdx.Screen;  
 import com.badlogic.gdx.graphics.GL10;  
 import com.badlogic.gdx.graphics.Texture;  
 import com.badlogic.gdx.graphics.g2d.SpriteBatch;  
 import com.badlogic.gdx.graphics.OrthographicCamera;  
 import com.badlogic.gdx.math.Vector2;  
 import com.badlogic.gdx.utils.Array;  
 public class GameScreen implements Screen {  
     private static final int WIDTH = 240;  
     private static final int HEIGHT = 320;  
     private RunBoboRun game;  
   private Bobo bobo;  
   private Array<Block> blocks;  
   private OrthographicCamera cam;  
   private Texture boboTexture;  
   private Texture blockTexture;  
     private SpriteBatch spriteBatch;  
     public GameScreen(RunBoboRun game) {  
         this.game = game;  
         boboTexture = new Texture(Gdx.files.internal("data/bobo.png"));  
         blockTexture = new Texture(Gdx.files.internal("data/block.png"));  
         createLevel();  
         // orthographic camera (2D camera) of fixed width and height, larger screens will scale to fit  
         cam = new OrthographicCamera(WIDTH, HEIGHT);  
         // camera focus: x-axis middle of level, y-axis 100px below bobo, z-axis ignored  
         cam.position.set(WIDTH/2, bobo.getPosition().y - 100, 0);  
       spriteBatch = new SpriteBatch();  
   }  
     private void createLevel() {  
         // create bobo and add him to the level  
         bobo = new Bobo(new Vector2((WIDTH/2)-(Bobo.WIDTH/2), 0));  
         // create an array to hold all the block objects  
         blocks = new Array<Block>();  
         // nasty temp cludge to blat out a bunch of blocks... will be replaced by level generation algorithm soon!  
         addBlock(new Vector2(0, 32));  
         addBlock(new Vector2(16, 32));  
         // -- add lots more blocks here if you like...  
         addBlock(new Vector2(224, -448));  
     }  
     private void addBlock(Vector2 position){  
         Block block = new Block(position);  
         blocks.add(block);  
     }  
   @Override  
     public void render(float delta) {  
         handleInput();  
         // user input has an impact on bobo, so update his state  
           bobo.update(delta);  
           // following bobo update, move camera accordingly (focus rule same as in constructor)  
         cam.position.set(WIDTH/2, bobo.getPosition().y - 100, 0);  
         // clear screen  
           Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);  
           // call cam.update() after changes to cam (http://code.google.com/p/libgdx/wiki/OrthographicCamera)  
           cam.update();  
           // set projection and model-view matrix after update (http://code.google.com/p/libgdx/wiki/OrthographicCamera)  
           cam.apply(Gdx.gl10);  
           // setProjectionMatrix before drawing sprites (http://code.google.com/p/libgdx-users/wiki/Sprites)  
           spriteBatch.setProjectionMatrix(cam.combined);  
     spriteBatch.begin();  
       for(Block block: blocks) {  
           spriteBatch.draw(blockTexture, block.getPosition().x, block.getPosition().y, Block.WIDTH, Block.HEIGHT);  
       }  
         spriteBatch.draw(boboTexture, bobo.getPosition().x, bobo.getPosition().y, Bobo.WIDTH, Bobo.HEIGHT);  
         spriteBatch.end();       
     }  
     private void handleInput() {  
         // if a valid keypress, respond accordingly (set bobo's velocity such that he moves in that direction)  
     if(Gdx.input.isKeyPressed(Input.Keys.DOWN)) {  
         bobo.setVelocity(new Vector2(0, -100));  
     }  
     if(Gdx.input.isKeyPressed(Input.Keys.UP)) {  
             bobo.setVelocity(new Vector2(0, 100));  
     }  
     if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) {  
         bobo.setVelocity(new Vector2(-100, 0));  
     }  
     if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {  
             bobo.setVelocity(new Vector2(100, 0));  
     }  
         // if no valid keypress, respond accordingly (set bobo's velocity such that he does not move)  
     if   
     (!(Gdx.input.isKeyPressed(Input.Keys.UP))&&!(Gdx.input.isKeyPressed(Input.Keys.DOWN))&&!(Gdx.input.isKeyPressed(Input.Keys.LEFT))&&!(Gdx.input.isKeyPressed(Input.Keys.RIGHT)))  
     {  
         bobo.setVelocity(new Vector2(0, 0));  
     }  
   }  
   @Override  
   public void resize(int width, int height) {  
     }  
     @Override  
     public void show() {  
     }  
     @Override  
     public void hide() {  
     }  
     @Override  
     public void pause() {  
     }  
     @Override  
     public void resume() {  
     }  
     @Override  
     public void dispose() {  
     }  
 }  


I think the code and comments (don’t miss the links in the comments!) should make sense without too much further explanation.
On entry we:
  1. Create our assets (in this case our two textures)
  2. Create a level comprised of an array of Blocks and a Bobo
  3. Create a camera focused on Bobo
  4. Create a spritebatch to allow drawing of sprites to screen
The render method can be thought of as the main game loop, it’s called repeatedly while the GameScreen is active. Here’s what we need to do every time render is called:
  1. Handle user input – if a valid key is pressed (or not), set Bobo’s velocity accordingly
  2. Update Bobo
  3. Update camera position (lock on to Bobo)
  4. Draw the sprites to screen
That’s basically it :)
The controls are more than a little bit dodgy (no diagonal movement, and you’re stuffed if your phone has no cursor keys), the ‘level’ is hardcoded, the assets aren’t disposed cleanly on close, and there’s no doubt a lot more that needs tidying up, but this post is getting a bit long so I’m going to leave it there for now. When all is said and done, we have an application that will run on the desktop and on android, and the camera follows Bobo around the world, that’s exactly what I hoped to achieve today, so this seems like a good place to stop.
Here’s a screenshot of the ‘game’ as it stands:


Next post I’ll probably look into pulling in the level generation algorithm, and maybe do some collision detection, or maybe investigate accelerometer controls, I don’t really know yet!


          

Saturday, 28 July 2012

Procedural Level Generation


I’ve written a little example program to illustrate the level generation algorithm that I’ll be using in “Run Bobo Run”.
The Game class is the main entry point, it simply creates an instance of Level, calls the generateLevel method (supplying relevant parameters), then calls printLevel (which outputs a representation of the level to standard out).
Here’s the sourcecode:
 public class Game {  
  public static void main(String args[]) {  
  Level level = new Level();  
  level.generateLevel(45,15,5,5);  
  level.printLevel();  
  }  
 }  
The Level class is where the level generation algorithm lives. Let’s think about what we need it to do:
  1. Create a 2D level comprised of a set amount of tiled rows and columns
  2. Create a path of a certain width that runs down the level
  3. Potentially shift the path one tile left or right on each consecutive row that is created (randomising means unique levels on repeated playthroughs)
  4. Ensure the path never strays outside the world bounds
Here’s the sourcecode:
 /********************************************************************************************  
 * RANDOM LEVEL GENERATOR  
 *  
 * This algorithm procedurally generates levels for use in simple 2D games where the object  
 * is to remain on the path and avoid crossing any blocked tiles.  
 ********************************************************************************************/  
 import java.util.Random;  
 public class Level {  
     int levelHeight; // Height of the level measured in tiles  
     int levelWidth; // Width of the level measured in tiles  
     int pathWidth; // Width of the path measured in tiles  
     int pathOffset; // Number of tiles to the left of the path  
     char[][] level; // Two dimensional array representing the level  
     Random randomGenerator = new Random();  
     public void generateLevel(int levelHeight, int levelWidth, int pathWidth, int pathOffset) {  
         this.levelHeight = levelHeight;  
         this.levelWidth = levelWidth;  
         this.pathWidth = pathWidth;  
         this.pathOffset = pathOffset;  
         this.level = new char[levelHeight][levelWidth];  
         for (int row=0; row<level.length; row++) { // for each row in the level  
             for (int col=0; col<level[row].length; col++) { // for each element in the row  
                 // set value based on elements location in the array  
                 if ((col < pathOffset) || (col >= pathOffset+pathWidth))  
                     level[row][col] = 'X'; // this tile is not on the path  
                 else  
                     level[row][col] = ' '; // this tile is on the path  
             }  
             // generate a random integer (-1 or 0 or +1)  
             int stepModifier = (randomGenerator.nextInt(3)) - 1;  
             // apply modifier to path offset provided the path would remain within world bounds  
             if ((pathOffset + stepModifier >= 0) && (pathOffset + stepModifier + pathWidth <= levelWidth))  
                 pathOffset = pathOffset + stepModifier;  
         }  
     }  
     public void printLevel() {      
         for (int row=0; row<level.length; row++) {  
             System.out.print("|");  
             for (int col=0; col<level[row].length; col++) {  
                 System.out.print(level[row][col]);  
             }  
             System.out.println("|");  
         }  
     }  
 }  
A two dimensional array is the perfect data structure for a 2D tiled level. In this toy example it’s an array of char’s (so I can output a human readable representation to console), in the real game it’ll be an array of Tile objects.
I use nested iterators to touch every element in the array. In English-ish - “For each row in the Level do {for each column in the current row do {depending on what column you’ve reached, set the value to something or other}}”.
How do we decide between setting the value to ‘something’ or ‘other’? This condition should shed a little light “if ((col < pathOffset) || (col >= pathOffset+pathWidth))”. If we have not yet reached the column that that marks the start of the path, or we have reached/passed the column that is the end of the path, we should set the current element to blocked. If the evaluation of the condition returns false, set the current element to be part of the path.
Finally, how do we introduce the random change in path offset per row? First, we generate a random integer between -1 and 1, “(randomGenerator.nextInt(3)) – 1″. Next, we check to see if applying this randomly generated modifier to the current path offset would result in the whole path remaining within the world bounds, “if ((pathOffset + stepModifier >= 0) && (pathOffset + stepModifier + pathWidth <= levelWidth))”. If the condition returns true, we apply the modifier, but otherwise we do nothing.
I think that about covers it. Next time I’ll likely be looking at how to move a sprite around the game world, and forcing the camera viewport to follow it. For now I’ll leave you with a super exciting screenshot of a procedurally generated level output to the console:


          

Friday, 27 July 2012

First android game - project outline


Time for a new project, you’re welcome to join me on the journey!

Step one, outline what you want to achieve…

  1. Game procedurally creates its own levels
  2. The project should be good tutorial fodder
  3. Game should be fun to play
  4. Game should be complete enough to be deployed to market
  5. Keep it simple, stupid!
That’s in order of importance for this project. Usually ‘fun to play’ would be number one, but what I really want to achieve with this project is first and foremost a bit of learning of my own, and secondly I’d like to turn it into a tutorial that might be of interest to other people just getting started with android game development.
Here’s a basic game idea that should do the job nicely…

Run Bobo Run!

Bobo is running along the path, he’s training hard to become the fastest clown in the world! Can you help him stay on the path and beat the level record? Try to avoid the walls, bumping into them slows Bobo down!
  • 2D game
  • Camera viewport locked onto Bobo
  • Tilting the device left/right moves Bobo in that direction
  • Procedurally generated level consists of a ‘path’ surrounded by wall ‘blocks’
  • Level fits the screen horizontally, and scrolls vertically
  • Bobo moves down the level automatically
  • Bobo cannot leave the path and colliding with wall blocks slows him down
  • Aim of the game is to get to end of level as quickly as possible, beat the level record!
  • The closest you get to ‘losing’ this game is finishing in a bad time – ideal for small children
This game could be extended to include multiple levels (vary level length, path width, Bobo speed), bonus pickups, speed boosts, new speed record facebook bragging, level grades (e.g. one star for sub 40 seconds, two stars for sub 35 seconds, three stars for sub 30 seconds, platinum cup for perfect level – sub 30 seconds, no wall collisions, all bonus pickups collected), a level select screen for direct access to previously unlocked levels, particle effects on collision with blocks, 3D graphics, story mode, character select… But honestly, it’s all getting a bit silly. We just want a very simple casual game for people to play when they’re bored (or to keep children amused for a little while), and one of the project tenets is to Keep it simple, stupid! We can always come back to some of these ideas later if we want, but for now let’s just make a working game!

What screens will the game need?

I figure a screen each for Menu, Game, Results, Best Time, Instructions, and About.

All screens transitions (bar one) will be as a result of UI button events. The transition from Game screen to Results screen is to be triggered when the level end is reached in the game. I know the transitions could be improved, maybe add a ‘Retry’ button to the Results screen, introduce a pause screen, a level select screen, etc. But I’m keeping things simple to start with.
To start with I’ll just focus on the Game screen, that’s where the real meat of the project lies.

What devices will the game run on?

This game is so simple that it should run on pretty much any Android device. I’ve decided to aim for global compatibility.
The smallest android phone resolution that I’m aware of is 240×320 (HTC Wildfire and HTC Tattoo), so let’s target that resolution. Higher resolution screens will simply scale to fit (the game won’t be Nexus 7 eye candy, but it should run all the same).
OpenGL ES 1.0 and 1.1 API spec have been supported since Android 1.0, OpenGL ES 2.0 since Android 2.2. Over 90% of devices support OpenGL 2.0 (http://developer.android.com/about/dashboards/index.html), and that percentage will keep on increasing, but what about the 10% with older devices, don’t they deserve to play this game too? Of course they do! I’ll target OpenGL 1.1.
I’m not aware of any Android devices (phones or tablets at least) that don’t at least have an accelerometer (tilt sensor) and touch screen support. I’ll avoid supporting more exotic inputs, a simple control scheme of touch for menu options and tilt for gameplay is plenty for this game. Note that for the purpose of being able to test on my dev laptop (much quicker than using the emulator or deploying apk’s to device) I’ll also include keyboard and mouse support.

Game Screen Mockup

Here’s a first stab at an example game screen:


  • 240x320px viewport displaying some of the level
  • Level is made up of 16x32px rectangular tiles
  • Tiles are either ‘path’ (beige) or ‘block’ (orange)
  • Bobo the clown is on the path (his sprite is also 16x32px)
  • Basic HUD displays progress percentage and current time
It’s not the most exciting looking thing we’ve ever seen, but it should be a good little project to work on nonetheless.
In the next post I’ll probably cover the procedural level generation algorithm, and maybe more if there’s time… See you then!