201
Android Game Development Tutorials Published on June 15, 2011 | 171,043 views | Filed in: Android Games Tags: featured Some months ago we received an email from a fellow Java developer, Tamas Jano, asking to be part of our JCG partners program. To our surprise he maintains a blog named “Against The Grain” debating about game development for the Android platform. I have been reading all of his articles since then and I must admit that his writings have been an inspiration and a motivation for me and my colleagues here at Java Code Geeks so as to start developing our first game for the Android platform. With this post I would like to present Tamas‘s work to our community hoping that you will be inspired and motivated just like we did! What follows is a portion of Tamas‘s introductory article titled as “A little motivation and what’s the idea behind all this.” I am certain that after reading it you will realize (just like I did) that you have many many things in common with this guy! First of all I know no great coder who is not interested in games. Some love slow paced ones while outdoorsy geeks (yes they do exist) will have a go with any type that requires all those reflexes some just won’t develop. At some point in their lives they might have wondered how the hell is this done? Wouldn’t it be cool to make such a thing? I’d love to do that. And so they went, getting into computing fueled by a passion for creating worlds they own and command. Back in the days you would see these guys at the arcades, hanging around computer labs and dreaming of owning one of those magnificent machines they can create their universe on. I’m talking about the 80s. Many took the classes, went through all that necessary crap that comes with getting a degree one would not care about in the future and here they are. Some graduated and have decent paying “software engineer” positions working for a multinational corporation doing who knows what. But a percentage of these so called engineers dream of games. They own the latest gadgets but they do not have the one thing that would enable them to make games: Time. Working 9-5 sucks and many have families or other obligations but they still think of doing projects on the side. Unfortunately many never even get started. How many thought: man…I’ll be building the greatest game of all, I’ll be rich and famous. Then they meet someone, have to get a job to pay for “settling” down and pay the bills for a place where they go in the evenings to crash just to start it over the next day. All this by doing boring web stuff or working on a small part of a monstrous multi-threaded distributed enterprise application architected by an inexperienced halfwit architect wannabe who got the job by sticking with the company since he was an intern. Where is the game you dreamed of doing 10 years ago? To be precise I am in a similar situation and while I had a short gig with a game company I am well in the rat race leading nowhere. I have decided to try one more time and I will give it a go.

Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Android Game Development TutorialsPublished on June 15, 2011 | 171,043 views | Filed in: Android Games Tags: featured

Some months ago we received an email from a fellow Java developer, Tamas Jano, asking to be part of our JCG partners program. To our surprise he maintains a blog named “Against The Grain” debating about game development for the Android platform. I have been reading all of hisarticles since then and I must admit that his writings have been an inspiration and a motivation for me and my colleagues here at Java Code Geeks so as to start developing our first game for the Android platform.

With this post I would like to present Tamas‘s work to our community hoping that you will be inspired and motivated just like we did!

What follows is a portion of Tamas‘s introductory article titled as “A little motivation and what’s the idea behind all this.” I am certain that after reading it you will realize (just like I did) that you have many many things in common with this guy!

First of all I know no great coder who is not interested in games. Some love slow paced ones while outdoorsy geeks (yes they do exist) will have a go with any type that requires all those reflexes some just won’t develop. At some point in their lives they might have wondered how thehell is this done? Wouldn’t it be cool to make such a thing? I’d love to do that.

And so they went, getting into computing fueled by a passion for creating worlds they own and command. Back in the days you would see these guys at the arcades, hanging around computer labs and dreaming of owning one of those magnificent machines they can create their universe on. I’m talking about the 80s.

Many took the classes, went through all that necessary crap that comes with getting a degree one would not care about in the future and here they are. Some graduated and have decent paying “software engineer” positions working for a multinational corporation doing who knows what. But a percentage of these so called engineers dream of games. They own the latest gadgets but they do not have the one thing that would enable them to make games: Time. Working 9-5 sucks and many have families or other obligations but they still think of doing projects on the side. Unfortunately many never even get started.

How many thought: man…I’ll be building the greatest game of all, I’ll be rich and famous. Then they meet someone, have to get a job to pay for “settling” down and pay the bills for a place where they go in the evenings to crash just to start it over the next day. All this by doing boring web stuff or working on a small part of a monstrous multi-threaded distributed enterprise application architected by an inexperienced halfwit architect wannabe who got the job by sticking with the company since he was an intern.

Where is the game you dreamed of doing 10 years ago?

To be precise I am in a similar situation and while I had a short gig with a game company I am well in the rat race leading nowhere. I have decided to try one more time and I will give it a go.

Page 2: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Why? Just for the hell of it, to demonstrate that games are simple to build and you can sit at your computer and have some fun too. Actually this is why I ended up a coder, to make games not to configure some frameworks (yes, that is not programming, it is mostly configuration).

Well was I right? I hope I was!

As I told you before Java Code Geeks have been busy enough developing our first game for the Android platform. A new category named “Android Games” has been created in order to contain all game related articles from now on.

Here is the list of all Android Game Development tutorials (up until now) for your reference:

1. The Game Idea

2. Create the Project

3. A Basic Game Architecture

4. A Basic Game Loop

5. Displaying Images

6. Moving Images

7. The Game Loop

8. Measuring FPS

9. Sprite Animation

10. Particle Explosion

11. Design In-game Entities – The Strategy Pattern

12. Using Bitmap Fonts

13. Switching from Canvas to OpenGL ES

14. Displaying Graphical Elements (Primitives) with OpenGL ES

15. OpenGL Texture Mapping

16. Design In-game Entities – The State Pattern

17. Building Games Using the MVC Pattern – Tutorial and Introduction

Page 3: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

18. Android Game Development with libgdx – Prototype in a day, Part 1a

19. Android Game Development with libgdx – Prototype in a day, Part 1b

20. Android Game Postmortem – ArkDroid Development

Last but not least we have established a new division, JCG Studios (Just Cool Games Studios) where all our games will be presented and promoted.

Android Game Development – The Game IdeaPublished on July 2, 2011 | 60,489 views | Filed in: Android Games

Coming up with an idea for the game

This is the hardest part. Because I am just one guy having limited time I will choose one idea thatis realisable in a short time and will contain all elements of an action game.

So I came up with a story for the game. The story goes like this:

The end is nigh! Evil robots from outer space have set up factories on the moon and are sending their ever increasing waves of machines to destroy humanity. For what reason? Beats me but they have laser cannons, missiles, brain washing weapons and a lot of other harmful stuff.Every man for himself! How long before the end? How long can one survive or maybe defeat themachines by reaching the moon base and annihilate the super brain?That should be enough. Now let’s design something around this story.Checking the Android specs we see that we have limited memory and 480×800 pixels to play with. The first game that comes to my mind is robotron. Waves of robots, missiles from everywhere and 2 joysticks. A perfect setup for a handheld device held horizontally.One thumb for directions and the other one for shooting the baddies in every direction. A classic shoot’em up.Let’s go retro. Pixelated graphics is cool and the art is in the effects. Will try to do that.

Let’s design!

Page 4: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

We have one guy. He’s got 3 lives and a gun. He’ll be dropped in the middle of a room and some baddies are trying to kill him already.We have the basic information to sketch out our game structure.But, we don’t have a name. Let’s see, droids taking over the planet…checked google for “droidz” and “droidz game” guess what? No droidz game found. I will name this: “droidz”.I find it a cool name for the first game using android.

Above you have a rough mock-up of what the game will look and feel like. The 2 grey circles arethe controllers. Imagine the device being held horizontally and you have your thumbs on the circles. Your left thumb will move our hero while the right thumb will fire the weapon. The direction is being controlled by the position of your thumb relative to the circle’s centre.

Now that we have the idea let’s identify what we need to get the game done.

We need the game objects. Currently there are 2 types of actors in this. Our guy and the droids.

To control our guy we need to receive user input. The user input will be the touch screen. To be more precise the 2 circles defined on the screen. One controls the guy’s position and the other hisweapon.

A typical game architecture looks like this:

1. Process input

2. Update state of game objects. This means calculate new positions for every item, check game logic, collisions etc

3. Produce sounds

4. Render state to screen

5. If game is not over repeat from step 1

For example: Our guy is in the middle. Droids move every 1/10 of the second towards him. Every tenth of a second we check if the screen was touched and if it was touched we move our

Page 5: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

guy or fire his weapon. If the weapon was fired we check every tick (that’s 1/10 s) if the bullett collided with any droid to destroy him. If collided then droid is destroyed and the bullett is also destroyed. If no collision then both droid’s and bullett’s new positions are calculated according totheir speed (droid moves 5 pixels every 1/10 s for ex and the bullett moves 50). We also check if the droid collided (reached) our guy and if so our hero is dead and game over.

This is an overview of how this game will work but will extend it as we go.

Reference: The Game Idea from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

Page 6: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Android Game Development – Create The ProjectPublished on July 3, 2011 | 88,812 views | Filed in: Android Games

Now that we have our idea let’s get the environment up and start coding.

To install Android follow the steps found on the official documentation page. I use eclipse so if you are a Java guy it should be pretty familiar. If you have never developed in Java but did some other coding in C++ or C# for example it should be pretty simple to catch up. I would recommend starting with some Java tutorials and then switch to Android. If you haven’t programmed before…well that’s though but it’s solvable. Google for some programming tutorials and don’t get discouraged! Then check back here.

I will use Android 2.2 as it is the latest at the time of this writing and I suspect it will take a long time till I finish this project so it just might be quite used. Also because we plan to use multi-touch we need version 2.x.

First let’s create the AVD (Android Virtual Device). Click on the little Android icon or choose Window -> Android SDK and AVD Manager and click on the New… button.

Set the name to MyDevice, the target to Android 2.2 – API Level 8. Set 128 MiB for the SD Card. Set the Skin to Built-in HVGA and the Hardware to Abstracted LCD density to 160. These are the current default settings.

Page 7: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Click Create AVD and the virtual device should be created.

Now let’s create the project.

Select from the menu: New -> Project and choose Android Project.

Fill in as per the screen-shot and click Finish.

The Application name is the name given to our game. The package name is just the name space to group our classes.

Select Android 2.2 for Build Target.

The most important is the Create Activity. The Activity is the class instantiated when the application is started. Don’t have to worry about it right now just remember that is the first thing being called.

Page 8: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

In a nutshell the Activity handles our input (gets the touches on the screen), creates the window where we will display our game and so on. This usually is a full screen window and we will use one as such.

Let’s run the created application. Right click on the project and choose Run As -> Android Application. Choose the configured device and wait for it to load. Remember not to close the Virtual Device once it has started as every time you will run your project, eclipse will redeploy itto the currently running device and will save you a lot of time if it’s already started.

You should see a screen like the one below. If the device asks you to unlock the screen do it by dragging the unlock button with your mouse.

Page 9: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Now let’s examine what has just happened. Open the DroidzActivity.java file.

view source

print?

package net.obviam.droidz;

import android.app.Activity;

import android.os.Bundle;

public class DroidzActivity extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

}

Page 10: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

01 package net.obviam.droidz;0203 import android.app.Activity;04 import android.os.Bundle;0506 public class DroidzActivity extends Activity {07 /** Called when the activity is first created. */08 @Override09 public void onCreate(Bundle savedInstanceState) {10 super.onCreate(savedInstanceState);11 setContentView(R.layout.main);12 }13 }

You’ll notice one method. The onCreate() method on line 09. This method is called when the activity is being created at the application launch. It’s sets the view (the display) to be the defaultR (check R.java) which is the default resource view automatically generated by the android tools behind the scenes.

This file feeds on multiple configuration files to provide the activity with the view. It reads the main.xml from the res (which stands for resources) directory and parses it.

Let’s open the res/layout/main.xml file:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="@string/hello"

/>

</LinearLayout>

Page 11: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

view source

print?

01 <?xml version="1.0" encoding="utf-8"?>02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"03 android:orientation="vertical"04 android:layout_width="fill_parent"05 android:layout_height="fill_parent"06 >07 <TextView08 android:layout_width="fill_parent"09 android:layout_height="wrap_content"10 android:text="@string/hello"11 />12 </LinearLayout>

You’ll notice that a LinearLayout is used that fills up the whole screen and has a vertical positioning (Line 2). Line 3 tells that our orientation is horizontal while lines 4 and 5 instruct android to use the whole display (currently the parent is the display) for the view.

Line 7 defines a TextView which is just a label that takes up a whole line of the contained text’s height. The value is a placeholder read from the @string file. @string is also a placeholder for the strings.xml file and opening this file you’ll immediately notice that this is the place where theactually displayed value comes from. Worth noting that the R.java file is regenerated after we modify strigs.xml and for each resource entry a corresponding constant is generated and it will be used internally.

Open the /res/values/strings.xml file:

view source

print?

1 <?xml version="1.0" encoding="utf-8"?>2 <resources>3 <string name="hello">Hello World, DroidzActivity!</string>4 <string name="app_name">droidz</string>5 <string name="warning">Robots are rising</string>6 </resources>

These are the resource strings. Apart from line 5 which I added everything is generated. To add the warning message to the display just after the hello message modify the main.xml file and adda new TextView that will display our @warning message.

The new main.xml file looks like this:

view source

Page 12: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

01 <?xml version="1.0" encoding="utf-8"?>02 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"03 android:orientation="vertical"04 android:layout_width="fill_parent"05 android:layout_height="fill_parent"06 >07 <TextView08 android:layout_width="fill_parent"09 android:layout_height="wrap_content"10 android:text="@string/hello"11 />12 <TextView13 android:layout_width="fill_parent"14 android:layout_height="wrap_content"15 android:text="@string/warning"16 />17 </LinearLayout>

If you run the activity then you should have a screen displaying the new warning message too.

Worth noting that eclipse regenerated the R.java file and if you open it you will notice a similar line to this:

view source

print?

1 public static final int warning=0x7f040002;

It is generated by the android tooling and it keeps the IDs and pointers to the actual resources that are used in the activity.

Go ahead and play with the current setting and see what the options are for different display widgets.

Page 13: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Next we will actually load some images and draw them onto the screen.

Reference: Creating the Android Project from our JCG partner Tamas Jano from “Against The Grain” blog.

Android Game Development – A Basic Game ArchitecturePublished on July 4, 2011 | 58,341 views | Filed in: Android Games

So we got our Android application up and running but you might be wondering what type of application is exactly a game. I will try to give you my understanding of it. The following diagram represents a game architecture.

Game architecture on an Android phone

In the schema above you see the Android OS running on the Phone and everything on top of that.

The input is the touch-screen in our case but it can be a physical keyboard if the phone has one, the microphone, the camera, the accelerometers or even the GPS receiver if equipped. The framework exposes the events when touching the screen through the View used in our Activity from the previous article.

The User Input

In our game this is the event generated by touching the screen in one of the 2 defined control areas. (see Step 1 – the coloured circles). Our game engine monitors the onTouch event and at every touch we record the coordinates. If the coordinates are inside our defined control areas on the screen we will instruct the game engine to take action. For example if the touch occurs in the circle designated to move our guy the engine gets notified and our guy is instructed to move. If the weapon controller circle is touched the equipped weapon will be instructed to fire its bullets. All this translates to changing the actors’ states that are affected by our gestures aka input.

Page 14: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

I have just described the Game Logic part which follows.

Game Logic

The game logic module is responsible for changing the states of the actors in the game. By actorsI mean every object that has a state. Our hero, droids, terrain, bullets, laser beams etc. For example we touch the upper half of the hero control area like in the drawing and this translates to: calculate the movement speed of our guy according to the position of our movement controller (our finger).

In the image above the light green circle represents our finger touching the control area. The User Input module notifies the Game Engine (Game Logic) and also provides the coordinates. dxand dy are the distances in pixels relative to the controller circle centre. The game engine calculates the new speed it has to set for our hero and the direction he will move. If dx is positivethat means he will go right and if dy is positive he will also move upward.

Audio

This module will produce sounds considering the current state. As almost every actor/object will produce sounds in their different states and because the devices we’ll run our game on are limited to just a few channels (that means briefly how many sounds can the device play at once) it has to decide which sounds to play. For example the droid posing the biggest threat to our hero will be heard as we want to draw attention to it and of course we will need to reserve a channel for the awesome shooting sound of our weapon as it is much fun listening to our blaster singing. So this is the audio in a nutshell.

Graphics

This is the module responsible for rendering the game state onto the display. This can be as simple as drawing directly onto the canvas obtained from the view or having a separate graphics buffer drawn into and then passed to the view which can be a custom view or an OpenGL view.

Page 15: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

We measure the rendering in FPS which stands for frames per second. If we have 30FPS that means that we display 30 images every second. For a mobile device 30 FPS is great so we will aim for that. More on this later.

The only thing you want to know now that the higher the FPS the smoother the animation. Just imagine someone walking and close your eyes for exactly one second. After opening your eyes you will see the person in the position after one second. This is a 2FPS. Watch them walk but keeping your eyes open and you’ll see a fluid motion. This is guaranteed to be a minimum of 30FPS but it is likely to be more, depending on your eyes. If you have awesome receptors in pristine condition this could be 80-100 or more.

Output

The output is the result of both sound and image and maybe vibration if we decide to produce some.

Next we will set up our view and will try to make our first game loop which will take input from the touch screen. We’ll have our first game engine.

Reference: A Basic Game Architecture from our JCG partner Tamas Jano from “Against The Grain” blog.

Android Game Development – A Basic Game LoopPublished on July 5, 2011 | 82,527 views | Filed in: Android Games

Following the series so far you we have an understanding of the game architecture. Even if just briefly but we know that we need to take input in some form, update the internal state of the game and finally render it to the screen and also produce some sounds and/or vibrations. Furthermore we have created an example Android project for our first game. In this article we are going to discuss and implement the basic game loop.

Let’s keep it simple. Check the following diagram.

Page 16: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

A Basic Game Loop

We handle input, update the state of our internal objects and render the current state. The Update and Render are grouped logically. They are tied together and tend to be executed one after the other.

Anything in Android happens inside an Activity. The Activity will create a View. The View is where everything happens. It is where the touch takes place and the resulting image gets displayed. Think of the Activity as a table that holds a sheet of paper (the View) enabling us to draw something. We will use our pencil to draw something onto the paper. That will be our touchand the actual chemistry happens on the paper so the result of our interaction with the View produces an image. The same is with Activity and View. Something like the following diagram:

Android Game Loop

Let’s open up DroidzActivity.java from our project. We see the line

Page 17: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

view source

print?

1 setContentView(R.layout.main);

This does nothing more than assigns the default (R) view to the activity when it is created. In ourcase it happens at startup.

Let’s create a new View which we will use. A View is a simple class that provides us with event handling (like onTouch) and a visible rectangle shaped space to draw on. The simplest way is to extend Android’s own SurfaceView. We will also implement SurfaceHolder.Callback to gain access to surface changes, for example when it is destroyed or the orientation of the device has changed.

MainGamePanel.java

package net.obviam.droidz;

import android.content.Context;

import android.graphics.Canvas;

import android.view.MotionEvent;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

public class MainGamePanel extends SurfaceView implements

SurfaceHolder.Callback {

public MainGamePanel(Context context) {

super(context);

// adding the callback (this) to the surface holder to intercept events

getHolder().addCallback(this);

Page 18: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

// make the GamePanel focusable so it can handle events

setFocusable(true);

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

}

@Override

public boolean onTouchEvent(MotionEvent event) {

return super.onTouchEvent(event);

}

@Override

protected void onDraw(Canvas canvas) {

Page 19: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

}

}

view source

print?

01 package net.obviam.droidz;0203 import android.content.Context;04 import android.graphics.Canvas;05 import android.view.MotionEvent;06 import android.view.SurfaceHolder;07 import android.view.SurfaceView;0809 public class MainGamePanel extends SurfaceView implements10 SurfaceHolder.Callback {1112 public MainGamePanel(Context context) {13 super(context);14 // adding the callback (this) to the surface holder to intercept events15 getHolder().addCallback(this);16 // make the GamePanel focusable so it can handle events17 setFocusable(true);18 }1920 @Override21

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

22

}

2324 @Override25 public void surfaceCreated(SurfaceHolder holder) {26 }2728 @Override29 public void surfaceDestroyed(SurfaceHolder holder) {30 }3132 @Override33 public boolean onTouchEvent(MotionEvent event) {34 return super.onTouchEvent(event);35 }3637 @Override38 protected void onDraw(Canvas canvas) {

Page 20: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

39 }40 }

The above code is a plain class that overrides the methods we are interested in.Nothing special apart from lines 15 and 17.

view source

print?

1 getHolder().addCallback(this);

This line sets the current class (MainGamePanel) as the handler for the events happening on the actual surface.

view source

print?

1 setFocusable(true);

The above line makes our Game Panel focusable, which means it can receive focus so it can handle events. We added the callback and made it focusable in the constructor so we won’t miss.

The over-riden methods (line 20 onwards) will all be used but currently keep them empty.

Let’s create the thread that will be our actual game loop.

MainThread.java

package net.obviam.droidz;

public class MainThread extends Thread {

// flag to hold game state

private boolean running;

public void setRunning(boolean running) {

this.running = running;

}

Page 21: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

@Override

public void run() {

while (running) {

// update game state

// render state to the screen

}

}

}

view source

print?

01 package net.obviam.droidz;0203 public class MainThread extends Thread {0405 // flag to hold game state06 private boolean running;07 public void setRunning(boolean running) {08 this.running = running;09 }1011 @Override12 public void run() {13 while (running) {14 // update game state15 // render state to the screen16 }17 }18 }

As you can see this does not do much. It overrides the run() method and while the running flag is set to true it does an infinite loop.

Currently the thread is not instantiated so let’s start it up when the screen loads.Let’s take a look at the modified MainGamePanel class.

Page 22: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

package net.obviam.droidz;

import android.content.Context;

import android.graphics.Canvas;

import android.view.MotionEvent;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

public class MainGamePanel extends SurfaceView implements

SurfaceHolder.Callback {

private MainThread thread;

public MainGamePanel(Context context) {

super(context);

getHolder().addCallback(this);

// create the game loop thread

thread = new MainThread();

setFocusable(true);

}

Page 23: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

thread.setRunning(true);

thread.start();

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

boolean retry = true;

while (retry) {

try {

thread.join();

retry = false;

} catch (InterruptedException e) {

// try again shutting down the thread

}

}

}

Page 24: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

@Override

public boolean onTouchEvent(MotionEvent event) {

return super.onTouchEvent(event);

}

@Override

protected void onDraw(Canvas canvas) {

}

}

view source

print?

01 package net.obviam.droidz;0203 import android.content.Context;04 import android.graphics.Canvas;05 import android.view.MotionEvent;06 import android.view.SurfaceHolder;07 import android.view.SurfaceView;0809 public class MainGamePanel extends SurfaceView implements10 SurfaceHolder.Callback {1112 private MainThread thread;1314 public MainGamePanel(Context context) {15 super(context);16 getHolder().addCallback(this);1718 // create the game loop thread19 thread = new MainThread();2021 setFocusable(true);22 }2324 @Override2 public void surfaceChanged(SurfaceHolder holder, int format, int width, int

Page 25: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

5 height) {26

}

2728 @Override29 public void surfaceCreated(SurfaceHolder holder) {30 thread.setRunning(true);31 thread.start();32 }3334 @Override35 public void surfaceDestroyed(SurfaceHolder holder) {36 boolean retry = true;37 while (retry) {38 try {39 thread.join();40 retry = false;41 } catch (InterruptedException e) {42 // try again shutting down the thread43 }44 }45 }4647 @Override48 public boolean onTouchEvent(MotionEvent event) {49 return super.onTouchEvent(event);50 }5152 @Override53 protected void onDraw(Canvas canvas) {54 }55 }

We added the following lines:Line 12 declares the thread as a private attribute.

view source

print?

1 private MainThread thread;

In line 19 we instantiate the thread.

view source

print?

1 thread = new MainThread();

Page 26: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

In the surfaceCreated method we set the running flag to true and we start up the thread (lines 30 and 31). By the time the this method is called the surface is already created and the game loop can be safely started.

Take a look at the surfaceDestroyed method.

view source

print?

01 public void surfaceDestroyed(SurfaceHolder holder) {02 // tell the thread to shut down and wait for it to finish03 // this is a clean shutdown04 boolean retry = true;05 while (retry) {06 try {07 thread.join();08 retry = false;09 } catch (InterruptedException e) {10 // try again shutting down the thread11 }12 }13 }

This method is called directly before the surface is destroyed. It is not the place to set the runningflag but the code we put in ensures that the thread shuts down cleanly. We simply block the thread and wait for it to die.

If we now run our project in the emulator won’t be able to see much but we’ll use some logging to test it. Don’t worry about it as I will cover logging in a later chapter.You can find more on the Android site.

Add interaction with the screen

We will exit the application when we touch the lower part of the screen. If we touch it anywhere else we’ll just log the coordinates.

In the MainThread class we add the following lines:

view source

print?

1 private SurfaceHolder surfaceHolder;2 private MainGamePanel gamePanel;34 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {

Page 27: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

5 super();6 this.surfaceHolder = surfaceHolder;7 this.gamePanel = gamePanel;8 }

We declared the gamePanel and surfaceHolder variables and a constructor taking the instances as parameters.It is important to have them both and not just the gamePanel as we need to lock the surface when we draw and that can be done through the surfaceHolder only.

Change the line int the constructor of the MainGamePanel that instantiates the thread to

view source

print?

1 thread = new MainThread(getHolder(), this);

We are passing the current holder and the panel to its new constructor so the thread can access them. We will create the game update method in the game panel and we’ll trigger it from the thread but currently just leave it as it is.

Add the TAG constant to the MainThread class. Every class will have its own String constant called TAG. The value of the constant will be the name of the class containing it. We are using Android’s own logging framework and that takes two parameters. The firs is the tag which is justa string to identify the source of the log message and the second is the message we want to log. It’s a good practice to use the name of the class for the tag as it makes it simple to look up the logs.

A note on logging

To open the log viewer go to Windows -> Show View -> Other… and in the dialog select Android -> LogCat

Page 28: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Show View -> LogCat

Now you should see the LogCat view. This is nothing more than a console where you can follow Android’s log. It’s a great tool as you can filter for logs containing a specific text or logs with a certain tag which is quite useful.

Let’s get back to our code. The MainThread.java class looks like this:

view source

print?

01 package net.obviam.droidz;0203 import android.util.Log;04 import android.view.SurfaceHolder;0506 public class MainThread extends Thread {0708 private static final String TAG = MainThread.class.getSimpleName();0910 private SurfaceHolder surfaceHolder;11 private MainGamePanel gamePanel;12 private boolean running;13 public void setRunning(boolean running) {14 this.running = running;15 }1617 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {18 super();

Page 29: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

19 this.surfaceHolder = surfaceHolder;20 this.gamePanel = gamePanel;21 }2223 @Override24 public void run() {25 long tickCount = 0L;26 Log.d(TAG, "Starting game loop");27 while (running) {28 tickCount++;29 // update game state30 // render state to the screen31 }32 Log.d(TAG, "Game loop executed " + tickCount + " times");33 }34 }

In line 08 we define the tag for logging.In the run() method we define tickCount which is incremented every time the while loop (the game loop) is executed.We log the results.

Let’s go back to MainGamePanel.java class where we modified the onTouchEvent method so we handle touches on the screen.

view source

print?

01 public boolean onTouchEvent(MotionEvent event) {02 if (event.getAction() == MotionEvent.ACTION_DOWN) {03 if (event.getY() > getHeight() - 50) {04 thread.setRunning(false);05 ((Activity)getContext()).finish();06 } else {07 Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());08 }09 }10 return super.onTouchEvent(event);11 }

Line 02 we check if the event on the screen is a start of a pressed gesture (MotionEvent.ACTION_DOWN). If so we check if the touch happened in the lower part of the screen. That is, the Y coordinate of the gesture is in the lower 50 pixels of the screen. If so we setthe thread’s running status to false and call finish() on the main activity which basically exits theapplication.

Page 30: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Note: The screen is a rectangle with the upper left coordinates at (0,0) and the lower right coordinates at (getWidth(), getHeight()).

I have also modified the DroidzActivity.java class so we log its lifecycle.

view source

print?

01 package net.obviam.droidz;0203 import android.app.Activity;04 import android.os.Bundle;05 import android.util.Log;06 import android.view.Window;07 import android.view.WindowManager;0809 public class DroidzActivity extends Activity {10 /** Called when the activity is first created. */1112 private static final String TAG = DroidzActivity.class.getSimpleName();1314 @Override15 public void onCreate(Bundle savedInstanceState) {16 super.onCreate(savedInstanceState);17 // requesting to turn the title OFF18 requestWindowFeature(Window.FEATURE_NO_TITLE);19

// making it full screen

20

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

21 // set our MainGamePanel as the View22 setContentView(new MainGamePanel(this));23 Log.d(TAG, "View added");24 }2526 @Override27 protected void onDestroy() {28 Log.d(TAG, "Destroying...");29 super.onDestroy();30 }3132 @Override33 protected void onStop() {34 Log.d(TAG, "Stopping...");35 super.onStop();36 }37 }

Page 31: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Line 20 makes the display fullscreen.The onDestroy() and onStop() methods were overridden just to log the activity’s lifecycle.

Let’s run the application by right-clicking on the project and select Run As -> Android applicationYou should see a black screen. If you click around a few time on the upper half and then you click on the bottom of your emulator’s screen the application should exit.At this stage it is worth checking the logs.

LogCat

The highlighted lines are the most interesting as if you match look the logs up in the code you will see exactly the order of the method calls. You should also see how many times the thread’s while loop executed. It is a very high number but next time we will be more considerate about the cycles as we will introduce FPS and UPS. That is Frames Per Second and Updates Per Second. We will create a game loop that will actually draw something onto the screen and it will do it as many times per second as we specify it.

Things we did so far:

Create a full screen application

Have a separate thread controlling the application

Intercepting basic gestures like pressed gesture

Shutting down the application graciously

Download the source code here.

Import it into eclipse and it should work right away.

5

Page 32: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Android Game Development – Displaying Images with AndroidPublished on July 7, 2011 | 18,476 views | Filed in: Android Games

Before moving to the actual game loop let’s display some graphics so we can get some measurements done. If you haven’t checked it out please do as it is imperative that you understand how a thread updates the screen. You can check it out here.

Displaying an image using Android is extremely simple.To scale the problem down we will just display the image in the top left corner. We need an image to display. I prefer .png formats and I have just created one named droid_1.png. The size of the image is 20×20 pixels. You can use whatever tool you like. I use Gimp or Photoshop.

To make it available for your application just copy the image into the /res/drawable-mdpi directory (the easiest way is to drag and drop it there).I have chosen mdpi which stands for normal screen medium density. To read on screen types check the android documentation.

Modify the MainGamePanel.java class and change the onDraw(Canvas canvas) method to looklike this:

view source

print?

1protected void onDraw(Canvas canvas) {

2canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);

3 }

The drawBitmap method draws the droid_1 image to the coordinates 10,10.We obtain the bitmap from the application resources by passing the id of our image (resource), which is droid_1 in our case. When we copied the droid_1.png into the resource directory eclipse detected it and the plugin executed the necessary scripts in the background so we have the droid_1 identifier in the R.java file. The R.java holds the resource identifiers.

The thread suffered some changes too. Examine the new run() method.

view source

print?

01 public void run() {02 Canvas canvas;

Page 33: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

03 Log.d(TAG, "Starting game loop");04 while (running) {05 canvas = null;06 // try locking the canvas for exclusive pixel editing on the surface07 try {08 canvas = this.surfaceHolder.lockCanvas();09 synchronized (surfaceHolder) {10 // update game state11 // draws the canvas on the panel12 this.gamePanel.onDraw(canvas);13 }14 } finally {15 // in case of an exception the surface is not left in16 // an inconsistent state17 if (canvas != null) {18 surfaceHolder.unlockCanvasAndPost(canvas);19 }20 } // end finally21 }22 }

In line 02 we declare the canvas on which we will draw our image. The canvas is the surface’s bitmap onto which we can draw and we can edit its pixels. In line 08 we try to get hold of it and in line 12 we trigger the panel’s onDraw event to which we pass the obtained canvas. Note that itis a synchronised block which means that we have exclusivity on it and nothing can modify it while we are using it.The functionality is very simple and basic. On every execution of the game loop we get hold of the canvas and we pass it to the game panel to draw on it. The game panel just displays the imageat coordinates 10,10. Now back to the FPS. If the number of times per second the image is displayed drops below 20, it starts to get noticeable by us humans. The challenge is to keep this rate above a set level and we will see how shortly.

Try running the code and you should see our droid displayed close to the top left corner.

Droid in top left corner

Moving the Image

Now that we have displayed it, let’s try moving it. How? We will use our finger. We will implement a simple drag and drop functionality. To pick up an image we will simply touch it and

Page 34: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

while our finger is on the screen we will update the image’s coordinates accordingly. Once the touch is finished we leave the image there where the last touch was recorded.

We need to create an object that will hold our image and the coordinates.I have created Droid.java for this. Note that I have put the class into the net.obviam.droidz.model package.

view source

print?

01 package net.obviam.droidz.model;0203 import android.graphics.Bitmap;0405 public class Droid {0607 private Bitmap bitmap; // the actual bitmap08 private int x; // the X coordinate09 private int y; // the Y coordinate1011 public Droid(Bitmap bitmap, int x, int y) {12 this.bitmap = bitmap;13 this.x = x;14 this.y = y;15 }1617 public Bitmap getBitmap() {18 return bitmap;19 }20 public void setBitmap(Bitmap bitmap) {21 this.bitmap = bitmap;22 }23 public int getX() {24 return x;25 }26 public void setX(int x) {27 this.x = x;28 }29 public int getY() {30 return y;31 }32 public void setY(int y) {33 this.y = y;34 }35 }

Page 35: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

It is a plain class with some attributes and a constructor.The x and y are the coordinates of the droid. The bitmap holds the image that will be displayed as the droid. It is the graphical representation of it.

So far nothing special. But to play around with it we need to add some state. To keep it simple, the droid has only 2 states. Touched and untouched. By touched I mean when our finger touched the droid on the screen. We keep the touched state true while we hold our finger down on the screen at the droid’s position. Otherwise the droid remains untouched (state set to false).

Check out the new droid class.

view source

print?

01 package net.obviam.droidz.model;0203 import android.graphics.Bitmap;04 import android.graphics.Canvas;05 import android.view.MotionEvent;0607 public class Droid {0809 private Bitmap bitmap; // the actual bitmap10 private int x; // the X coordinate11 private int y; // the Y coordinate12 private boolean touched; // if droid is touched/picked up1314 public Droid(Bitmap bitmap, int x, int y) {15 this.bitmap = bitmap;16 this.x = x;17 this.y = y;18 }1920 public Bitmap getBitmap() {21 return bitmap;22 }23 public void setBitmap(Bitmap bitmap) {24 this.bitmap = bitmap;25 }26 public int getX() {27 return x;28 }29 public void setX(int x) {30 this.x = x;31 }32 public int getY() {33 return y;

Page 36: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

34 }35 public void setY(int y) {36 this.y = y;37 }3839 public boolean isTouched() {40 return touched;41 }4243 public void setTouched(boolean touched) {44 this.touched = touched;45 }4647

public void draw(Canvas canvas) {

48

canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y - (bitmap.getHeight() / 2), null);

49 }5051

public void handleActionDown(int eventX, int eventY) {

52

if (eventX >= (x - bitmap.getWidth() / 2) && (eventX <= (x + bitmap.getWidth()/2))) {

53

if (eventY >= (y - bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {

54

// droid touched

55 setTouched(true);56 } else {57 setTouched(false);58 }59 } else {60 setTouched(false);61 }6263 }64 }

We added the touched field to keep track of the state of our droid. You will notice two more methods: public void draw(Canvas canvas) and public void handleActionDown(int eventX, int eventY).These methods are discussed later.Now let’s have a look at the MainGamePanel.java. It changed quite a lot.

view source

print?

001 package net.obviam.droidz;

Page 37: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

002003 import net.obviam.droidz.model.Droid;004 import android.app.Activity;005 import android.content.Context;006 import android.graphics.BitmapFactory;007 import android.graphics.Canvas;008 import android.graphics.Color;009 import android.util.Log;010 import android.view.MotionEvent;011 import android.view.SurfaceHolder;012 import android.view.SurfaceView;013014 public class MainGamePanel extends SurfaceView implements015 SurfaceHolder.Callback {016017 private static final String TAG = MainGamePanel.class.getSimpleName();018019 private MainThread thread;020 private Droid droid;021022 public MainGamePanel(Context context) {023 super(context);024 // adding the callback (this) to the surface holder to intercept events025 getHolder().addCallback(this);026027

// create droid and load bitmap

028

droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 50, 50);

029030 // create the game loop thread031 thread = new MainThread(getHolder(), this);032033 // make the GamePanel focusable so it can handle events034 setFocusable(true);035 }036037 @Override038 public void surfaceChanged(SurfaceHolder holder, int format, int width,039 int height) {040 }041042 @Override043 public void surfaceCreated(SurfaceHolder holder) {044 // at this point the surface is created and045 // we can safely start the game loop046 thread.setRunning(true);047 thread.start();

Page 38: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

048 }049050 @Override051 public void surfaceDestroyed(SurfaceHolder holder) {052 Log.d(TAG, "Surface is being destroyed");053 // tell the thread to shut down and wait for it to finish054 // this is a clean shutdown055 boolean retry = true;056 while (retry) {057 try {058 thread.join();059 retry = false;060 } catch (InterruptedException e) {061 // try again shutting down the thread062 }063 }064 Log.d(TAG, "Thread was shut down cleanly");065 }066067 @Override068 public boolean onTouchEvent(MotionEvent event) {069 if (event.getAction() == MotionEvent.ACTION_DOWN) {070 // delegating event handling to the droid071 droid.handleActionDown((int)event.getX(), (int)event.getY());072073 // check if in the lower part of the screen we exit074 if (event.getY() > getHeight() - 50) {075 thread.setRunning(false);076 ((Activity)getContext()).finish();077 } else {078 Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());079 }080 } if (event.getAction() == MotionEvent.ACTION_MOVE) {081 // the gestures082 if (droid.isTouched()) {083 // the droid was picked up and is being dragged084 droid.setX((int)event.getX());085 droid.setY((int)event.getY());086 }087 } if (event.getAction() == MotionEvent.ACTION_UP) {088 // touch was released089 if (droid.isTouched()) {090 droid.setTouched(false);091 }092 }093 return true;094 }095096 @Override

Page 39: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

097 protected void onDraw(Canvas canvas) {098 // fills the canvas with black099 canvas.drawColor(Color.BLACK);100 droid.draw(canvas);101 }102 }

Line 28 creates the droid object at the the coordinates 50,50.It is declared as an attribute in line 20.

In the onTouchEvent (method line 71) if the action is the touch of the screen (MotionEvent.ACTION_DOWN) we want to know if our finger landed on the droid. To do this is easy. We need to check if the event’s coordinates are inside the droid’s bitmap. In order not to clutter the onTouch event we just delegate this to the droid object. Now you can go back to the Droid.java class and check the handleActionDown method.

view source

print?

01

public void handleActionDown(int eventX, int eventY) {

02

if (eventX >= (x - bitmap.getWidth() / 2) && (eventX <= (x + bitmap.getWidth()/2))) {

03

if (eventY >= (y - bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {

04

// droid touched

05 setTouched(true);06 } else {07 setTouched(false);08 }09 } else {10 setTouched(false);11 }1213 }

It is very simple. If the action happened inside the area of our droid’s bitmap we’ll set its touchedstatus to true

Going back to the onTouched method, notice that there is a code block (lines 81-86) that is executed when the event is of type MotionEvent.ACTION_MOVE. This event happens when our finger started to move on the screen. It is simple. We check if the droid is touched and if so we just update its coordinates accordingly.That is it. This was the update game state. We have updated the state of our sole object in the game. The touched state and the coordinates. Now it is time to display it.

Page 40: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Check the onDraw method. This is triggered at every execution of the main loop inside the thread remember?It contains 2 lines. Line 99 simply fills the canvas with black and line 100 tells the droid to draw itself on the canvas provided. By doing this is like me giving you a paper to draw yourself onto it, and give the paper back to me so I can continue my drawing.

Check Droid.java for the draw implementation. It is dead simple. It takes the bitmap it was instantiated with and draws it to the canvas at the coordinates the droid is at in that moment. Note that the coordinates of the droid are exactly in the center of the bitmap so we need to move the pointer to the top left corner of the image and draw it there. I’m sure you won’t find it hard tounderstand.

That’s it. Run it and have a play with it.

Download he code for the project here (droidz.android.02.3-graphics.tar.gz)

Reference: Displaying Images with Android from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

6

Android Game Development – Moving Images on ScreenPublished on July 9, 2011 | 5,696 views | Filed in: Android Games

In the previous post we’ve displayed an image and implemented a very simple drag functionality.Things we should know by now following the series:

launch an Android application in full screen

use a separate thread which controls the application (the game loop)

load an image from the resources

acquire the canvas and draw the image onto it

handle basic touch gestures

Page 41: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The task I’m setting for this entry is simple: have the droid travel through the screen. It should never leave the surface and it should bounce back when it hits the wall which is the edge of the screen.

If you remember the image is just a representation of the droid. So we will modify the droid object and we’ll add some abilities. Just one for the time being. Our droid is movable. It can move. This implies that it has speed. We will vest it with the ability of movement. To achieve thiswe will add a move() method and this method will just update the X and Y coordinates based on its Speed. Speed will be a class in itself and the Droid will contain it. I will do a concrete implementation now but later on I will be using the Strategy Pattern.

Create the Speed.java class.

view source

print?

01 package net.obviam.droidz.model.components;0203 public class Speed {0405 public static final int DIRECTION_RIGHT = 1;06 public static final int DIRECTION_LEFT = -1;07 public static final int DIRECTION_UP = -1;08 public static final int DIRECTION_DOWN = 1;0910 private float xv = 1; // velocity value on the X axis11 private float yv = 1; // velocity value on the Y axis1213 private int xDirection = DIRECTION_RIGHT;14 private int yDirection = DIRECTION_DOWN;1516 public Speed() {17 this.xv = 1;18 this.yv = 1;19 }2021 public Speed(float xv, float yv) {22 this.xv = xv;23 this.yv = yv;24 }2526 public float getXv() {27 return xv;28 }29 public void setXv(float xv) {30 this.xv = xv;31 }

Page 42: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

32 public float getYv() {33 return yv;34 }35 public void setYv(float yv) {36 this.yv = yv;37 }3839 public int getxDirection() {40 return xDirection;41 }42 public void setxDirection(int xDirection) {43 this.xDirection = xDirection;44 }45 public int getyDirection() {46 return yDirection;47 }48 public void setyDirection(int yDirection) {49 this.yDirection = yDirection;50 }5152 // changes the direction on the X axis53 public void toggleXDirection() {54 xDirection = xDirection * -1;55 }5657 // changes the direction on the Y axis58 public void toggleYDirection() {59 yDirection = yDirection * -1;60 }61 }

We’ll use direction constants to determine the movement direction on the axis. The droid has a vertical and a horizontal speed and at each game update the coordinates are set considering the direction of the movement.The droid will be allowed to move only on the area of the canvas. That is a rectangle and our 2D coordinate system. Unlike in the math classes the origin is in the top left corner. So for the droid to start from the top left corner of the screen its coordinates will be 0,0. To move in a diagonal line the speed will be 1 for both the X and Y components of the speed vector. To move towards the bottom right the directions will be: 1 (right) for the X axis and 1 (down) for the Y axis.

Page 43: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Canvas Coordinate System

To have the droid move horizontally the speed of the Y vector must be 0. A value of 0.5 for Y and 1 for X will make the droid travel at a 22.5 degrees to the X axis. Simple geometry.

In the Speed we have the vector components (x and y) and the directions along with the getters and setters. The two methods (toggleXDirection() and toggleYDirection()) just change the direction with one call. We’ll see later at collision detection (with the wall of the screen) that it is pretty useful.

The game loop (MainThread.java) gets an important modification as it gets the game update method introduced. The following code snippet is the updated run() method which has just one line added:

view source

print?

1 this.gamePanel.update();

The run() method:

view source

print?

01 public void run() {02 Canvas canvas;03 Log.d(TAG, "Starting game loop");04 while (running) {

Page 44: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

05 canvas = null;06 // try locking the canvas for exclusive pixel editing07 // in the surface08 try {09 canvas = this.surfaceHolder.lockCanvas();10 synchronized (surfaceHolder) {11 // update game state12 this.gamePanel.update();13 // render state to the screen14 // draws the canvas on the panel15 this.gamePanel.render(canvas);16 }17 } finally {18 // in case of an exception the surface is not left in19 // an inconsistent state20 if (canvas != null) {21 surfaceHolder.unlockCanvasAndPost(canvas);22 }23 } // end finally24 }25 }

We will create the corresponding method in the MainGamePanel. This method is in charge of updating the state of all the objects in the application. Currently only the droid. Because the droidis moving we will introduce a basic collision detection with the walls. The logic is simple. Checkif the droid is moving towards left then check if the droid’s position is at the wall and if it is then change its direction. Bear in mind that the droid’s position is the center of the image so we need to use the image’s width and height to get the accuracy right.We also update the position of the droid. To keep the update method simple we delegate the update of the droid’s position to the droid itself. So the droid will get an update method which will keep updating its position if the droid is not being picked up by a touch gesture. Check the previous post for this.

Check the code: MainGamePanel.java

view source

print?

01 public void update() {02 // check collision with right wall if heading right03 if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT04 && droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {05 droid.getSpeed().toggleXDirection();06 }07 // check collision with left wall if heading left08 if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT09 && droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {10 droid.getSpeed().toggleXDirection();

Page 45: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

11 }12 // check collision with bottom wall if heading down13 if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN14 && droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {15 droid.getSpeed().toggleYDirection();16 }17 // check collision with top wall if heading up18 if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP19 && droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {20 droid.getSpeed().toggleYDirection();21 }22 // Update the lone droid23 droid.update();24 }

getWidth() and getHeight() return the width and height of the view. The panel is a view, remember?

The Droid.java file’s update() method:

view source

print?

1 public void update() {2 if (!touched) {3 x += (speed.getXv() * speed.getxDirection());4 y += (speed.getYv() * speed.getyDirection());5 }6 }

I also changed the render’s name in the MainThread.java so now it is render instead if onDraw. Just that I like it better as it follows the update -> render naming.

Run the application and you should see a screen like the following one with the droid moving in a 45 degrees angle and bouncing off the walls as it hits them. You can also drag the droid around.To exit the application click (touch) the lower part of the screen.

Page 46: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Moving Droid

Download the full source code and eclipse project here.

Reference: Moving Images on the Screen with Android from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

7

Android Game Development – The Game LoopPublished on July 12, 2011 | 32,726 views | Filed in: Android Games

The game loop is the heartbeat of every game. We used a very rudimentary one so far (you can find it here) without any control over how fast or slow we update our game state and which frames to render.

To recapitulate, the most rudimentary game loop is a while loop that keeps executing some instructions until we signal it to finish, usually by setting a variable called running to false

view source

print?

1 boolean running = true;2 while (!running)3 {4 updateGameState();5 displayGameState();6 }

The above code runs blindly without a care for timing and resources. If you have a fast device then it will run very fast and if you have a slow one it will run slower.

The updateGameState() updates the state of every object in the game and the displayGameState() renders the objects into an image which is displayed onto the screen.

There are two things we should consider here: FPS and UPS.

FPS – Frames per Second – the number of times displayGameState() is being called per second.UPS – Update per Second – the number of times updateGameState() is being called per second.

Page 47: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Ideally the update and render methods will be called the same number of times per second (preferably not less than 20-25 times per second). 25 FPS is usually enough on a phone so us humans won’t notice the animation being sluggish.

For example if we target 25 FPS then it means we have to call the displayGameState() method every 40ms (1000 / 25 = 40ms, 1000ms = 1s). We need to bear in mind that updateGameState() is also called before the display method and for us to reach 25 FPS, we have to make sure that the update – display sequence executes in exactly 40ms. If it takes less than 40ms, then we have a higher FPS. If it takes more than that, then we have a slower running game.

Let’s see some examples to understand the FPS better.

The following diagram shows exactly 1 FPS. It takes the update – render cycle exactly one second to execute. This means that you will see the image on the screen change once every second.

1 Frame per Second

The following diagram shows 10FPS. An update – render cycle takes 100ms. This means every tenth of a second the image changes.

Page 48: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

10 FPS

But the above scenario means that the update-render cycle executes in 1/10 of a second EVERY time. That is an assumption and we can’t control the actual times on cycle executes, or can we? What happens if we have 200 enemies and every enemy is shooting at us? We need to update the state of each enemy and the states of their bullets and check for collisions in one single update. It’s different when we have just 2 enemies. The times will clearly differ. The same applies to the render method. Rendering 200 firing droids will clearly take more time than rendering only 2.

So what are the scenarios? We could have an update-render cycle that finishes in less than 100ms(1/10 of a second), finishes in exactly 100ms or finishes in more than that. On a powerful hardware it will be faster than on a weaker one. Let’s see the diagrams.

The cycle finishes before the desired timeframe so we have a small amount of free time before running the next cycle.

Page 49: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Frame with time to spare

The following diagram shows a cycle which falls behind. That means that the time it takes for a update-render cycle to finish is greater than the desired one. If it takes 12ms that means we are 2ms behind (still considering the 10FPS). This can mount up and every cycle we loose time and the game will run slowly.

Overdue Frame

The first situation is the desired one. This gives us some free time to do something before we kick off the next cycle. We don’t need to do anything so we just tell the game loop to go to sleep for the remaining time period and wake up when the next cycle is due. If we won’t do this the game will run quicker than intended. By introducing the sleep time we achieved constant frame rate.

Page 50: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The second situation (I skipped the ideal one as it almost never happens) when the loop is behind, requires a different approach.

To achieve constant speed in a game we need to update the state of our objects when required. Imagine a droid approaching you at a constant speed. You know if it travelled half the screen in one second, so it will take another second to reach the other side of the screen. To calculate the position accurately we need to know either the time delta since the last postion, and the current speed of the droid, or we update the position (status) of the droid at constant intervals. I will choose the second one as playing with deltas in the game update can be tricky. To achieve a constant game speed we will have to skip displaying frames. Game speed is NOT FPS!

Examine the following diagram. It is a scenario in which the update-render cycle takes longer than the desired time so we have to catch up. To do that we will skip the rendering of this frame and will do another update so the game speed won’t be affected. We’ll do a normal cycle in the next frame with even some time to give to the CPU to rest.

Constant Game Speed with Variable FPS

The above scenario has many variations. You can imagine the game update taking more than one full frame. In this case we can do nothing to keep the game speed constant and the game will run slower. We might have to skip multiple renderings to keep the speed constant but we have to make sure that we set the maximum number of frames allowed to be skipped because it can take quite a few updates to catch up and in case we skipped 15 frames that means we lost a lot from the game and it will just be unplayable.

The MainThread.java‘s run() looks like this:

view source

print?

01 // desired fps02 private final static int MAX_FPS = 50;03 // maximum number of frames to be skipped

Page 51: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

04 private final static int MAX_FRAME_SKIPS = 5;05 // the frame period06 private final static int FRAME_PERIOD = 1000 / MAX_FPS; 0708 @Override09 public void run() {10 Canvas canvas;11 Log.d(TAG, "Starting game loop");1213 long beginTime; // the time when the cycle begun14 long timeDiff; // the time it took for the cycle to execute15 int sleepTime; // ms to sleep (<0 if we're behind)16 int framesSkipped; // number of frames being skipped 1718 sleepTime = 0;1920 while (running) {21 canvas = null;22 // try locking the canvas for exclusive pixel editing23 // in the surface24 try {25 canvas = this.surfaceHolder.lockCanvas();26 synchronized (surfaceHolder) {27 beginTime = System.currentTimeMillis();28 framesSkipped = 0; // resetting the frames skipped29 // update game state30 this.gamePanel.update();31 // render state to the screen32 // draws the canvas on the panel33 this.gamePanel.render(canvas);34 // calculate how long did the cycle take35 timeDiff = System.currentTimeMillis() - beginTime;36 // calculate sleep time37 sleepTime = (int)(FRAME_PERIOD - timeDiff);3839 if (sleepTime > 0) {40 // if sleepTime > 0 we're OK41 try {42 // send the thread to sleep for a short period43 // very useful for battery saving44 Thread.sleep(sleepTime);45 } catch (InterruptedException e) {}46 }4748 while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {49 // we need to catch up50 // update without rendering51 this.gamePanel.update();52 // add frame period to check if in next frame

Page 52: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

53 sleepTime += FRAME_PERIOD;54 framesSkipped++;55 }56 }57 } finally {58 // in case of an exception the surface is not left in59 // an inconsistent state60 if (canvas != null) {61 surfaceHolder.unlockCanvasAndPost(canvas);62 }63 } // end finally64 }65 }

Examine the above code very carefully as it implements the logic behind the diagram. You can find the full code in the downloadable project.

There is another approach which I like. It is constant game speed with maximum number of frames per second. It uses interpolation to draw the state and it occurs on fast hardwares when there is time left for another rendering before the next game update. This can enhance the visualsof a game as it enables smoother animation but because we use mobile devices, giving the CPU some rest will save the battery quite a lot.

There is an awesome article on game loops here. I personally understood the game loops reading this article so I highly recommend it. The best I could find.

Note that I also modified the default values in the Speed.java class. The speed is measured in units/second. Because we are setting our desired FPS to 50 that means that the speed will increase by 50*speed.value every update. To have the speed of let’s say 40 pixels/second you will need to set the speed delta for every tick to 2 (40 / (1000 / 50) = 2). In other words you need the droid to advance 2 pixels every game update (when you have 50 game updates per second) tocover 40 pixels per second.

Download the code here and play with it.

Examine it and you have a constant game speed with variable frame rate.

Reference: The Game Loop from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

8

Android Game Development – Measuring FPS

Page 53: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Published on July 18, 2011 | 21,773 views | Filed in: Android Games

In the previous entry we have created a game loop that runs at a constant speed and constant (more or less) FPS.

How can we measure it?

Check the new MainThread.java class.

view source

print?

001 package net.obviam.droidz;002003 import java.text.DecimalFormat;004005 import android.graphics.Canvas;006 import android.util.Log;007 import android.view.SurfaceHolder;008009 /**010 * @author impaler011

*

012

* The Main thread which contains the game loop. The thread must have access to

013 * the surface view and holder to trigger events every game tick.014 */015 public class MainThread extends Thread {016017 private static final String TAG = MainThread.class.getSimpleName();018019 // desired fps020 private final static int MAX_FPS = 50;021 // maximum number of frames to be skipped022 private final static int MAX_FRAME_SKIPS = 5;023 // the frame period024 private final static int FRAME_PERIOD = 1000 / MAX_FPS;025026 // Stuff for stats */027 private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp028 // we'll be reading the stats every second029 private final static int STAT_INTERVAL = 1000; //ms030 // the average will be calculated by storing031 // the last n FPSs

Page 54: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

032 private final static int FPS_HISTORY_NR = 10;033 // last time the status was stored034 private long lastStatusStore = 0;035 // the status time counter036 private long statusIntervalTimer = 0l;037 // number of frames skipped since the game started038 private long totalFramesSkipped = 0l;039 // number of frames skipped in a store cycle (1 sec)040 private long framesSkippedPerStatCycle = 0l;041042 // number of rendered frames in an interval043 private int frameCountPerStatCycle = 0;044 private long totalFrameCount = 0l;045 // the last FPS values046 private double fpsStore[];047 // the number of times the stat has been read048 private long statsCount = 0;049 // the average FPS since the game started050 private double averageFps = 0.0;051052 // Surface holder that can access the physical surface053 private SurfaceHolder surfaceHolder;054 // The actual view that handles inputs055 // and draws to the surface056 private MainGamePanel gamePanel;057058 // flag to hold game state059 private boolean running;060 public void setRunning(boolean running) {061 this.running = running;062 }063064 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {065 super();066 this.surfaceHolder = surfaceHolder;067 this.gamePanel = gamePanel;068 }069070 @Override071 public void run() {072 Canvas canvas;073 Log.d(TAG, "Starting game loop");074 // initialise timing elements for stat gathering075 initTimingElements();076077 long beginTime; // the time when the cycle begun078 long timeDiff; // the time it took for the cycle to execute079 int sleepTime; // ms to sleep (<0 if we're behind)080 int framesSkipped; // number of frames being skipped

Page 55: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

081082 sleepTime = 0;083084 while (running) {085 canvas = null;086 // try locking the canvas for exclusive pixel editing087 // in the surface088 try {089 canvas = this.surfaceHolder.lockCanvas();090 synchronized (surfaceHolder) {091 beginTime = System.currentTimeMillis();092 framesSkipped = 0; // resetting the frames skipped093 // update game state094 this.gamePanel.update();095 // render state to the screen096 // draws the canvas on the panel097 this.gamePanel.render(canvas);098 // calculate how long did the cycle take099 timeDiff = System.currentTimeMillis() - beginTime;100 // calculate sleep time101 sleepTime = (int)(FRAME_PERIOD - timeDiff);102103 if (sleepTime > 0) {104 // if sleepTime > 0 we're OK105 try {106 // send the thread to sleep for a short period107 // very useful for battery saving108 Thread.sleep(sleepTime);109 } catch (InterruptedException e) {}110 }111112 while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {113 // we need to catch up114 this.gamePanel.update(); // update without rendering115 sleepTime += FRAME_PERIOD; // add frame period to check if in next frame116 framesSkipped++;117 }118119 if (framesSkipped > 0) {120 Log.d(TAG, "Skipped:" + framesSkipped);121 }122 // for statistics123 framesSkippedPerStatCycle += framesSkipped;124 // calling the routine to store the gathered statistics125 storeStats();126 }127 } finally {128 // in case of an exception the surface is not left in129 // an inconsistent state

Page 56: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

130 if (canvas != null) {131 surfaceHolder.unlockCanvasAndPost(canvas);132 }133 } // end finally134 }135 }136137 /**138 * The statistics - it is called every cycle, it checks if time since last139 * store is greater than the statistics gathering period (1 sec) and if so140 * it calculates the FPS for the last period and stores it.141 *142 * It tracks the number of frames per period. The number of frames since143 * the start of the period are summed up and the calculation takes part144 * only if the next period and the frame count is reset to 0.145 */146 private void storeStats() {147 frameCountPerStatCycle++;148 totalFrameCount++;149150 // check the actual time151statusIntervalTimer += (System.currentTimeMillis() - statusIntervalTimer);152153 if (statusIntervalTimer >= lastStatusStore + STAT_INTERVAL) {154 // calculate the actual frames pers status check interval155

double actualFps = (double)(frameCountPerStatCycle / (STAT_INTERVAL / 1000));

156157 //stores the latest fps in the array158 fpsStore[(int) statsCount % FPS_HISTORY_NR] = actualFps;159160 // increase the number of times statistics was calculated161 statsCount++;162163 double totalFps = 0.0;164 // sum up the stored fps values165 for (int i = 0; i < FPS_HISTORY_NR; i++) {166 totalFps += fpsStore[i];167 }168169 // obtain the average170 if (statsCount < FPS_HISTORY_NR) {171 // in case of the first 10 triggers172 averageFps = totalFps / statsCount;173 } else {174 averageFps = totalFps / FPS_HISTORY_NR;175 }176 // saving the number of total frames skipped

Page 57: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

177 totalFramesSkipped += framesSkippedPerStatCycle;178 // resetting the counters after a status record (1 sec)179 framesSkippedPerStatCycle = 0;180 statusIntervalTimer = 0;181 frameCountPerStatCycle = 0;182183 statusIntervalTimer = System.currentTimeMillis();184 lastStatusStore = statusIntervalTimer;185 // Log.d(TAG, "Average FPS:" + df.format(averageFps));186 gamePanel.setAvgFps("FPS: " + df.format(averageFps));187 }188 }189190 private void initTimingElements() {191 // initialise timing elements192 fpsStore = new double[FPS_HISTORY_NR];193 for (int i = 0; i < FPS_HISTORY_NR; i++) {194 fpsStore[i] = 0.0;195

}

196

Log.d(TAG + ".initTimingElements()", "Timing elements for stats initialised");

197 }198199 }

I introduced a simple measuring function. I count the number of frames every second and store them in the fpsStore[] array. The storeStats() is called every tick and if the 1 second interval (STAT_INTERVAL = 1000;) is not reached then it simply adds the number of frames to the existing count.If the one second is hit then it takes the number of rendered frames and adds them to the array of FPSs. After this I just reset the counters for the current statistics cycle and add the results to a global counter. The average is calculated on the values stored in the last 10 seconds.Line 171 logs the FPS every second while line 172 sets the avgFps value of the gamePanel instance to be displayed on the screen.

The MainGamePanel.java class’s render method contains the the displayFps call which just draws the text onto the top right corner of the display every time the state is rendered. It also has a private member that is set from the thread.

view source

print?

01 // the fps to be displayed02 private String avgFps;03 public void setAvgFps(String avgFps) {04 this.avgFps = avgFps;

Page 58: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

05 }0607 public void render(Canvas canvas) {08 canvas.drawColor(Color.BLACK);09 droid.draw(canvas);10 // display fps11 displayFps(canvas, avgFps);12 }1314 private void displayFps(Canvas canvas, String fps) {15 if (canvas != null && fps != null) {16 Paint paint = new Paint();17 paint.setARGB(255, 255, 255, 255);18 canvas.drawText(fps, this.getWidth() - 50, 20, paint);19 }20 }

Try running it. You should have the FPS displayed in the top right corner.

FPS displayed

Reference: Measuring FPS from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

9

Android Game Development – Sprite AnimationPublished on July 23, 2011 | 35,341 views | Filed in: Android Games

If you followed the series so far we are pretty knowledgable in handling touches, displaying images and moving them around.

Page 59: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

But a moving image it’s a pretty dull sight as it looks really fake and amateurish. To give the characters some life we will need to do more than that. That is what animation is all about. A rock is an inanimate object and even if it is thrown, it doesn’t change its shape. A human on the other hand, is very animated. Try throwing one and you’ll see twitching limbs and even screams in the air.

Let’s just resort to examining walking which is pretty complex in its own. Imagine a human crossing your way (just in 2D). You’ll notice different displays of the body. Left foot in front, right hand in front while the oposite limbs are behind. This slowly changes so the left foot remains behind while the right progresses along with the body. But at one point the cycle repeats.If you don’t close your eyes you see the person progressing smoothly. If you close your eyes and keep them closed for a bit and open them again the person already went on and is in a different position. Try blinking quite rapidly and you will see something like the old black and white comedies. That is low frame rate. More on FPS here.

Actually we do want a low frame rate walking for this tutorial, just like this.

The walking presented above is a bit dodgy but it’s a ripped off version of the sprites from Monkey Island. She’s Elaine Marley.This is called a Sprite. It is a simple 2 dimensional image or animation.To be able to re-create the above animation, we need every frame from the walking cycle.

It is a 150 pixels wide image and each frame is 30 pixels wide.To illustrate it better check the following image.

To get the above animation in android (or iPhone or in any other program for that matter), we need to load up each frame as a separate image and display them at regular intervals one after each other. OR we can load up the big image containing all the frames and use the methods provided by android do slice and dice them on the fly and to display only the relevant frame.To do that is trivial. We know that we have 5 frames and each frame is 30 pixels wide. We definea rectangle (that will be our selection) which has the width of one frame and the height of the image.The following image shows how I cut out the first two frames. The rest you should fill in.

Page 60: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Knowing all this let’s go create the project. We will use the knowledge from some previous chapters, most notably about the game loop and the one about the image display (here we set up the thread that triggers the drawing of the graphics item every frame).

We will need an object to animate. We use Elaine from Monkey Island so I will the class ElaineAnimated.java.

view source

print?

01 public class ElaineAnimated {0203 private static final String TAG = ElaineAnimated.class.getSimpleName();0405

private Bitmap bitmap; // the animation sequence

06

private Rect sourceRect; // the rectangle to be drawn from the animation bitmap

07 private int frameNr; // number of frames in animation08 private int currentFrame; // the current frame09 private long frameTicker; // the time of the last frame update10 private int framePeriod; // milliseconds between each frame (1000/fps)1112

private int spriteWidth; // the width of the sprite to calculate the cut outrectangle

13 private int spriteHeight; // the height of the sprite1415 private int x; // the X coordinate of the object (top left of the image)16 private int y; // the Y coordinate of the object (top left of the image)1718 }

The private attributes are commented but worth mentioning a few.

bitmap is the png file containing all the frames. The second image in this article.

sourceRect is the selection rectangle. It is the blue window in the image above. The rectangle moves every frame onto the next.

Page 61: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

frameTicker this is the java timestamp of the last frame change in the walking sequence. Note that this is not the game FPS but the walking FPS. If we want Elaine to perform a complete walk cycle in a second we set the frame rate for walking to 5 because we have 5frames. To get a really smooth animation we need 30 frames but it’s not the point now.

framePeriod is time in milliseconds that represents the period of time a frame is being displayed. If the cycle completes in 1 second that means for 5 frames the period will be 0.2 seconds. That is, each frame will be displayed for 0.2 seconds.

The constructor is as follows:

view source

print?

01

public ElaineAnimated(Bitmap bitmap, int x, int y, int width, int height, int fps, int frameCount) {

02

this.bitmap = bitmap;

03 this.x = x;04 this.y = y;05 currentFrame = 0;06 frameNr = frameCount;07 spriteWidth = bitmap.getWidth() / frameCount;08 spriteHeight = bitmap.getHeight();09 sourceRect = new Rect(0, 0, spriteWidth, spriteHeight);10 framePeriod = 1000 / fps;11 frameTicker = 0l;12 }

I’m assuming that the frames are the same width so I calculate the width of the rectangle by dividing the width of the image with the number of frames. I also pass in the fps which is again, the frames per second of the walk cycle not the game FPS.

Elaine will have an update method of her own as she is an animated object and she needs to lookgood and she is in charge of dragging her feet. Because the period of the game update cycle and Elaine’s one might be (in this case is) different we pass the actual game time as a variable so we know when we need to display the next frame.For example the game runs very fast and the update is called every 20 milliseconds and we need to update the frame every 200ms, then the progression of the frame will happen at every 10th game update.

Here’s the code:

view source

print?

Page 62: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

01 public void update(long gameTime) {02 if (gameTime > frameTicker + framePeriod) {03 frameTicker = gameTime;04 // increment the frame05 currentFrame++;06 if (currentFrame >= frameNr) {07 currentFrame = 0;08 }09 }10 // define the rectangle to cut out sprite11 this.sourceRect.left = currentFrame * spriteWidth;12 this.sourceRect.right = this.sourceRect.left + spriteWidth;13 }

The update is called from the main game panel (check previous entries how that works). This is the update method of the MainGamePanel class.

view source

print?

1 public void update() {2 elaine.update(System.currentTimeMillis());3 }

The update method is simple (Elaine’s). It increments the frame if the passed in time (which is the system time when the update method was called) is greater than the last time (frameTicker) the frame was updated plus the period of the next update.If the next frame is beyond the last, we reset the cycle.

After all that area from which the image will be cut out is defined as the sourceRect.That’s it. Now let’s go on to display it.

view source

print?

1 public void draw(Canvas canvas) {2 // where to draw the sprite

3Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);

4canvas.drawBitmap(bitmap, sourceRect, destRect, null);5 }

That is all. We set the destination rectangle as to where to draw the cut out image. It is at Elaine’sposition (X and Y set in the constructor).

view source

Page 63: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

1 canvas.drawBitmap(bitmap, sourceRect, destRect, null);

tells android to cut out the image defined by sourceRect from the image contained in bitmap anddraw it into the rectangle on the canvas defined by destRect.

The draw is called from the game panel’s render method triggered by the game loop (check previous entries).

The MainGamePanel.java differs slightly from the one from previous chapters. I got rid of all the droidz and added just Elaine.

view source

print?

01 private ElaineAnimated elaine;0203 public MainGamePanel(Context context) {04 //* ... removed ... */0506 // create Elaine and load bitmap07 elaine = new ElaineAnimated(08 BitmapFactory.decodeResource(getResources(), R.drawable.walk_elaine)09 , 10, 50 // initial position10 , 30, 47 // width and height of sprite11 , 5, 5); // FPS and number of frames in the animation1213 // create the game loop thread14 thread = new MainThread(getHolder(), this);1516 //* ... removed ... */17 }

Elaine is instantiated in the panel’s constructor and is given an initial positon of (X=10, Y=50). I pass in the width and the height of the sprite too but that is ignored anyway, but you can modify the code.The FPS is very important and the number of frames too. FPS says how many frames are to be shown in one second. The last parameter is the number of frames in the cycle.

The thread and activity classes haven’t changed at all. You can find them in the download as theyare quite long to be pasted. The image is named walk_elaine.png and it was copied to /res/drawable-mdpi/ so android can pick it up automatically.

If you run the application you should be seeing Elaine performing walking cycles in one place. We should have used jumping as that can be performed in one place but you get the idea.

Page 64: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Elaine Walking

Enhancement

To make some neat additions modify Elaine’s draw method so it displays the original image containing the sprites from which the frames are extracted.

view source

print?

1 public void draw(Canvas canvas) {2 // where to draw the sprite

3Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);

4canvas.drawBitmap(bitmap, sourceRect, destRect, null);5 canvas.drawBitmap(bitmap, 20, 150, null);6 Paint paint = new Paint();7paint.setARGB(50, 0, 255, 0);

8canvas.drawRect(20 + (currentFrame * destRect.width()), 150, 20 + (currentFrame * destRect.width()) + destRect.width(), 150 + destRect.height(), paint);

9 }

This just displays the image at (20, 150) and creates a new paint object so we can paint over the current frame on the original image.The method setARGB creates a semi-transparent green paint. The first value is 50 which means it’s 75% transparent. 0 is completely transparent while 255 is fully opaque.After everything was drawn we paint a rectangle of the size of a frame onto the original image soyou see which frame is being displayed in the motion.

Page 65: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Walking with Current Frame Painted

That’s it. Run it and you have your first sprite animation.

Download the source code here (animation_walk.tar.gz)

Reference: Sprite Animation with Android from our JCG partner Tamas Jano from “Against TheGrain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

10

Android Game Development – Particle ExplosionPublished on August 2, 2011 | 19,264 views | Filed in: Android Games

Ever wondered how explosions are created? Let’s take a little detour and try to implement a basicparticle explosion.

An explosion is nothing more than a bunch of particles (be them pixels, small shapes or images) scattered across the screen, originating from a single point. Not all the time but mostly and for the sake of simplicity we’ll assume that all particles originate from a single point.

Just think of fireworks. A tiny little rocket shoots up and explodes into hundreds of sparkling little stars that fade out as they fall down. What happens is that a huge force in the center of the rocket rips the body apart (thus creating particles) and scatters them randomly around the point of explosion.

To make it simple we’ll create a few particles, we will place them in one place (the origin) and give them random forces. A force is a vector quantity. It means that it has magnitude and

Page 66: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

direction. The magnitude will determine its speed and its direction will tell the particle which way to go.

The Particle

The class file:

view source

print?

01 public class Particle {0203 public static final int STATE_ALIVE = 0; // particle is alive04 public static final int STATE_DEAD = 1; // particle is dead0506 public static final int DEFAULT_LIFETIME = 200; // play with this07 public static final int MAX_DIMENSION = 5; // the maximum width or height08 public static final int MAX_SPEED = 10; // maximum speed (per update)0910 private int state; // particle is alive or dead11 private float width; // width of the particle12 private float height; // height of the particle13 private float x, y; // horizontal and vertical position14 private double xv, yv; // vertical and horizontal velocity15 private int age; // current age of the particle16 private int lifetime; // particle dies when it reaches this value17 private int color; // the color of the particle18 private Paint paint; // internal use to avoid instantiation19 }

Page 67: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The particle is nothing more than a little rectangle (this can be an image, circle or any other shape, but in our case we use a rectangle) with a few properties.

It has a state. This indicates whether the particle is alive or dead. A particle is alive when its color is not black (it hasn’t faded) and its age hasn’t reached its lifetime. More on this a bit later.

It has a position. It’s position in a 2D coordinate system is represented by 2 points: x and y.

It also has a speed and a direction. As you recall speed is a vector so it has 2 components in 2D. In 3D it will also have the z component but we stay in 2D for now. To keep it simple now we addtwo properties for this. vx and vy

The age of the particle is it’s 0 in the beginning and is incremented at each update.

The lifetime is the maximum age a particle can reach before it dies.

The rest are color and paint. These are for drawing only.

If you recall the previous entries, the game update is nothing more than calling the update methods of every entities in the game and displaying them. The update method of the particle is pretty simple.

But first we need to create the particle:

view source

print?

01 public Particle(int x, int y) {02 this.x = x;03 this.y = y;04 this.state = Particle.STATE_ALIVE;05 this.widht = rndInt(1, MAX_DIMENSION);06 this.height = this.widht;07 this.lifetime = DEFAULT_LIFETIME;08 this.age = 0;09 this.xv = (rndDbl(0, MAX_SPEED * 2) - MAX_SPEED);10 this.yv = (rndDbl(0, MAX_SPEED * 2) - MAX_SPEED);11 // smoothing out the diagonal speed12 if (xv * xv + yv * yv > MAX_SPEED * MAX_SPEED) {13 xv *= 0.7;14 yv *= 0.7;15

}

16

this.color = Color.argb(255, rndInt(0, 255), rndInt(0, 255), rndInt(0, 255));

17 this.paint = new Paint(this.color);18 }

Page 68: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Check the creation of a particle and it should be straight forward.

You will notice that a particle is created at position x,y.

The state is set to alive.We want to randomise the size of the rectangles because an explosion creates particles in different sizes and shapes but we’ll just randomise the size and colour.I have written a few helper methods that give me random numbers, for this check the complete source code.

Next the lifetime is set. Every particle will have the same lifetime.

The age is 0 of course as the particle has just been born.

Next is the interesting bit. It’s very amateurish. To set the speed I have used 2 random numbers for the 2 components of the speed vector (vx and vy). The smoothing is needed because if both components are near the maximum value then the resulting magnitude will be over the max speed. You could use simple trigonometric functions with a random degree instead of this.

The las thing to set is the color which again is randomised.

There you have it.

The update() method for the particle.

view source

print?

01 public void update() {02 if (this.state != STATE_DEAD) {03 this.x += this.xv;04 this.y += this.yv;0506 // extract alpha07 int a = this.color >>> 24;08 a -= 2; // fade by 209 if (a <= 0) { // if reached transparency kill the particle10 this.state = STATE_DEAD;11 } else {12 this.color = (this.color & 0x00ffffff) + (a << 24); // set the new alpha13 this.paint.setAlpha(a);14 this.age++; // increase the age of the particle15 }16 if (this.age >= this.lifetime) { // reached the end if its life17 this.state = STATE_DEAD;18 }19 }

Page 69: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

20 }

It’s pretty simple. Every update, the position is set according to the speed and the alpha component of the particle’s color is decremented. In other words the particle is being faded.

If the age exceeded the lifetime or the opacity is 0 (that means that it is completely transparent) the particle is declared dead.

If you wonder about the magic with colours, it is quite simple once you get the bitwise operators.Don’t worry, I’m rubbish as well, just make sure you know where to look. Here is a good explanation of colour components and how to use bitwise operators to manipulate them: http://lab.polygonal.de/2007/05/10/bitwise-gems-fast-integer-math/. It’s faster than using the objects but you can safely use the android methods too.

Just as a side note on coloursYou can specify colours in Android as an int. If you’re familiar with rgb and argb that is great.rgb is 24 bits color while argb is 32 bits. It also has the alpha component which is transparency/opacity.

Opacity values: 0 = transparent, 255 = completely opaque.

To represent an int in hex you just prefix it with 0x. A color in hex is simple: 0x00FF00 is green for example. The pattern is: 0xRRGGBB (Red, Green, Blue). Now to add the alpha you will addit to the beginning. 0xAARRGGBB.Because it is in hex, the values are between 00 and FF. 0 being 0 and FF being 255 in decimal.When you create a colour out of components like color(a, r, g, b) (for example: new Color(125, 255, 0, 0) creates a semi transparent red), you can simply create it with an integer expressed in hex like this: new Color(0x80FF0000);

This is how you would extract the components of an argb colour.

view source

print?

1 int color = 0xff336699;2 int alpha = color >>> 24;3 int red = color >>> 16 & 0xFF;4 int green = color >>> 8 & 0xFF;5 int blue = color & 0xFF;

The draw() method is simple again.

view source

print?

Page 70: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

1 public void draw(Canvas canvas) {2 paint.setColor(this.color);

3canvas.drawRect(this.x, this.y, this.x + this.widht, this.y + this.height, paint);

4}

At this stage try to create some particles in your game panel and see what happens.

The Explosion

The explosion is nothing more than hundreds of particles originating from one place, the origin.

In the image above you see the first 4 updates of a simple explosion. All the particles have the same speed but they spread out in different directions. Each circle is one update.

The main properties of an explosion are:

view source

print?

01 public class Explosion {0203 public static final int STATE_ALIVE = 0; // at least 1 particle is alive04 public static final int STATE_DEAD = 1; // all particles are dead0506 private Particle[] particles; // particles in the explosion07 private int x, y; // the explosion's origin08 private int size; // number of particles09 private int state; // whether it's still active or not10 }

Page 71: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

It contains an array of particles. The size is the number of particles. An explosion is alive if it hasat least one particle alive.

The update is extremely simple. It iterates through all the particles and calls the update() method on each particle. The draw() ditto.

In our application we will create explosions on the screen where we touch it.The constructor is very simple:

view source

print?

01 public Explosion(int particleNr, int x, int y) {02 Log.d(TAG, "Explosion created at " + x + "," + y);03 this.state = STATE_ALIVE;04 this.particles = new Particle[particleNr];05 for (int i = 0; i < this.particles.length; i++) {06 Particle p = new Particle(x, y);07 this.particles[i] = p;08 }09 this.size = particleNr;10 }

The array of particles is being filled at the touch down position.

In our application we will allow up to 10 explosions. So in the MainGamePanel we declare an array of explosions.

view source

print?

1 private Explosion[] explosions;

In the surfaceCreated method we instantiate the array and fill it with null.

view source

print?

1 explosions = new Explosion[10];2 for (int i = 0; i < explosions.length; i++) {3 explosions[i] = null;4 }

The onTouchEvent is where we create explosions.

Page 72: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

view source

print?

01 public boolean onTouchEvent(MotionEvent event) {02 if (event.getAction() == MotionEvent.ACTION_DOWN) {03 // check if explosion is null or if it is still active04 int currentExplosion = 0;05

Explosion explosion = explosions[currentExplosion];

06

while (explosion != null && explosion.isAlive() && currentExplosion < explosions.length) {

07 currentExplosion++;08 explosion = explosions[currentExplosion];09 }10 if (explosion == null || explosion.isDead()) {11

explosion = new Explosion(EXPLOSION_SIZE, (int)event.getX(), (int)event.getY());

12

explosions[currentExplosion] = explosion;

13 }14 }15 return true;16 }

What we do is iterate through the explosions and when we find the first null (this means we never used it for an instance) or the first dead explosion we create a new one at the touch position.

The update and render methods are straight forward. Iterate through the explosions and if they are not null and are alive then call their update and draw methods respectively.

In the final code I added a border for the screen as the wall and added a basic collision detection for the particles so they bounce off the walls. The wall is being transmitted as a reference and theupdate method checks for collision with it. Use it as an exercise and remove the collision and try attaching an image to the particle instead of being a rectangle. To create explosions just click on the screen.

It should look like this:

Page 73: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Explore the code and have fun.

Download it here (android.particles.tgz).

Reference: Particle Explosion with Android from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

11

Android Game Development – Design In-game Entities – The Strategy PatternPublished on August 17, 2011 | 14,982 views | Filed in: Android Games

In this part I will try to explain what I understand on good game design elements. I will use droids in the examples and I will script a basic fight simulator to see how they behave.

The problem:

I command a single robot and I want to obliterate my enemies. To face the same type of enemy all over again is boring. I need new challenges and this means new types of enemies. For example in the first level I want only to practice my target. So I need a pretty dumb enemy that does not do much but takes the shots. After I mastered that skill (shooting a helpless droid), I need a bit of a challenge and I want the enemy droid to fight back, but because I am still a

Page 74: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

beginner I don’t want to die quickly so I need weak droids. After I am over with them I want a tougher challenge. I need better and stronger droids. Not just stronger, but different in behaviour as well as it can get boring killing the same type of enemy over and over again.

The obvious solution:

Create 3 classes for the 3 types of enemy droids. To keep it simple, each droid has 2 abilities: move and attack. It makes sense to create a Droid interface with these two methods and have each droid implement them.

They can move and shoot. Well, not all of them but we can provide an empty implementation forthe ones that do nothing.

The droid types:

Decoy Droid – will have no weapon and can’t move.

Scout Droid – will have a weak weapon and moves fast.

Assault Droid – will have a heavy weapon and moves slowly.

Looking at the 3 types we can implement the following simple class diagram:

The interface has 3 simple methods which the droids need to implement:

view source

print?

01 public interface Droid {0203 // display some info of the droid04 public void display();

Page 75: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

0506 // move the droid07 public void move(int x, int y);0809 // attack position10 public void shoot(int x, int y);11 }

The 3 classes are as follow:

DecoyDroid.java

view source

print?

01 public class DecoyDroid implements Droid {0203 @Override04 public void display() {05 System.out.println("I am a DECOY droid");06 }07 @Override08 public void move(int x, int y) {09 System.out.println("Can't move.");10 }1112 @Override13 public void shoot(int x, int y) {14 System.out.println("Have no weapon.");15 }16 }

ScoutDroid.java

view source

print?

01 public class ScoutDroid implements Droid {0203 private float damage = 0.5f;0405 @Override06 public void display() {07 System.out.println("I am a scout droid");08 }09

Page 76: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

10 @Override11 public void move(int x, int y) {12 System.out.println("Moving QUICKLY to: " + x + "," + y + ".");13 }1415 @Override16 public void shoot(int x, int y) {17 System.out.println("Light Laser Canon targeting: " + x + "," + y18 + ". Damage: " + damage);19 }20 }

AssaultDroid.java

view source

print?

01 public class AssaultDroid implements Droid {0203 private float damage = 2.5f;04 private boolean loaded = true;0506 @Override07 public void display() {08 System.out.println("I am an ASSAULT droid");09 }1011 @Override12 public void move(int x, int y) {13 System.out.println("Moving SLOWLY to: " + x + "," + y + ".");14 }1516 @Override17 public void shoot(int x, int y) {18 if (loaded) {19 System.out.println("Heavy laser targeting: " + x + "," + y20 + ". Damage: " + damage);21 loaded = false;22 } else {23 System.out.println("Reloading...");24 loaded = true;25 }26 }27 }

Both ScoutDroid and AssaultDroid have the argument damage. This holds the value of the damage inflicted by them.

Page 77: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

To give the AssaultDroid a heavy weapon with a slow reload time we added the loaded variable. This way it takes the assault droid two turns to fire its weapon once.

I have created a simple simulator for the droids to take turns to move and shoot.Run the simulator for this design:

BadDroidSimulator.java

view source

print?

01 public class BadDroidSimulator {0203 public static void main(String[] args) {04 // for generating random numbers05 Random rand = new Random();0607 Droid scout = new ScoutDroid();08 Droid assailant = new AssaultDroid();09 Droid decoy = new DecoyDroid();1011 scout.display();12 assailant.display();13 decoy.display();1415 // shoot-out - each droid fires once per turn16 for (int i = 1; i <= 5; i++) {17

System.out.println("\n<=== BEGIN TURN " + i + " ===>");

18

scout.shoot(rand.nextInt(10), rand.nextInt(10)); // we assume this is an enemy position

19 scout.move(rand.nextInt(10), rand.nextInt(10));20 System.out.println();21 assailant.shoot(rand.nextInt(10), rand.nextInt(10));22 assailant.move(rand.nextInt(10), rand.nextInt(10));23 System.out.println();24 decoy.shoot(rand.nextInt(10), rand.nextInt(10));25 decoy.move(rand.nextInt(10), rand.nextInt(10));26 System.out.println("<=== END TURN " + i + " ===>");27 }28 }29 }

The result (console output) will look like this:

view source

Page 78: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

01 I am a scout droid02 I am an ASSAULT droid03 I am a DECOY droid04 <=== BEGIN TURN 1 ===>05 Light Laser Canon targeting: 9,0. Damage: 0.506 Moving QUICKLY to: 4,6.0708 Heavy laser targeting: 6,2. Damage: 2.509 Moving SLOWLY to: 9,1.1011 Have no weapon.12 Can’t move.13 <=== END TURN 1 ===>1415 <=== BEGIN TURN 2 ===>16 Light Laser Canon targeting: 3,4. Damage: 0.517 Moving QUICKLY to: 6,5.1819 Reloading…20 Moving SLOWLY to: 1,6.2122 Have no weapon.23 Can’t move.24 <=== END TURN 2 ===>2526 <=== BEGIN TURN 3 ===>27 Light Laser Canon targeting: 6,7. Damage: 0.528 Moving QUICKLY to: 9,7.2930 Heavy laser targeting: 7,1. Damage: 2.531 Moving SLOWLY to: 2,0.3233 Have no weapon.34 Can’t move.35 <=== END TURN 3 ===>3637 <=== BEGIN TURN 4 ===>38 Light Laser Canon targeting: 3,7. Damage: 0.539 Moving QUICKLY to: 1,4.4041 Reloading…42 Moving SLOWLY to: 5,9.4344 Have no weapon.45 Can’t move.46 <=== END TURN 4 ===>

Page 79: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

4748 <=== BEGIN TURN 5 ===>49 Light Laser Canon targeting: 0,8. Damage: 0.550 Moving QUICKLY to: 3,9.5152 Heavy laser targeting: 1,2. Damage: 2.553 Moving SLOWLY to: 3,2.5455 Have no weapon.56 Can’t move.57 <=== END TURN 5 ===>

Challenges to extend the design

The droids take turns to move and shoot. This is all good, but:

What if you want to create a hybrid droid? A droid that moves as fast as the scout but with a heavy weapon? You will have to create a new class and copy paste the respective methods from the Scout and Assault droid, right?

Also imagine that the shooting mechanism is not that simple and it needs collision detection and so on. For each droid the same redundant code needs to be rewritten.

What if the fire power could be enhanced with power ups?

What if the droid gains self-conscientiousness and finds a weapon to use it instead of the current one?

I am sure you have plenty ideas on how to enhance the gameplay and extend the world but the most obvious solution (described above) seems ill-suited for this. It requires new droid classes to be created and each droid type will implement its methods separately. Many of these methods areidentical. The current design doesn’t allow you to change the droid’s internals at runtime withoutsignificant effort.

Here is one proposed solution: Composition and the Strategy Pattern.

Designing a Droid (properly)

A very simple droid consists of a weapon put on a chassis. The first design consisted of a “is a” type relationship. A ScoutDroid is a generic Droid with some peculiarities.

Composition is based on “has a” relationships. A Droid has a Chassis. A Droid has a Weapon. What type of components a droid has, determines its type.

Page 80: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Let’s decompose the Scout Droid for example.The Scout Droid is a Droid which has a Light Laser Canon has a set of Wheels to move. We want to make the scout move quickly with a light weapon.The Assault Droid on the other hand is a Droid too but it has a Heavy Laser Canon and it runs on Tracks. This makes it extremely powerful but a bit slow.

Think from a factory perspective. How does a car production line work? You get the chassis witha specific place for the engine, wheels, drive-shaft, gear-box and so on.All these components are produced separately. The teams that produce them have no idea of the other parts. They must fulfil one criteria: the gearbox must fit in perfectly in its place and connected up with the engine.. Different makes have different ways of doing this. The connector in this instance is the interface.The engine has a similar story. If it hooks up nicely with the wheels and gearbox then it can be fitted. Its internal design, capacity, power, fuel consumption can be completely different. The engine is one of the car’s components.

So is our droid. But to keep it simple we have only 2 components. We need one generic droid that has all the wirings built so its components will be triggered by the droid through those interfaces. For example a droid needs to only pull the trigger of the weapon and doesn’t care what type of weapon it is as long as it has a trigger. The droid needs to understand the pullTrigger method and to do this it needs to be implemented, in order for us to give weapons to the droid to use.The same thing with the changing of location. It needs to trigger the movement. The wheels or track or anti-gravity propulsion will take the droid there. The droid only needs to set the coordinates.

To fulfil this we need a class with implemented methods instead of an interface.We create the abstract Droid class. We make it abstract because we actually implement the methods that trigger the weapon, and action the moving mechanism but we don’t have concrete weapons and movement mechanisms attached to the droid. The assembly of a concrete droid willbe delegated to the type constructor along with the description method.

view source

print?

01 public abstract class Droid {0203 protected Weapon weapon; // the weapon which will be used in fights04 protected Chassis chassis; // the chassis on which the droid is placed0506 public void moveToPosition(int x, int y) {07 System.out.print(id + " > " );08 chassis.moveTo(x, y);09 }1011 /**

Page 81: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

12 * Engages the position on the screen whether it is occupied by13 * an enemy or not. Each strategy should decide how to do it.14 */15 public void attackPosition(int x, int y) {16 System.out.print(id + " > ");17 weapon.useWeapon(new Vector2f(x, y));18 }1920 /**21 * Displays some info on the droid22 */23 public abstract void display();24 }

If you examine the class you will see that the Droid has 3 methods from which 2 are implemented. It also has two components: Weapon and Chassis.The components are interfaces so the droid does not know what it is doing when triggering the actions on them. It is all delegated to the implementation.

The interfaces are as follows:

Weapon.java

view source

print?

01 public interface Weapon {02 /**03 * The trigger to use the weapon.04 * @param target - where on the map is the target05 */06 public void useWeapon(Vector2f target);0708 /**09 * Returns the description of the weapon10 */11 public String getDescription();12 }

Chassis.java

view source

print?

01 public interface Chassis {02 /**03 * Delegates the movement to the supporting chassis and

Page 82: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

04 * tries to move the unit to x,y05 */06 public void moveTo(int x, int y);0708 /**09 * Returns the description of the chassis10 */11 public String getDescription();12 }

We will enhance our base Droid class. We will add setter and getter methods for both Weapon and Chassis. This will allow us to change the droid’s behaviour at runtime. This is what the strategy pattern is all about. A Droid has behaviours: it can use a weapon and it can move. These two strategies (behaviours) need to be implemented.

We also add an id which will be unique in our game for each droid instance. I use a very simple id generation strategy. I increment the nextId static field and append it to the concrete droid type prefix in the constructor for each type.

Here is the new Droid class:

view source

print?

01 public abstract class Droid {0203 protected static int nextId = 0; // the next available ID0405 protected String id; // unique id06 protected Weapon weapon; // the weapon which will be used in fights07 protected Chassis chassis; // the chassis on which the droid is placed0809 // the unique ID of the droid in the game10 public String getId() {11 return id;12 }1314 public Weapon getWeapon() {15 return weapon;16 }17 public void setWeapon(Weapon weapon) {18 this.weapon = weapon;19 }2021 public Chassis getChassis() {22 return chassis;23 }

Page 83: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

24 public void setChassis(Chassis chassis) {25 this.chassis = chassis;26 }2728 public void moveToPosition(int x, int y) {29 System.out.print(id + " > " );30 chassis.moveTo(x, y);31 }3233 /**34 * Engages the position on the screen whether it is occupied by35 * an enemy or not. Each strategy should decide how to do it.36 */37 public void attackPosition(int x, int y) {38 System.out.print(id + " > ");39 weapon.useWeapon(new Vector2f(x, y));40 }4142 /**43 * Displays some info on the droid44 */45 public abstract void display();46 }

Let’s build some weapons

NoWeapon.java

view source

print?

01/**02* This is a null object. A null object is a dummy that does nothing and it03 * is a mere place-holder and eliminates the need to check for null.04 * @author impaler05 *06 */07 public class NoWeapon implements Weapon {0809 @Override10 public void useWeapon(Vector2f target) {11 // We are doing nothing12 System.out.println("No weapon equipped!");13 }1415 @Override16 public String getDescription() {

Page 84: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

17 return "Nothing";18 }19 }

This is the null object. The class description should give you an idea what it is.

LightLaserCanon.java

view source

print?

01 /**02 * This is a light laser cannon whit a quick reload time and high accuracy03 *04 * @author impaler05 *06 */07 public class LightLaserCanon implements Weapon {0809 private float damage = 0.5f; // the damage inflicted1011 @Override12 public void useWeapon(Vector2f target) {13System.out.println("Shooting my laser canon to " + (int)target.getX() + ","14+ (int)target.getY() + ". Bang on! Done " + damage + " damage.");15 }1617 @Override18 public String getDescription() {19 return "First generation laser canon. Street use only!";20 }21 }

HeavyLaserCanon.java

view source

print?

01

/**

02

* This is a heavy assault laser cannon with high accuracy but slow reload time.

03 * @author impaler04 */05 public class HeavyLaserCanon implements Weapon {0607 private boolean loaded = true; // after fire needs to be reloaded

Page 85: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

08 private float damage = 1.5f; // the damage is considerable0910 @Override11 public void useWeapon(Vector2f target) {12 if (loaded) {13

// we fire the canon

14

System.out.println("Eat this! Laser beam hit target (" + (int)target.getX() + "," + (int)target.getY() + ") and dealt " + damage + " damage.");

15 // next time needs reloading16 loaded = false;17 } else {18 System.out.println("Darn! Out of ammo! Reloading...");19 loaded = true;20 }21 }2223 @Override24 public String getDescription() {25

return "DASS-5000 - The ultimate in siege weaponry provided by Obviam Enterprises.";

26

}

27 }

You might notice the Vector2f class. This is a very basic 2D vector class which currently holds the x and y coordinates. Nothing more. You can find it in the downloaded source.

Let’s build some chassis

The getDescription() method says what the chassis is like.

NoChassis.java – null object (see weapons)

view source

print?

01 public class NoChassis implements Chassis {0203 @Override04 public void moveTo(int x, int y) {05 System.out.println("It's just a frame. Can't move.");06 }0708 @Override09 public String getDescription() {10 return "It's just a frame.";

Page 86: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

11 }12 }

SteelStand.java

view source

print?

01 public class SteelStand implements Chassis {0203 @Override04 public void moveTo(int x, int y) {05 System.out.println("Can't move.");06 }0708 @Override09

public String getDescription() {

10

return "Unmovable reinforced steel stand ideal for turrets and defensive units.";

11 }12 }

Wheels.java

view source

print?

01 public class Wheels implements Chassis {0203 @Override04 public void moveTo(int x, int y) {05 System.out.println("Speeding to " + x + "," + y + " on my wheels!");06 }0708 @Override09

public String getDescription() {

10

return "4 wheel drive, very fast on flat terrain but struggling through obstacles.";

11 }12 }

Track.java

view source

Page 87: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

01 public class Track implements Chassis {0203 @Override04 public void moveTo(int x, int y) {05

System.out.println("Don't get in my way! Moving slowly to: " + x + "," + y +".");

06

}

0708 @Override09 public String getDescription() {10 return "Slow moving tracks but able to go through many obstacles.";11 }12 }

Now we can assemble our droids

First let’s create a DecoyDroid. This droid will have no weapon and will be placed on a steel stand. It’s for our target practice, remember?

DecoyDroid.java

view source

print?

01 public class DecoyDroid extends Droid {0203 public DecoyDroid() {04 id = "DCY-" + (++Droid.nextId);05 weapon = new NoWeapon();06 chassis = new SteelStand();07 }0809 @Override10 public void display() {11

System.out.println("+--------------------------------------------------------------------------------------------+");

12

System.out.println("| I am a DECOY droid.");

13 System.out.println("|\tID: " + id);14 System.out.println("|\tWeapon: " + weapon.getDescription());15

System.out.println("|\tChassis: " + chassis.getDescription());

16

System.out.println("+--------------------------------------------------------------------------------------------+");

17 }

Page 88: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

18 }

Examine the default constructor. It creates an id and assigns an instance of NoWeapon and SteelStand to the droid.The display() method is more elaborate than before but just to describe the droid better. It makes use of the components’ descriptions too.If you instantiate a DecoyDroid and call its display method you will get a nice description of it.

view source

print?

1 +——————————————————————————————–+2 | I am a DECOY droid.3 | ID: DCY-34 | Weapon: Nothing

5| Chassis: Unmovable reinforced steel stand ideal for turrets and defensive units.

6+——————————————————————————————–+

Let’s build the rest of the types:

ScoutDroid.java

view source

print?

01 public class ScoutDroid extends Droid {0203 public ScoutDroid() {04 id = "SCT-" + (++Droid.nextId);05 weapon = new LightLaserCanon();06 chassis = new Wheels();07 }0809 @Override10 public void display() {11

System.out.println("+--------------------------------------------------------------------------------------------+");

12

System.out.println("| I am a SCOUT droid.");

13 System.out.println("|\tID: " + id);14 System.out.println("|\tWeapon: " + weapon.getDescription());15

System.out.println("|\tChassis: " + chassis.getDescription());

16

System.out.println("+--------------------------------------------------------------------------------------------+");

17 }

Page 89: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

18 }

AssaultDroid.java

view source

print?

01 public class AssaultDroid extends Droid {0203 public AssaultDroid() {04 id = "ASS-" + (++Droid.nextId);05 weapon = new HeavyLaserCanon();06 chassis = new Track();07 }0809 @Override10 public void display() {11

System.out.println("+--------------------------------------------------------------------------------------------+");

12

System.out.println("| I am an ASSAULT droid.");

13 System.out.println("|\tID: " + id);14 System.out.println("|\tWeapon: " + weapon.getDescription());15

System.out.println("|\tChassis: " + chassis.getDescription());

16

System.out.println("+--------------------------------------------------------------------------------------------+");

17 }18 }

You will notice that the only things needed to be implemented are the constructor – which adds the chassis and weapon – and the display() method.The following diagram shows the new architecture:

Page 90: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Let’s create a test script for it. We’ll simulate 5 turns in which each droid will use its weapon andmove to a random location. Check the behaviour of each weapon and you will notice that the heavy laser will fire once every 2 turns. To make it interesting, in turn 4 we give a HeavyLaserCanon to DecoyDroid. Look at how it changes the droid’s behaviour and it starts firing. This is a hybrid droid created on the fly at runtime.

The simulator code (DroidSimulator.java):

view source

print?

01 public class DroidSimulator {0203 public static void main(String[] args) {04 // for generating random numbers05 Random rand = new Random();0607 Droid scout = new ScoutDroid();08 Droid assailant = new AssaultDroid();09 Droid decoy = new DecoyDroid();1011 scout.display();12 assailant.display();13 decoy.display();1415 // shoot-out - each droid fires once per turn16 for (int i = 1; i <= 5; i++) {17 System.out.println("\n<=== BEGIN TURN " + i + " ===>");18 // in turn 3 decoy droid is given an assault canon19 if (i == 4) {20 decoy.setWeapon(new HeavyLaserCanon());21

System.out.println("* " + decoy.getId() + " acquired " + decoy.getWeapon().getDescription() + "\n");

22

}

23

scout.attackPosition(rand.nextInt(10), rand.nextInt(10)); // we assume thisis an enemy position

24

scout.moveToPosition(rand.nextInt(10), rand.nextInt(10));

25 System.out.println();26 assailant.attackPosition(rand.nextInt(10), rand.nextInt(10));27 assailant.moveToPosition(rand.nextInt(10), rand.nextInt(10));28 System.out.println();29 decoy.attackPosition(rand.nextInt(10), rand.nextInt(10));30 decoy.moveToPosition(rand.nextInt(10), rand.nextInt(10));31 System.out.println("<=== END TURN " + i + " ===>");32 }33 }

Page 91: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

34 }

The output:

view source

print?

01 +——————————————————————————————–+02 | I am a SCOUT droid.03 | ID: SCT-104 | Weapon: First generation laser canon. Street use only!05

| Chassis: 4 wheel drive, very fast on flat terrain but struggling through obstacles.

06

+——————————————————————————————–+

07 +——————————————————————————————–+08 | I am an ASSAULT droid.09

| ID: ASS-2

10

| Weapon: DASS-5000 – The ultimate in siege weaponry provided by Obviam Enterprises.

11 | Chassis: Slow moving tracks but able to go through many obstacles.12 +——————————————————————————————–+13 +——————————————————————————————–+14 | I am a DECOY droid.15 | ID: DCY-316 | Weapon: Nothing17

| Chassis: Unmovable reinforced steel stand ideal for turrets and defensive units.

18

+——————————————————————————————–+

19 <=== BEGIN TURN 1 ===>20 SCT-1 > Shooting my laser canon to 0,3. Bang on! Done 0.5 damage.21 SCT-1 > Speeding to 0,2 on my wheels!2223 ASS-2 > Eat this! Laser beam hit target (3,4) and dealt 1.5 damage.24 ASS-2 > Don’t get in my way! Moving slowly to: 3,8.2526 DCY-3 > No weapon equipped!27 DCY-3 > Can’t move.28 <=== END TURN 1 ===>2930 <=== BEGIN TURN 2 ===>31 SCT-1 > Shooting my laser canon to 4,0. Bang on! Done 0.5 damage.32 SCT-1 > Speeding to 5,0 on my wheels!3334 ASS-2 > Darn! Out of ammo! Reloading…35 ASS-2 > Don’t get in my way! Moving slowly to: 1,6.

Page 92: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

3637 DCY-3 > No weapon equipped!38 DCY-3 > Can’t move.39 <=== END TURN 2 ===>4041 <=== BEGIN TURN 3 ===>42 SCT-1 > Shooting my laser canon to 3,0. Bang on! Done 0.5 damage.43 SCT-1 > Speeding to 0,6 on my wheels!4445 ASS-2 > Eat this! Laser beam hit target (9,1) and dealt 1.5 damage.46 ASS-2 > Don’t get in my way! Moving slowly to: 8,0.4748 DCY-3 > No weapon equipped!49 DCY-3 > Can’t move.50 <=== END TURN 3 ===>5152 <=== BEGIN TURN 4 ===>53

* DCY-3 acquired DASS-5000 – The ultimate in siege weaponry provided by Obviam Enterprises.

5455 SCT-1 > Shooting my laser canon to 8,6. Bang on! Done 0.5 damage.56 SCT-1 > Speeding to 2,3 on my wheels!5758 ASS-2 > Darn! Out of ammo! Reloading…59 ASS-2 > Don’t get in my way! Moving slowly to: 0,6.6061 DCY-3 > Eat this! Laser beam hit target (9,4) and dealt 1.5 damage.62 DCY-3 > Can’t move.63 <=== END TURN 4 ===>6465 <=== BEGIN TURN 5 ===>66 SCT-1 > Shooting my laser canon to 1,7. Bang on! Done 0.5 damage.67 SCT-1 > Speeding to 1,9 on my wheels!6869 ASS-2 > Eat this! Laser beam hit target (1,4) and dealt 1.5 damage.70 ASS-2 > Don’t get in my way! Moving slowly to: 3,6.7172 DCY-3 > Darn! Out of ammo! Reloading…73 DCY-3 > Can’t move.74 <=== END TURN 5 ===>

Note in turn 4 how DecoyDroid got the new weapon and changed its behaviour (the yellow line).Now you should understand the null object pattern as well.

As it stands now, it is easy to create new weapons, chassis and droids by keeping the code to a minimum. Always favour composition over inheritance in these situations. You can create a very elaborate droid, with shields, sensors, an array of weapons and also an AI component which

Page 93: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

decides what weapons to use according to the situation. If you have noticed, I used the term “use” instead of fire, because a weapon can be a melee one too and not necessarily a ranged weapon.

The downloadable project contains only the strategy pattern implementation. The simple inheritance approach is left out. Play with it and get the grips of this useful pattern as I will use it extensively and it is considered good design. It is a simple Java application, it is not Android enabled.

Dowload the source here (obviam.compositions.part1.tgz).

In the following parts I’ll try to add some AI capabilities and how to compose the final droid from images of its components.

Reference: Design In-game Entities. Object Composition Strategies. Part 1 – The Strategy Pattern from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

12

Android Game Development – Using Bitmap FontsPublished on September 12, 2011 | 11,215 views | Filed in: Android Games

Android is an OS running on many types of devices with different screen sizes. Because of that itis pretty difficult to address font related issues regarding both size and appearance on these platforms.To use a consistent font face across devices I have used bitmap fonts. That is, each character is represented by a bitmap.

We can create an image for each letter in the alphabet and number for example and whenever we want to display a text, we draw the images of the characters from the string at the given position.But wait! Isn’t loading an image for every character overkill? Yes it is. We can use android’s utilities for manipulating bitmaps to our advantage.

All we need is a bitmap containing all the characters we want to use and slice it up into individual bitmaps. To do this the easy way we will use a monospaced font. A monospaced font is a font whose letters and characters occupy the same horizontal space. In other words, the characters have the same width.

A simple character map can look like this.

Page 94: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Note that the background is transparent.The above character map is arranged in a grid. The width of a character is 8 pixels. The height is 12 pixels. Note that the second row starts at 15 pixels so there is a gap between the rows. It’s justa choice and also how Photoshop broke the lines and I didn’t bother to change them.

The above image shows the beginning of the first row and how the characters are organised into cells.Following this it is easy to slice it up. A simple for iteration will do the trick. To keep things simple I have created a map of only the English alphabet, digits and a few punctuation marks. You can extend it as you wish. Use a monospaced font in Photoshop or Gimp or whatever image editor you fancy and create your own sheet.Here are plenty of bitmap fonts to choose from.

How can we use this? My idea to display text onto the screen is to create a drawString method that takes the text to be displayed as a parameter along with the position where we want to display it.

Something like this will do it:

view source

print?

1 void drawString(Canvas canvas, String text, int x, int y)

I also pass the canvas object in, onto which I want to draw the text. This is just for simplicity. In case of an OpenGL renderer we will have to use billboards (squares with textures). But for the purpose of slicing images and displaying fonts let’s stick with this approach.

Create a simple Android project that use simple 2D canvas. We will draw onto that.I implemented the SurfaceView to hold my canvas and called it DrawingPanel.In its constructor I simply register it to receive events when touching the surface and load the resources. The resources are in fact just the images of the glyphs/characters.

Page 95: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Download the following image file and drag it into your eclipse’s projects resource folder under:/res/drawable-mdpi for ADP to generate the id for the resource.

Create the DrawingPanel class.

view source

print?

01

public class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {

0203 private Canvas canvas; // the canvas to draw on04 private Glyphs glyphs; // the glyphs0506 public DrawingPanel(Context context) {07 super(context);08 // adding the panel to handle events09 getHolder().addCallback(this);1011 // initialise resources12 loadResources();1314 // making the Panel focusable so it can handle events15 setFocusable(true);16 }1718 /** Loads the images of the glyphs */19

private void loadResources() {

20

this.glyphs = new Glyphs(BitmapFactory.decodeResource(getResources(), R.drawable.glyphs_green));

21 Log.d(TAG, "Green glyphs loaded");22 }

I omitted the other methods that need to be implemented as they are just stubs.

The canvas variable is used to draw the text onto and is obtained at every touch event. You’ll seelater in the onTouchEvent method.The most interesting class is the Glyphs class which holds the association of characters with images. The glyphs variable is instantiated in the loadResources() method. It calls the constructor of the Glyphs class with the character sheet image copied earlier.

Page 96: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Check out the Glyphs class:

view source

print?

01 package net.obviam.fonts;0203 import java.util.HashMap;04 import java.util.Map;0506 import android.graphics.Bitmap;07 import android.graphics.Canvas;08 import android.util.Log;0910 /**11 * @author impaler12 *13 */14 public class Glyphs {1516 private static final String TAG = Glyphs.class.getSimpleName();17 private Bitmap bitmap; // bitmap containing the character map/sheet1819// Map to associate a bitmap to each character20private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>(62);2122 private int width; // width in pixels of one character23 private int height; // height in pixels of one character2425// the characters in the English alphabet26private char[] charactersL = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g',27 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',28 'u', 'v', 'w', 'x', 'y', 'z' };29private char[] charactersU = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G',30'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',31 'U', 'V', 'W', 'X', 'Y', 'Z' };32 private char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7',33 '8', '9', '0' };3435 public Glyphs(Bitmap bitmap) {36 super();37 this.bitmap = bitmap;38 this.width = 8;39 this.height = 12;40 // Cutting up the glyphs41 // Starting with the first row - lower cases42 for (int i = 0; i < 26; i++) {

Page 97: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

43 glyphs.put(charactersL[i], Bitmap.createBitmap(bitmap,44 0 + (i * width), 0, width, height));45 }46 Log.d(TAG, "Lowercases initialised");4748 // Continuing with the second row - upper cases49 // Note that the row starts at 15px - hardcoded50 for (int i = 0; i < 26; i++) {51 glyphs.put(charactersU[i], Bitmap.createBitmap(bitmap,52 0 + (i * width), 15, width, height));53 }54 // row 3 for numbers55 Log.d(TAG, "Uppercases initialised");56 for (int i = 0; i < 10; i++) {57 glyphs.put(numbers[i], Bitmap.createBitmap(bitmap,58 0 + (i * width), 30, width, height));59 }60 Log.d(TAG, "Numbers initialised");6162 // TODO - 4th row for punctuation63 }6465 public Bitmap getBitmap() {66 return bitmap;67 }6869 /**70 * Draws the string onto the canvas at <code>x</code> and <code>y</code>71 * @param text72 */73 public void drawString(Canvas canvas, String text, int x, int y) {74 if (canvas == null) {75 Log.d(TAG, "Canvas is null");76 }77 for (int i = 0; i < text.length(); i++) {78 Character ch = text.charAt(i);79 if (glyphs.get(ch) != null) {80 canvas.drawBitmap(glyphs.get(ch), x + (i * width), y, null);81 }82 }83 }84 }

The line

view source

print?

Page 98: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

1private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>(62);

creates the map which associates a bitmap to each character.To load this up we need the bitmaps for each character. I have created 3 arrays for the characters for which I have bitmaps.charactersL[] holds the lower case letters of the English alphabet, charactersU[] the upper caseletters and numbers[] holds the numbers. As an exercise add the punctuation array as this one is missing.

Note that the order of the characters is the same as in the character sheet.For convenience I have created an array for each row from the image. To associate the images with the characters I will iterate through them and cut out the respective image from the sheet based on the index. Having a fixed width for the characters, makes all this dead easy. Examine carefully and understand the constructor. It does the slicing and association.

The drawString(Canvas canvas, String text, int x, int y) method does the drawing. It takes the position where to draw, iterates through the passed in text and draws every character progressively. It is easy to calculate the horizontal offset as each character has the same width.

That is it. To try it out add the following method to the DrawingPanel:

view source

print?

01 public boolean onTouchEvent(MotionEvent event) {02 // draw text at touch03 try {04 canvas = getHolder().lockCanvas();05 synchronized (getHolder()) {06 if (event.getAction() == MotionEvent.ACTION_DOWN07 || event.getAction() == MotionEvent.ACTION_MOVE) {08 // clear the screen09 canvas.drawColor(Color.BLACK);10 // draw glyphs11 glyphs.drawString(canvas, "Drawing string at "12 + (int) event.getX() + " " + (int) event.getY(),13 (int) event.getX(), (int) event.getY());14 }15 if (event.getAction() == MotionEvent.ACTION_UP) {16 canvas.drawColor(Color.BLACK);17 glyphs.drawString(canvas, "Drawn string at "18 + (int) event.getX() + " " + (int) event.getY(),19 (int) event.getX(), (int) event.getY());20 }21 }22 } finally {23 if (canvas != null) {

Page 99: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

24 getHolder().unlockCanvasAndPost(canvas);25 }26 }27 // event was handled28 return true;29 }

Every time we touch the screen, we try to get hold of the canvas to be able to draw onto it. In case of a touch or drag we simply clear the canvas and draw the string onto it.When we stopped touching the screen we display a slightly different text at the last position.Finally we release the canvas. Make sure you return true to signal that the event was handled.

That is it. One last thing needed is to set the DrawingPanel to be our view. This one is done in the activity created with the project. I have also disabled the title.

view source

print?

01 public class PrintingActivity extends Activity {02 /** Called when the activity is first created. */03 @Override04 public void onCreate(Bundle savedInstanceState) {05 super.onCreate(savedInstanceState);06 // turn off title07 requestWindowFeature(Window.FEATURE_NO_TITLE);08 setContentView(new DrawingPanel(this));09 }10 }

The resulting application should look like this:

To do this with OpenGL follow the same principle and use the bitmaps for textures. I will publishan OpenGL version of this article at some point so stay tuned.

Page 100: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Download the code here (obviam.bitmapfont.tar.gz).

Reference: Using Bitmap Fonts in Android from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

13

Android Game Development – Switching from Canvas to OpenGL ESPublished on September 30, 2011 | 19,886 views | Filed in: Android Games

It is about time we delve into the graphical capabilities of the Android platform. Android supports the OpenGL ES API. Needless to say that offloading graphics handling to a dedicated GPU is way more optimal than doing it in the CPU. Most android devices have such a dedicated GPU.

OpenGL is an API for writing 2D and 3D graphics that is rendered on the GPU. This will free up precious computing resources on the CPU to be used for more complex physics or more entities or anything not related to graphics.

There are a few notions that need to be understood but I will introduce them when we will bump into them during the course.

If you followed the articles related to displaying graphics on an android device, you already know that in order to display graphical elements, we need a surface and a renderer. We used a basic SurfaceView from which we obtained the Canvas and we drew everything onto it by calling the supported draw method from within our game loop.

Using OpenGL is not much different. Android comes with a dedicated implementation of the SurfaceView interface for displaying images rendered by OpenGL.

Let’s create the android project the usual way.

Page 101: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

New Project Wizard

I call the activity simply Run. Check what the wizard has generated and it should look like this:

view source

print?

1 public class Run extends Activity {2 /** Called when the activity is first created. */3 @Override4 public void onCreate(Bundle savedInstanceState) {

Page 102: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

5 super.onCreate(savedInstanceState);6 setContentView(R.layout.main);7 }8 }

Nothing special.

Creating the OpenGL renderer

Let’s build the renderer. Create a class GlRenderer which implements the android.opengl.GLSurfaceView.Renderer interface.

It will look like this:

view source

print?

01 import javax.microedition.khronos.egl.EGLConfig;02 import javax.microedition.khronos.opengles.GL10;0304 import android.opengl.GLSurfaceView.Renderer;0506 public class GlRenderer implements Renderer {0708 @Override09 public void onDrawFrame(GL10 gl) {10 }1112 @Override13 public void onSurfaceChanged(GL10 gl, int width, int height) {14 }1516 @Override17 public void onSurfaceCreated(GL10 gl, EGLConfig config) {18 }19 }

We need to implement the above 3 methods. Currently they are empty and do nothing.

The methods

onSurfaceCreated(GL10 gl, EGLConfig config)created or recreated. It is important to bear the recreated bit in mind as it means every time the device goes to sleep for example and awakes, the surface gets recreated. Because the context which holds the resources gets destroyed too, this is the place where we will load our resources (images for textures, etc).

Page 103: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

onSurfaceChanged(GL10 gl, int width, int height) is called whenever the surface size changes. This mainly affects our viewport. The viewport is just a rectangular region through which we see our game world.

onDrawFrame(GL10 gl) is called by the rendering thread to draw each frame. This is where all the drawing happens. We don’t need to call it explicitly. A rendering thread is created by android for us and that will call it.

Let’s switch to the OpenGL renderer. Check out the new Run activity.

view source

print?

01 package net.obviam.opengl;0203 import android.app.Activity;04 import android.opengl.GLSurfaceView;05 import android.os.Bundle;06 import android.view.Window;07 import android.view.WindowManager;0809 public class Run extends Activity {1011 /** The OpenGL view */12 private GLSurfaceView glSurfaceView;1314 /** Called when the activity is first created. */15 @Override16 public void onCreate(Bundle savedInstanceState) {17 super.onCreate(savedInstanceState);1819 // requesting to turn the title OFF20 requestWindowFeature(Window.FEATURE_NO_TITLE);21 // making it full screen22 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,23 WindowManager.LayoutParams.FLAG_FULLSCREEN);2425 // Initiate the Open GL view and26 // create an instance with this activity27 glSurfaceView = new GLSurfaceView(this);2829 // set our renderer to be the main renderer with30 // the current activity context31 glSurfaceView.setRenderer(new GlRenderer());32 setContentView(glSurfaceView);33 }34

Page 104: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

35 /** Remember to resume the glSurface */36 @Override37 protected void onResume() {38 super.onResume();39 glSurfaceView.onResume();40 }4142 /** Also pause the glSurface */43 @Override44 protected void onPause() {45 super.onPause();46 glSurfaceView.onPause();47 }48 }

In line 12 we declare a GLSurfaceView member variable. This is our OpenGL view provided byandroid. When we instantiate it (line 27) we have to make it context aware. That is, for the view to have access to the application environment.

All we need to do is to add our renderer to this view. This we do in line 31.

Line 32 tells the activity to use our OpenGL view.

The onResume() and onPause() methods are being overridden and trigger the respective methods in our view.

You can run the application as an Android app and you should see a blank black screen.

That is it. We have switched from the canvas to the OpenGL renderer.

Download the source code and eclipse project here (obviam.opengl.p01.tgz)

Reference: OpenGL ES with Android Tutorial- Switching from Canvas to OpenGL from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

14

Android Game Development – Displaying Graphical Elements (Primitives) with OpenGL ESPublished on October 3, 2011 | 2,586 views | Filed in: Android Games

Page 105: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

This is part 2 of the android OpenGL ES series. In the previous article we looked at how to set upthe android project to use the provided OpenGL view with our renderer. You can use the project from that article as a template for this.

Before we start displaying things, we must know a few basic concepts of 3D programming and also familiarise ourselves with the terminology. I’s basic geometry really.

3D graphics happens in the Cartesian Coordinate System.

That means that the coordinate system used has three dimensions. X, Y and Z.

Traditionally X goes from left to right, Y from bottom to top, and Z from me into the screen so to speak.

While we deal with objects to display (a robot for example or a car) OpenGL deals with components of these objects. Each object is created from primitives which in the case of OpenGL is a triangle. Every triangle has a face and a backface.

A triangle is defined by 3 points in space. A point is called a vertex (vertices plural).

The following diagram shows 2 vertices. A and B.

Vertices

I drew this diagram to show how we will differentiate between 2D and 3D. A vertex is defined byits X, Y and Z coordinates. If we use 0 for the Z component all the time, we have 2D. You can see vertex A is part of the plane defined by X and Y. Vertex B is farther in on the Z coordinate. If you think of Z as a line being perpendicular to the screen, we wouldn’t even see B.

A triangle is called a primitive. A primitive is the simplest type OpenGL understands and is ableto graphically represent.

Page 106: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

It is very simple. 3 vertices define a triangle. There are other primitives as well, like quads but we’ll stick to the basics. Every shape can be broken down into triangles.

We mentioned the face of the triangle before.

Why is it important? In 3D you will have objects with parts facing towards you, the player and parts facing away from you. In order to make the drawing efficient, OpenGL will not draw the triangles facing away from you as it is not necessary because they will be hidden by the triangles facing towards you anyway. This is called backface culling.

How does OpenGL determine this? This is determined by the order of the vertices when drawing the triangle. If the order is counter clockwise then it is a face (green triangle). Clockwise order of the vertices means it is a backface (the red triangle). This is the default setting but it can be changed of course. The following diagram illustrates just that.

Backface Culling

The red triangle won’t be drawn.

Creating and Drawing a Triangle

With all the theory understood, let’s create a triangle and draw it.

A triangle is defined by 3 vertices. The coordinates of the vertices is not measured in pixels. We will use float to represent the values and they will be relative to each other.

If a side’s length is 1.0f and an other side’s length is 0.5f, then it means that the second side is half the length of the first side’s length. How big it will be displayed depends on how the viewport is set up. Imagine the viewport as a camera. When we use 2D then it means that the

Page 107: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

camera is orthogonal to the screen. If the camera is very close, the triangle will appear big, if it’s far, then the triangle will be small.

Let’s create the Triangle class.

view source

print?

01 package net.obviam.opengl;0203 import java.nio.ByteBuffer;04 import java.nio.ByteOrder;05 import java.nio.FloatBuffer;0607 import javax.microedition.khronos.opengles.GL10;0809 public class Triangle {1011 private FloatBuffer vertexBuffer; // buffer holding the vertices1213 private float vertices[] = {14 -0.5f, -0.5f, 0.0f, // V1 - first vertex (x,y,z)15 0.5f, -0.5f, 0.0f, // V2 - second vertex16 0.0f, 0.5f, 0.0f // V3 - third vertex17 };1819 public Triangle() {20 // a float has 4 bytes so we allocate for each coordinate 4 bytes21

ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);

22

vertexByteBuffer.order(ByteOrder.nativeOrder());

2324 // allocates the memory from the byte buffer25 vertexBuffer = vertexByteBuffer.asFloatBuffer();2627 // fill the vertexBuffer with the vertices28 vertexBuffer.put(vertices);2930 // set the cursor position to the beginning of the buffer31 vertexBuffer.position(0);32 }33 }

Line 11 defines a FloatBuffer that will hold the vertices for our triangle. We need to use the java.nio package as it is very intensive input output.

Page 108: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The vertices[] array holds the actual coordinates for the vertices.

The triangle we will draw is represented in the following diagram. We calculate everything from the origin.

Triangle

In the constructor we initialise the triangle from this vertices[] array.

What we do is, we fill the vertexBuffer with the coordinates and set the cursor’s position to the beginning of the buffer. We will be using this buffer in the OpenGL call to display triangle strips.We currently have just one.

Let’s take a look at the renderer. The GlRenderer

view source

print?

01 package net.obviam.opengl;0203 import javax.microedition.khronos.egl.EGLConfig;04 import javax.microedition.khronos.opengles.GL10;0506 import android.opengl.GLU;07 import android.opengl.GLSurfaceView.Renderer;0809 public class GlRenderer implements Renderer {1011 private Triangle triangle; // the triangle to be drawn1213 /** Constructor */14 public GlRenderer() {

Page 109: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

15 this.triangle = new Triangle();16 }1718 @Override19 public void onDrawFrame(GL10 gl) {20 // clear Screen and Depth Buffer21 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);2223 // Reset the Modelview Matrix24 gl.glLoadIdentity();2526 // Drawing27 gl.glTranslatef(0.0f, 0.0f, -5.0f); // move 5 units INTO the screen28 // is the same as moving the camera 5 units away29 triangle.draw(gl); // Draw the triangle3031 }3233 @Override34 public void onSurfaceChanged(GL10 gl, int width, int height) {35 if(height == 0) { //Prevent A Divide By Zero By36 height = 1; //Making Height Equal One37 }3839 gl.glViewport(0, 0, width, height); //Reset The Current Viewport40 gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix41 gl.glLoadIdentity(); //Reset The Projection Matrix4243//Calculate The Aspect Ratio Of The Window44GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);4546 gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix47 gl.glLoadIdentity(); //Reset The Modelview Matrix48 }4950 @Override51 public void onSurfaceCreated(GL10 gl, EGLConfig config) {52 }53 }

We create the triangle in the constructor.

The onDrawFrame(GL10 gl) is of the most interest for us.

OpenGL works with state variables. Every method we call on the OpenGL context changes its internal state.

Page 110: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Following the onDrawFrame method we see that every time a frame is drawn, the buffers get cleared, the ModelView matrix is reloaded (don’t worry if you don’t understand this at the moment), the camera is moved away 5 units (we’re dealing with units here, not pixels) and the triangle’s draw() method is called.

The onSurfaceChanged on the other hand, transitions the OpenGL context between a few states.First it sets the viewport to the current width and height of the surface (so it works with the GL_PROJECTION state), then it transitions the state to the GL_MODELVIEW so we can work with our models – the triangle in our case. It will make sense later on, don’t worry.

Let’s check out the draw method for the triangle:

view source

print?

01 public void draw(GL10 gl) {02 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);0304 // set the colour for the triangle05 gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);0607 // Point to our vertex buffer08 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);0910 // Draw the vertices as triangle strip11 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);1213 //Disable the client state before leaving14 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);15 }

Because we store the triangle’s vertices’ coordinates in a FloatBuffer we need to enable OpenGLto read from it and understand that is a triangle there. Line 02 does just that.

Line 05 sets the colour for the entity (triangle in our case) that will be drawn. Note that the values of the rgb are floats and are between 0.0 and 1.0.

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); will tell OpenGL to use the vertexBuffer to extract the vertices from.

The first parameter (value = 3) represents the number of vertices in the buffer. The second lets OpenGL know what type the data the buffer holds.

The third parameter is the offset in the array used for the vertices. Because we don’t store extra data, our vertices follow each other and there is no offset.

Page 111: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Finally the last parameter is our buffer containing the vertices.

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3); tells OpenGL to draw triangle strips found in the buffer provided earlier, starting with the first element. It also letsit know how many vertices there are.

That is it. Run the project and you should be able to see your first accelerated triangle. Just like this:

Download the source here (obviam.opengl.p02.tgz):

I was inspired by code from the nehe android ports. To learn the guts of OpenGL I warmly recommend the nehe tutorials.

Next we will see how we can create basic 3D objects and rotate them. We will also find out how we can use textures on elements.

Reference: OpenGL ES Android – Displaying Graphical Elements (Primitives) from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

15

Page 112: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Android Game Development – OpenGL Texture MappingPublished on October 6, 2011 | 17,582 views | Filed in: Android Games

In the previous two articles (article 1 and article 2) I have tried to introduce OpenGL ES on android. Now let’s take it further and build on them. In this article we will create a billboard (which is a square) and we will apply a texture onto it. A texture is nothing more than a bitmap image. When we work in 2D we set the Z coordinate to 0. We’ll cover 3D later. This is very useful to use in 2D games and is the preferred way to display images using OpenGL. It is very fast indeed.

In the previous articles we managed to display triangles. How to display a square then? A square is composed of 2 triangles.

The following diagram shows you this:

Square from Triangles

There is an interesting thing to note here. The square is ABDC instead of the usual ABCD. Why is that? Because of how OpenGL chains triangles together.

What you see here is a triangle strip. A triangle strip is a series of connected triangles, 2 trianglesin our case.

OpenGL draws the following triangle strip (which is a square) using the vertices in the followingorder:

Triangle 1: V1 -> V2 -> V3

Triangle 2: V3 -> V2 -> V4

Page 113: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Triangle Strip

It draws the first triangle using the vertices in order, then it takes the last vertex from the previous triangle and uses the last side of the triangle as the basis for the new triangle.

This also has benefits: we eliminate redundant data from the memory.

Grab the project from the previous article and create a new class called Square.

If you compare the Square class with the Triangle class, you will notice just one difference:

view source

print?

01 package net.obviam.opengl;0203 import java.nio.ByteBuffer;04 import java.nio.ByteOrder;05 import java.nio.FloatBuffer;0607 import javax.microedition.khronos.opengles.GL10;0809 public class Square {1011 private FloatBuffer vertexBuffer; // buffer holding the vertices1213 private float vertices[] = {14 -1.0f, -1.0f, 0.0f, // V1 - bottom left15 -1.0f, 1.0f, 0.0f, // V2 - top left16 1.0f, -1.0f, 0.0f, // V3 - bottom right17 1.0f, 1.0f, 0.0f // V4 - top right18 };

Page 114: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

1920 public Square() {21

// a float has 4 bytes so we allocate for each coordinate 4 bytes

22

ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);

23 vertexByteBuffer.order(ByteOrder.nativeOrder());2425 // allocates the memory from the byte buffer26 vertexBuffer = vertexByteBuffer.asFloatBuffer();2728 // fill the vertexBuffer with the vertices29 vertexBuffer.put(vertices);3031 // set the cursor position to the beginning of the buffer32 vertexBuffer.position(0);33 }3435 /** The draw method for the square with the GL context */36 public void draw(GL10 gl) {37 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);3839 // set the colour for the square40 gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);4142 // Point to our vertex buffer43 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);4445 // Draw the vertices as triangle strip46 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);4748 //Disable the client state before leaving49 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);50 }51 }

The difference is in the highlighted lines (13-18). That’s right, we’ve added one more vertex to the vertices array.

Now change the GlRenderer so instead of a Triangle we use a Square.

view source

print?

01 package net.obviam.opengl;0203 import javax.microedition.khronos.egl.EGLConfig;

Page 115: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

04 import javax.microedition.khronos.opengles.GL10;0506 import android.opengl.GLU;07 import android.opengl.GLSurfaceView.Renderer;0809 public class GlRenderer implements Renderer {1011 private Square square; // the square1213 /** Constructor to set the handed over context */14 public GlRenderer() {15 this.square = new Square();16 }1718 @Override19 public void onDrawFrame(GL10 gl) {20 // clear Screen and Depth Buffer21 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);2223 // Reset the Modelview Matrix24 gl.glLoadIdentity();2526 // Drawing27 gl.glTranslatef(0.0f, 0.0f, -5.0f); // move 5 units INTO the screen28 // is the same as moving the camera 5 units away29 square.draw(gl); // Draw the triangle3031 }3233 @Override34 public void onSurfaceChanged(GL10 gl, int width, int height) {35 if(height == 0) { //Prevent A Divide By Zero By36 height = 1; //Making Height Equal One37 }3839 gl.glViewport(0, 0, width, height); //Reset The Current Viewport40 gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix41 gl.glLoadIdentity(); //Reset The Projection Matrix4243//Calculate The Aspect Ratio Of The Window44GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);4546 gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix47 gl.glLoadIdentity(); //Reset The Modelview Matrix48 }4950 @Override

Page 116: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

51 public void onSurfaceCreated(GL10 gl, EGLConfig config) {52 }53 }

Running this will produce the following result:

Triangle Strip forming a Square

Examining this, the draw() method in the Square class should make sense now.

view source

print?

01 public void draw(GL10 gl) {02 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);0304 // set the colour for the square05 gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);0607 // Point to our vertex buffer08 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);0910 // Draw the vertices as triangle strip11 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);1213 //Disable the client state before leaving14 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);15 }

Page 117: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

First we enable OpenGL to use a vertex array for rendering. Our vertex array contains the vertices for our square.

gl.glVertexPointer (line 5) tells the opengl renderer from where to take the vertices and of what type they are.

The first parameter tells how many coordinates are used for a vertex. We use 3 (x,y,z). The second parameter tells that the values are of type float.

The 3rd parameter is the offset between the vertices in the array. It is called the strife. We have a tightly packed array so it is 0.

Finally the last parameter tells where the vertices are held. Of course it is our buffer vertexBuffer.

gl.glDrawArrays in line 11 tells OpenGL to draw the primitive. What kind of primitive? The one specified in the first parameter: GL10.GL_TRIANGLE_STRIP. It takes the vertices from the previously set vertex buffer and it follows the rules of the triangle strips described earlier.

The second parameter specifies the starting index for the vertices in the array.

The 3rd parameter tells OpenGL, how many vertices to use for the polygon, about to be rendered. Because in the previous statement (gl.glVertexPointer) we specified that 3 coordinatesdefine a vertex, we will provide the length of our vertex array divided by 3. There are 9 elements in the array defining 3 vertices.

glDisableClientState(GL10.GL_VERTEX_ARRAY) disables the state of rendering from an array containing the vertices.

Think of glEnableClientState and glDisableClientState as begin … end statements in a program. We basically enter subroutines in the OpenGL renderer. Once we entered a routine, we set up variables (the vertex buffer, the colour, etc) and we execute other subroutines (draw vertices). After we’re done, we exit the subroutine. We work in isolation inside the renderer.

Make sure you run the application at this stage and understand what is going on.

Creating the Texture

Now the fun part. Let’s load up an image and create a texture. A texture IS an image.

To find out how you can load up images in your android app, check out this article.

We will be working with the Square class as we want to apply the texture to the square.

We need to load up the image, tell the opengl renderer that we want to use it as a texture, and finally we will tell the renderer where exactly onto our primitive (square) to display it.

Page 118: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Think of it as if you were putting a foil onto a window or a wall. I provide you with a foil containing an image of the size of the window and tell you to cover the window with it, so the top left corner of the foil will be on the top left corner of the window. That is it, let’s get to work.

OpenGL uses the vertices to work out where to put stuff. So we need to create an array for the image. But this time, this will be 2D as a bitmap is like a sheet of paper, a flat plane.

Add the coordinate array for the texture.

view source

print?

1private FloatBuffer textureBuffer; // buffer holding the texture coordinates2private float texture[] = {3 // Mapping coordinates for the vertices4 0.0f, 1.0f, // top left (V2)5 0.0f, 0.0f, // bottom left (V1)6 1.0f, 1.0f, // top right (V4)7 1.0f, 0.0f // bottom right (V3)8 };

We need to create the textureBuffer in a similar way to the vertexBuffer. This happens in the constructor and we’ll just reuse the byteBuffer. Check the new constructor:

view source

print?

01 public Square() {02 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);03 byteBuffer.order(ByteOrder.nativeOrder());04 vertexBuffer = byteBuffer.asFloatBuffer();05 vertexBuffer.put(vertices);06 vertexBuffer.position(0);0708 byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);09 byteBuffer.order(ByteOrder.nativeOrder());10 textureBuffer = byteBuffer.asFloatBuffer();11 textureBuffer.put(texture);12 textureBuffer.position(0);13 }

We will add an important method to the Square class. The loadGLTexture method. This will be called from the renderer when it starts up. It happens in the onSurfaceCreated method. This willload up the image from the disk and bind it to a texture in the OpenGL repository. It will basically assign an internal ID for the processed image and will be used by the OpenGL API to identify it among other textures.

Page 119: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

view source

print?

01 /** The texture pointer */02 private int[] textures = new int[1];0304 public void loadGLTexture(GL10 gl, Context context) {05 // loading texture06 Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),07 R.drawable.android);0809 // generate one texture pointer10 gl.glGenTextures(1, textures, 0);11 // ...and bind it to our array12 gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);1314 // create nearest filtered texture15

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);

16

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

1718

// Use Android GLUtils to specify a two-dimensional texture image from our bitmap

19 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);2021 // Clean up22 bitmap.recycle();23 }

We need a texture pointer array. This is where OpenGL will store the names of the textures we will use in our application. Because we have just one image, we will create an array of size 1.

Line 06 loads the android bitmap which was previously copied into the /res/drawable-mdpi directory, so the ID is already generated.

A note about this bitmap. It is encouraged to be square. It helps a lot with scaling. So make sure your bitmaps for textures are squares (6×6, 12×12, 128×128, etc.). If not square, make sure the width and height are powers of 2 (2, 4, 8, 16, 32, …). You can have a bitmap 128×512 and it is perfectly usable and it is optimised.

Line 10 generates the names for the textures. In our case generates one name and stores it in the textures array. Even if it says name, it actually generates an int. A bit confusing, but it is how it is.

Page 120: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Line 12 binds the texture with the newly generated name (texture[0]). What this means is, that anything using textures in this subroutine, will use the bound texture. It practically activates the texture. A bound texture is the active texture. If we would have had multiple textures and multiple squares to use them, we would have had to bind (activate) the appropriate textures for each square just before they were used to activate them.Lines 15 and 16 set some filters to be used with for texture. We have just told OpenGL what types of filters to use when it needs to shrink or expand the texture to cover the square. We have chosen some basic algorithms on how to scale the image. Don’t have to worry about this now.

In line 19 we use Android’s utilities to specify the 2D texture image for our bitmap. It creates the image (texture) internally in its native format based on our bitmap.

in line 22 we free up the memory. This you should not forget as memory on a device is very limited and images are big.

Now let’s see how the draw() method has been modified.

view source

print?

01 public void draw(GL10 gl) {02 // bind the previously generated texture03 gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);0405 // Point to our buffers06 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);07 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);0809 // Set the face rotation10 gl.glFrontFace(GL10.GL_CW);1112 // Point to our vertex buffer13 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);14 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);1516 // Draw the vertices as triangle strip17 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);1819 //Disable the client state before leaving20 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);21 gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);22 }23 }

It’s not a huge modification from the previous article. The additions are documented and do the following:

Page 121: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Line 03 binds (activates) the texture with the name (integer ID) stored in textures[0].

Line 07 enables the texture mapping in the current OpenGL context.

Line 14 provides the OpenGL context with the texture coordinates.After drawing the primitive with textures, we switch off the texture mapping along with the primitive rendering.

Important – UV Mapping

If you look carefully, the vertex order in the texture mapping coordinates array doesn’t follow theorder present in the square’s vertex coordinates array.

There is a very good explanation of texture mapping coordinates here: http://iphonedevelopment.blogspot.com/2009/05/opengl-es-from-ground-up-part-6_25.html.

I will try to explain it quickly though. Examine the following diagram.

Square and Texture Coordinates Ordering

The square is composed of 2 triangles and the vertices are in the following order.

1 – bottom left

2 – bottom right

3 – top left

4 – top right

Notice the counter clockwise path.

The texture coordinates will be in the order: 1 -> 3 -> 2 -> 4

Just bear this mapping in mind and rotate it if you start your shape from a different corner. To read up on UV mapping check the wikipedia entry or search the net for it.

Page 122: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

For the final part, to make this work, we need to provide the context to our renderer so we can load up the texture at startup.

The onSurfaceCreated method will look like this.

view source

print?

01 public void onSurfaceCreated(GL10 gl, EGLConfig config) {02 // Load the texture for the square03 square.loadGLTexture(gl, this.context);0405 gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )06 gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading07 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background08 gl.glClearDepthf(1.0f); //Depth Buffer Setup09 gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing10 gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do1112 //Really Nice Perspective Calculations13 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);14 }

Line 03 loads the texture. The rest of the lines just configure the renderer with some values. You don’t have to worry about them now.

You will need to provide the application context to the Square object, because the object itself loads the texture and needs to know the path to the bitmap.

Just provide the context to the renderer in the Run activity’s onCreate method (glSurfaceView.setRenderer(new GlRenderer(this));) and it’s done.

Make sure the renderer has the context declared and set via the constructor.

Excerpt from the GlRendered class.

view source

print?

01 private Square square; // the square02 private Context context;0304 /** Constructor to set the handed over context */05 public GlRenderer(Context context) {06 this.context = context;07

Page 123: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

08 // initialise the square09 this.square = new Square();10 }

If you run the code you should see the square with a nice android laid on top of it.

Square with Android Texture

Download the source code and project here (obviam.opengl.p03.tgz).

Reference: Texture Mapping – OpenGL Android (Displaying Images using OpenGL and Squares) from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

16

Android Game Development – Design In-game Entities – The State PatternPublished on October 7, 2011 | 2,739 views | Filed in: Android Games

In this part I will try to explain how to design easily extensible and maintainable game elements that control their own internal state and behaviours.

An internal state is best described as being the soul and mind of the entity. In the first part I described why composition is better than inheritance. In a nutshell composition provides the

Page 124: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

means to interchange the algorithms associated with their behaviours. State on the other hand helps objects to control their own behaviors.

If you are not familiar with the behaviors and strategies, I strongly suggest to go and check out the previous article as I will be picking up those droids and make them utterly clever during the next articles. But first we need to take a closer look to how I design less clever entities, like weapons.

Let’s design an old fashioned rifle and learn from the process how to design the next gen weapons to fend off the invading droid army.

Breaking it down, what can one do with a rifle? Pull the trigger of course and reload (insert, ejectthe ammo clip).

Now think of all the scenarios. What happens if I pull the trigger and there is no clip? Or when there is one but it’s empty? Apparently a simple thing became a bit more complicated. Let’s see iton paper:

Initial Rifle State Diagram

Let’s examine the diagram and figure out what it is and what is that we want.

The above diagram is called a State Diagram.

Each of those circles is a State and each of those arrows is a State Transition.

Each state is just a different configuration of the rifle. The rifle behaves in certain ways depending in which state it is in and some action is needed to take it to another state. So, to go to another state, you will need to do something like pull the trigger or insert clip. See the arrows on the diagram.

We identify the following states:

Page 125: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

No Clip

Has Clip

Ammo fired

Out of Ammo

and actions (transitions):

inserts clip

ejects clip

pulls trigger

fire ammo

Note: I used third person for 3 of the actions. It is because the user of the weapon will trigger these actions while fire ammo is more of an internal action.

The whole thing described above is also called a Finite State Machine. It is nothing more than an object that holds a finite number of states that govern behaviour and the object can be in only one state at any given time.

Our First Implementation

Knowing all this, what would be our first choice for the implementation? A class that has all the possible states and actions, right? It should also hold the current state. Simple.

Create the Rifle.java class.

view source

print?

01 public class Rifle {0203 // defining the states04 final static int NO_CLIP = 0;05 final static int HAS_CLIP = 1;06 final static int AMMO_FIRED = 2;07 final static int OUT_OF_AMMO = 3;0809 int state = NO_CLIP; // instance variable holding the current state10 int ammoCount = 0; // we count the ammo

Page 126: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

11 }

Great! We created the structure of the rifle. We also want to know when we are out of ammo, so we added the ammoCount variable. They are set to default values. The rifle holds no clip thus the ammo is 0 when it is created.

Now let’s add the actions. But beware! Exposing all the actions to someone handling the weaponis dangerous. What will happen when someone tries to pull out the clip while firing? We need to take these into consideration when triggering the actions.

view source

print?

01 // **********************02 // Creating the actions03 // **********************0405 public void insertClip() {06 // We check each possible state and act according to them07 if (state == HAS_CLIP) {08 System.out.println("There is already a clip loaded.");09 } else if (state == AMMO_FIRED) {10 System.out.println("You'll hurt yourself!!!");11 } else if (state == OUT_OF_AMMO) {12 System.out.println("You need to take out the empty clip first.");13 } else if (state == NO_CLIP) {14 state = HAS_CLIP;15

ammoCount = 10;

16

System.out.println("You have loaded a clip with " + ammoCount + " bulletts.");

17 }18 }1920 public void ejectClip() {21 if (state == NO_CLIP) {22 System.out.println("The magazine is empty.");23 } else if (state == AMMO_FIRED) {24 System.out.println("You'll hurt yourself!!!");25 } else if (state == HAS_CLIP) {26 // You could still eject it if you want but for the sake of27 // simplicity let's use up the ammo first28 System.out.println("Use up all your ammo first.");29 } else if (state == OUT_OF_AMMO) {30 state = NO_CLIP;31 System.out.println("You have unloaded a clip.");32 }33 }

Page 127: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

3435 public void pullTrigger() {36 if (state == NO_CLIP) {37 System.out.println("Empty Click!");38 } else if (state == AMMO_FIRED) {39 System.out.println("Jammed!");40 } else if (state == OUT_OF_AMMO) {41 System.out.println("Click! Out of ammo.");42 } else if (state == HAS_CLIP) {43 System.out.println("BANG!!!");44 state = AMMO_FIRED;45 fireAmmo();46 }47 }4849 public void fireAmmo() {50 if (state == NO_CLIP) {51 System.out.println("Empty magazine.");52 } else if (state == AMMO_FIRED) {53 System.out.println("Bullet already on its way to kill someone!");54 } else if (state == OUT_OF_AMMO) {55 System.out.println("Out of ammo.");56 } else if (state == HAS_CLIP) {57 state = AMMO_FIRED;58 ammoCount--;59 System.out.println("Bullet on its way!");60 // we check if the clip is empty61 if (ammoCount == 0) {62 // yes, it's empty63 System.out.println("Darn! Out of ammo");64 state = OUT_OF_AMMO;65 } else {66 state = HAS_CLIP;67 }68 }69 }

Let’s put the rifle to the test.

Create the RifleTest.java class.

view source

print?

01 public class RifleTest {0203 public static void main(String[] args) {04 Rifle rifle = new Rifle();

Page 128: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

05 System.out.println(rifle);0607 rifle.insertClip();08 rifle.pullTrigger();09 rifle.pullTrigger();10 rifle.pullTrigger();11 rifle.pullTrigger();1213 System.out.println(rifle);1415 rifle.insertClip();16 rifle.ejectClip();17 rifle.pullTrigger();18 }19 }

It is a very simple scripted scenario which performs some actions on the rifle. Some may be goodsome bad. As when trying to force in a second clip or pulling the trigger when it’s out of ammo.

Check out the result and examine it carefully. How cool is that? We are the Kalashnikovs of our age.

view source

print?

01 << RIFLE [state=Empty Magazine (No Clip), ammo=0] >>02 > You have loaded a clip with 3 bullets.03 > BANG!!!04 > Bullet on its way!05 > BANG!!!06 > Bullet on its way!07 > BANG!!!08 > Bullet on its way!09 > Darn! Out of ammo10 !* Click! Out of ammo.11 << RIFLE [state=Out of Ammo, ammo=0] >&g;t12 !* You need to take out the empty clip first.13 > You have unloaded a clip.14 !* Empty Click! – No clip!

Note that I have omitted the toString() method for the Rifle.

Well done! We have our first state machine.

But

Page 129: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

We can’t do much firing bullet by bullet. We need automatic fire! Oh, and we can’t just let people running around with rifles without the safety ON.

Ah, that’s easy, right? We’ll have a few more states and a few more transitions.

But wait, we will need to rework the Rifle class a bit.

Let’s see what we need to modify just to support automatic and manual fire:

we need to add the two states

but then we need to modify every single method to handle the states by adding conditional statements

pullTrigger() will get complicated as it will need to know what state it is in and check bullets and fire them as such

That is a LOT of work. It must be some other way.

The Solution

What if we give each state a behaviour and put it into its own class? This way each state will implement its own actions only. We will have the rifle class delegating the action to the state object that represents the current state.

Let’s see how does it look?

Final Rifle State Diagram

What you should notice is that the Has Clip is now Manual/Auto and has a switch transition. It basically has a sub-state now. Flipping the switch changes the behaviour. Both states will have

Page 130: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

the pull trigger action but each state will behave differently. This is easily achieved with interfaces, right?

Let’s start coding then. First, let’s create the state interface. Remember, each state will implementits transition and will provide the dummy implementation for the rest. The interface will contain all the actions.

The methods map directly to all the actions that can happen with the Rifle

view source

print?

1 public interface RifleState {23 public void insertClip();4 public void ejectClip();5 public void swithManualAuto();6 public void pullTrigger();7 public void fireAmmo();8 }

The new Rifle class will have none of the implemented actions, but will have all the states and will delegate the actions to its current state.

Rifle.java

view source

print?

01 public class Rifle {0203 // the states of the rifle04 RifleState emptyState;05 RifleState autoFireState;06 RifleState manualFireState;07 RifleState outOfAmmoState;08 RifleState roundFiredState;09 RifleState ammoFiredState;1011 RifleState state = emptyState;12 int ammoCount = 0;1314 // constructor15 public Rifle() {16 // creating states17 this.emptyState = new NoClipState(this);

Page 131: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

18 this.autoFireState = new AutoFireState(this);19 this.manualFireState = new ManualFireState(this);20 this.outOfAmmoState = new OutOfAmmoState(this);21 this.roundFiredState = new RoundFiredState(this);22 this.ammoFiredState = new AmmoFiredState(this);2324 this.state = this.emptyState;25 this.ammoCount = 0;26 }27 // convenience methods - delegating only28 public void insertClip() {29 this.state.insertClip();30 }31 public void ejectClip() {32 this.state.ejectClip();33 }34 public void switchManualAuto() {35 this.state.switchManualAuto();36 }37 public void pullTrigger() {38 this.state.pullTrigger();39 }4041 // getters and setters42 // ... omitted43 }

You see that the class has changed a bit. It has all the states and a current state. It has a constructor too. The constructor is needed to set up the rifle and pass itself as a reference to all ofthe states to give them access to the rifle’s properties. In our case just the ammo count and current state need to be accessed.

Also the fireAmmo() is missing as it is a state internal action.

Now let’s map the states to actual classes. These are the same as in the original rifle class.

I will list one full class and for the rest only the methods that change the state. Examine the source code for the complete listings.

OutOfAmmoState.java

view source

print?

01 public class OutOfAmmoState implements RifleState {0203 private Rifle rifle;

Page 132: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

04 public OutOfAmmoState(Rifle rifle) {05 this.rifle = rifle;06 }0708 @Override09 public void ejectClip() {10 rifle.setState(rifle.getEmptyState());11 System.out.println("> Clip ejected.");12 }1314 @Override15 public void fireAmmo() {16 System.out.println("!* You can't fire with no ammo.");17 }1819 @Override20 public void insertClip() {21 System.out.println("!* There is an empty clip inserted already!");22 }2324 @Override25 public void pullTrigger() {26 System.out.println("!* Out of ammo!");27 }2829 @Override30 public void switchManualAuto() {31 System.out.println("!* Plesea reload first");32 }33 }

Notice that the only way out of the OutOfAmmoState is by ejecting the clip.

Every other attempt will do nothing.

Also note the constructor. We are passing the reference to the rifle there.

Check out the other classes too:

AmmoFiredState

view source

print?

01 public class AmmoFiredState implements RifleState {0203 private Rifle rifle;

Page 133: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

04 public AmmoFiredState(Rifle rifle) {05 this.rifle = rifle;06 }0708 @Override09 public void fireAmmo() {10 rifle.setAmmoCount(rifle.getAmmoCount() - 1);11 System.out.println("> Fired 1 bullet.");12 if (rifle.getAmmoCount() == 0) {13 rifle.setState(rifle.getOutOfAmmoState());14 } else {15 rifle.setState(rifle.getManualFireState());16 }17 }18 // ... ommited19 }

AutoFireState

view source

print?

01 public class AutoFireState implements RifleState {0203 private Rifle rifle;04 public AutoFireState(Rifle rifle) {05 this.rifle = rifle;06 }0708 @Override09 public void ejectClip() {10 rifle.setAmmoCount(0);11 rifle.setState(rifle.getEmptyState());12 System.out.println("> Clip ejected. Please reload.");13 }1415 @Override16 public void pullTrigger() {17 System.out.println("> Pulled trigger.");18 rifle.setState(rifle.getRoundFiredState());19 rifle.getState().fireAmmo();20 }2122 @Override23 public void switchManualAuto() {24 rifle.setState(rifle.getManualFireState());25 System.out.println("> Switched to manual. Hope they are slow and few!");26 }

Page 134: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

27 // ... ommited28 }

If you follow the diagram then you should be able to figure out the transitions. There is a trick there as the Manual and Auto modes are very similar and I just transition between them. There is a drawback as after a reload, the manual state is the active one even if the auto was set before. But I’m sure you can figure out a quick fix.

ManualFireState

view source

print?

01 public class ManualFireState implements RifleState {0203 private Rifle rifle;04 public ManualFireState(Rifle rifle) {05 this.rifle = rifle;06 }0708 @Override09 public void ejectClip() {10 rifle.setAmmoCount(0);11 rifle.setState(rifle.getEmptyState());12 System.out.println("> Clip ejected. Please reload.");13 }1415 @Override16 public void pullTrigger() {17 System.out.println("> Pulled trigger.");18 rifle.setState(rifle.getAmmoFiredState());19 rifle.getState().fireAmmo();20 }2122 @Override23 public void switchManualAuto() {24 rifle.setState(rifle.getAutoFireState());25 System.out.println("> Switched to auto. Bring'em on!!!");26 }2728 // ... ommited29 }

NoClipState

view source

Page 135: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

01 public class NoClipState implements RifleState {0203 private Rifle rifle;04 public NoClipState(Rifle rifle) {05 this.rifle = rifle;06 }0708 @Override09 public void insertClip() {10 rifle.ammoCount = 50;11 rifle.setState(rifle.getManualFireState());12 }1314 // ...ommited15 }

RoundFiredState

view source

print?

01 public class RoundFiredState implements RifleState {0203 private Rifle rifle;04 public RoundFiredState(Rifle rifle) {05 this.rifle = rifle;06 }0708 @Override09 public void fireAmmo() {10 int count = 10;11 while (count > 0 && rifle.getAmmoCount() > 0) {12 System.out.print("> BANG! ");13 rifle.setAmmoCount(rifle.getAmmoCount() - 1);14 count--;15 }16 System.out.println();17

System.out.println("> Fired a round of " + (10 - count) + " bullets. Yeah!");

18

if (rifle.getAmmoCount() <= 0) {

19 rifle.setAmmoCount(0);20 rifle.setState(rifle.getOutOfAmmoState());21 } else {22 rifle.setState(rifle.getAutoFireState());23 }

Page 136: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

24 }25 // ...ommited26 }

Great! Let’s throw together a test for the new shiny Rifle.

RifleTest

view source

print?

01 public class RifleTest {0203 public static void main(String[] args) {04 Rifle rifle = new Rifle();0506 rifle.pullTrigger();07 rifle.ejectClip();08 rifle.insertClip();09 rifle.pullTrigger();10 rifle.switchManualAuto();11 rifle.pullTrigger();12 rifle.pullTrigger();13 rifle.switchManualAuto();14 rifle.pullTrigger();15 rifle.insertClip();16 rifle.switchManualAuto();17 rifle.pullTrigger();18 rifle.pullTrigger();19 rifle.pullTrigger();20 rifle.pullTrigger();21 rifle.pullTrigger();22 }

Examine the output very carefully and go through the source code. You should try adding new features or think of other scenarios.

view source

print?

01 !* You can’t fire with an empty magazine.02 !* The magazine is empty.03 > Pulled trigger.04 > Fired 1 bullet.05 > Switched to auto. Bring’em on!!!06 > Pulled trigger.07 > BANG! >BANG! >BANG! >BANG! >BANG! >BANG! >BANG! > BANG! >BANG! >BANG!

Page 137: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

08 > Fired a round of 10 bullets. Yeah!09 > Pulled trigger.10 >BANG! >BANG! >BANG! >BANG! >BANG! >BANG! >BANG! > BANG! >BANG! >BANG!11 > Fired a round of 10 bullets. Yeah!12 > Switched to manual. Hope they are slow and few!13 > Pulled trigger.14 > Fired 1 bullet.15 !* Clip is already present!16 > Switched to auto. Bring’em on!!!17 > Pulled trigger.18 > BANG! >BANG! >BANG! >BANG! >BANG! >BANG! >BANG! > BANG! >BANG! >BANG!19 > Fired a round of 10 bullets. Yeah!20 > Pulled trigger.21 > BANG! >BANG! >BANG! >BANG! >BANG! >BANG! >BANG! > BANG! >BANG! >BANG!22 > Fired a round of 10 bullets. Yeah!23 > Pulled trigger.24 > BANG! >BANG! >BANG! >BANG! >BANG! >BANG! >BANG! >BANG!25 > Fired a round of 8 bullets. Yeah!26 !* Out of ammo!27 !* Out of ammo!

Again, the yellow lines show you when you tried something dodgy.

Voila! We have state machines and easily extensible game elements.

I strongly encourage you to extend it and build your own, as it is a very important element of game design.

You can apply this principle for the whole game and infrastructure. Think of the game as a wholeand when you’re on the menu screen (that’s the Menu State), when you’re in the paused screen, that’s the Pause State, or the main screen that’s the Running State. You could create a framework and easily add different game states.

I do hope this gave you a good introduction on how to implement state driven behaviours. Note that I used normal Java practices to write the code for clarity. Meaning that when writing a game,especially for Android, you might not need to overload your classes with getters and setters and you should adhere to the optimized ways. You could use public attributes and access them directly for example. But it was not the scope of this article.

Also understanding this is crucial to make a step towards autonomous agents (automatons). Next time I will introduce event and/or message driven behaviours. We will return to our beloved droids to give them wits to outrun you.

Download the source code and project here (obviam.states.tgz).

Note that the first attempt was renamed to RifleOld.java and RifleOldTest.java

Page 138: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Reference: Design In-game Entities. Object Composition Strategies. Part 2 – The State Pattern from our JCG partner Tamas Jano from “Against The Grain” blog.

Do not forget to check out our new Android Game ArkDroid (screenshots below). You feedback will be more than helpful!

17

Building Games Using the MVC Pattern – Tutorial and IntroductionPublished on February 14, 2012 | 7,062 views | Filed in: Desktop Java Tags: Game Design

One useful architecture pattern in game development is the MVC (model-view-controller) pattern.

It helps separate the input logic, the game logic and the UI (rendering). The usefulness is quickly noticeable in the early stages of any game development project because it allows to change things quickly without too much rework of code in all layers of the application.

The following diagram is the simplest logical representation of the model view controller concept.

Model-View-Controller pattern

Example Usage

In an example game where the player controls a robot the following can happen:

1 – User clicks/taps somewhere on the screen.

2 – The controller handles the click/tap and converts the event into an appropriate action.For example if the terrain is occupied by an enemy, an attack action is created, if it is

Page 139: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

empty terrain, then a move action is created and finally if the place where the user tapped is occupied by an obstacle, do nothing.

3 – The controller updates the robot‘s (model‘s) state accordingly. If the move action was created, then it changes the position, if the attack, then it fires.

4 – The renderer (view) gets notified about the state changes and renders the world’s current state.

What this all means is, that the models (robots) don’t know anything about how to draw themselves, or how to change their state (position, hit points). They are dumb entities. In Java they are also called POJOs (plain old java objects).

The controller is in charge of changing the models’ state and notify the renderer.

The renderer has to have a reference to the models (robots and any other entities) and their state, in order to draw them.We know from the typical game architecture that the main loop acts as a super controller, which updates the states and then renders the objects onto the screen many times a second. We can put all the update and rendering into the main loop along with the robots but that would be messy.Let’s identify the different aspects (concerns) of our games.

The models

The droid controlled by the player

An arena where the droid can move

Some obstacles

Some enemies to shoot at

The controllers

The main loop and the input handler

Controller to process player input

Controller to perform actions on the player’s robot (move, attack)

The views

The world renderer – to render the objects onto the screen

Creating the Project

Page 140: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

For simplicity I have chosen the applet this time and will try to keep it very brief. The project hasthe following structure:

MVC – Project structure

The file Droids.java is the applet and contains the main loop.

view source

print?

01 package net.obviam.droids;0203 import java.applet.Applet;04 import java.awt.Color;05 import java.awt.Event;06 import java.awt.Graphics;07 import java.awt.image.BufferedImage;0809 public class Droids extends Applet implements Runnable {1011 private static final long serialVersionUID = -2472397668493332423L;1213 public void start() {14 new Thread(this).start();15 }1617 public void run() {1819 setSize(480, 320); // For AppletViewer, remove later.2021

// Set up the graphics stuff, double-buffering.

22

BufferedImage screen = new BufferedImage(480, 320, BufferedImage.TYPE_INT_RGB);

23 Graphics g = screen.getGraphics();24 Graphics appletGraphics = getGraphics();2526 long delta = 0l;

Page 141: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

2728 // Game loop.29 while (true) {30 long lastTime = System.nanoTime();3132 g.setColor(Color.black);33 g.fillRect(0, 0, 480, 320);3435 // Draw the entire results on the screen.36 appletGraphics.drawImage(screen, 0, 0, null);3738 // Lock the frame rate39 delta = System.nanoTime() - lastTime;40 if (delta < 20000000L) {41 try {42 Thread.sleep((20000000L - delta) / 1000000L);43 } catch (Exception e) {44 // It's an interrupted exception, and nobody cares45 }46 }47 if (!isActive()) {48 return;49 }50 }51 }5253 public boolean handleEvent(Event e) {54 return false;55 }56 }

Running the above code as an applet does nothing more than to sett up the main loop and to paintthe screen black.There are 3 packages in the structure and the respective components will go there.

net.obviam.droids.model will contain all the modelsnet.obviam.droids.view will contain all the renderersnet.obviam.droids.controller will contain all the controllers

Creating the models

The Droid

Droid.java

view source

print?

Page 142: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

01 package net.obviam.droids.model;0203 public class Droid {0405 private float x;06 private float y;07 private float speed = 2f;08 private float rotation = 0f;09 private float damage = 2f;1011 public float getX() {12 return x;13 }14 public void setX(float x) {15 this.x = x;16 }17 public float getY() {18 return y;19 }20 public void setY(float y) {21 this.y = y;22 }23 public float getSpeed() {24 return speed;25 }26 public void setSpeed(float speed) {27 this.speed = speed;28 }29 public float getRotation() {30 return rotation;31 }32 public void setRotation(float rotation) {33 this.rotation = rotation;34 }35 public float getDamage() {36 return damage;37 }38 public void setDamage(float damage) {39 this.damage = damage;40 }41 }

It is a simple java object without any knowledge of the surrounding world. It has a position, rotation, speed and damage. These states are defined by the member variables and are accessible through the getter and setter methods.The game requires a few more models: obstacles and enemies on a map. For simplicity the obstacles will have just a position on the map and the enemies will be standing objects. The map will be a 2 dimensional array holding the enemies, obstacles and the droid. The map will be called Arena to differentiate from the standard Java map and will be populated with obstacles

Page 143: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

and enemies when it is constructed.Obstacle.java

view source

print?

01 package net.obviam.droids.model;0203 public class Obstacle {0405 private float x;06 private float y;0708 public Obstacle(float x, float y) {09 this.x = x;10 this.y = y;11 }1213 public float getX() {14 return x;15 }16 public float getY() {17 return y;18 }19 }

Enemy.java

view source

print?

01 package net.obviam.droids.model;0203 public class Enemy {0405 private float x;06 private float y;07 private int hitpoints = 10;0809 public Enemy(float x, float y) {10 this.x = x;11 this.y = y;12 }1314 public float getX() {15 return x;

Page 144: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

16 }17 public float getY() {18 return y;19 }20 public int getHitpoints() {21 return hitpoints;22 }23 public void setHitpoints(int hitpoints) {24 this.hitpoints = hitpoints;25 }26 }

Arena.java

view source

print?

01 package net.obviam.droids.model;0203 import java.util.ArrayList;04 import java.util.List;05 import java.util.Random;0607 public class Arena {0809 public static final int WIDTH = 480 / 32;10 public static final int HEIGHT = 320 / 32;1112 private static Random random = new Random(System.currentTimeMillis());1314 private Object[][] grid;15 private List<Obstacle> obstacles = new ArrayList<Obstacle>();16 private List<Enemy> enemies = new ArrayList<Enemy>();17 private Droid droid;1819 public Arena(Droid droid) {20 this.droid = droid;2122 grid = new Object[HEIGHT][WIDTH];23 for (int i = 0; i < WIDTH; i++) {24 for (int j = 0; j < HEIGHT; j++) {25 grid[j][i] = null;26 }27 }28 // add 5 obstacles and 5 enemies at random positions29 for (int i = 0; i < 5; i++) {30 int x = random.nextInt(WIDTH);31 int y = random.nextInt(HEIGHT);

Page 145: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

32 while (grid[y][x] != null) {33 x = random.nextInt(WIDTH);34 y = random.nextInt(HEIGHT);35 }36 grid[y][x] = new Obstacle(x, y);37 obstacles.add((Obstacle) grid[y][x]);38 while (grid[y][x] != null) {39 x = random.nextInt(WIDTH);40 y = random.nextInt(HEIGHT);41 }42 grid[y][x] = new Enemy(x, y);43 enemies.add((Enemy) grid[y][x]);44 }45 }4647 public List<Obstacle> getObstacles() {48 return obstacles;49 }50 public List<Enemy> getEnemies() {51 return enemies;52 }53 public Droid getDroid() {54 return droid;55 }56 }

The Arena is a more complex object but reading through the code should make it easy to understand. It basically groups all the models together into a single world. Our game world is thearena which contains all the elements like our droid, enemies and obstacles.

The WIDTH and HEIGHT are calculated based on the resolution I have chosen. A cell (tile) on the grid will be 32 pixels wide and tall so I just compute how many cells go onto the grid.In the constructor (line #19) the grid is set up and 5 obstacles and 5 enemies are randomly placed. This will make up the starting arena and our game world.In order to keep the main loop tidy, we’ll delegate the update and rendering to the GameEngine. This is a simple class that will process the user input, update the states of the models and will render the world. It is a tiny glue framework to make all these happen.The GameEngine.java stub

view source

print?

01 package net.obviam.droids.controller;0203 import java.awt.Event;04 import java.awt.Graphics;05

Page 146: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

06 public class GameEngine {0708 /** handle the Event passed from the main applet **/09 public boolean handleEvent(Event e) {10 switch (e.id) {11 case Event.KEY_PRESS:12 case Event.KEY_ACTION:13 // key pressed14 break;15 case Event.KEY_RELEASE:16 // key released17 break;18 case Event.MOUSE_DOWN:19 // mouse button pressed20 break;21 case Event.MOUSE_UP:22 // mouse button released23 break;24 case Event.MOUSE_MOVE:25 // mouse is being moved26 break;27 case Event.MOUSE_DRAG:28 // mouse is being dragged (button pressed)29 break;30 }31 return false;32 }3334 /** the update method with the deltaTime in seconds **/35 public void update(float deltaTime) {36 // empty37 }3839 /** this will render the whole world **/40 public void render(Graphics g) {41 // empty42 }43 }

To use the engine the Droids.java class needs to be modified. We need to create an instance of the GameEngine class and call the update() and render() methods at the appropriate times. Also we need to delegate the input processing to the engine.Add the following lines:

Declare the private member and also instantiate it.

view source

Page 147: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

1 private GameEngine engine = new GameEngine();

The modified game loop looks like this:

view source

print?

01 while (true) {02 long lastTime = System.nanoTime();0304 g.setColor(Color.black);05 g.fillRect(0, 0, 480, 320);0607 // Update the state (convert to seconds)08 engine.update((float)(delta / 1000000000.0));09 // Render the world10 engine.render(g);1112 // Draw the entire results on the screen.13 appletGraphics.drawImage(screen, 0, 0, null);1415 // Lock the frame rate16 delta = System.nanoTime() - lastTime;17 if (delta < 20000000L) {18 try {19 Thread.sleep((20000000L - delta) / 1000000L);20 } catch (Exception e) {21 // It's an interrupted exception, and nobody cares22 }23 }24 }

The highlighted lines (#7-#10) contain the delegation to the update() and render() methods. Note that there is a conversion to seconds from nano seconds. It’s very useful to work in seconds as we can work with real world values.

Important: The update needs to happen after the delta (time elapsed since the last update) has been calculated. Also the render should be called after the update so it will display the current state of the objects. Note that the screen is cleared each time before the render (painted black).The last thing to be done is to delegate the input handling.

Replace the current handleEvent method with the following snippet:

view source

Page 148: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

1 public boolean handleEvent(Event e) {2 return engine.handleEvent(e);3 }

Very simple straightforward delegation.Running the applet yields no particular exciting result. Just a black screen. It makes sense as everything is just a stub apart from the screen being cleared every cycle.

Initialising the models (world)

Our game needs a droid and some enemies. By design, the world is our Arena. By instantiating it, we have created a world (check the constructor in Arena).We will create the world in the GameEngine as the engine is responsible for telling the view whatto render.

We also need the Droid to be created here because the Arena requires it its constructor. Is good to have it separate as the droid will be controlled by the player.Add the following members to the GameEngine along with the constructor which initialises the world.

view source

print?

01 private Arena arena;02 private Droid droid;0304 public GameEngine() {05 droid = new Droid();06 // position droid in the middle07 droid.setX(Arena.WIDTH / 2);08 droid.setY(Arena.HEIGHT / 2);09 arena = new Arena(droid);10 }

Note: Arena‘s constructor needs to be modified, so the Droid gets added to the grid before the obstacles and enemies.

view source

print?

1 ...2 // add the droid3 grid[(int)droid.getY()][(int) droid.getX()] = droid;4 ...

Page 149: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Running the applet again, won’t change the output but we have our world created. We can add logging to see the result but that won’t be interesting. Let’s create our first view which will reveal our world.

Creating the first View/Renderer

We’ve put a lot of effort in creating the arena and world, we’re eager to actually see it. Because of this, we will create a quick and dirty renderer to reveal the world. By quick and dirty I mean no fancy images or anything but simple squares, circles and placeholders. Once we are happy that the game elements are in we can work on a more elaborate view to replace the squares and circles with fancy graphics. This is where the power of decoupling shines.Steps to render the world.

Draw the grid to see where the cells are.

Obstacles will be drawn as blue squares and they will occupy the cells

Enemies will be red circles

The droid will be a green circle with a brown square

First we create the renderer interface. We use this to establish a single way to interact with the renderer and it will make it easy to create more views without affecting the game engine. To readmore on why is a good idea check this and this.Create an interface in the view package.

Renderer.java

view source

print?

1 package net.obviam.droids.view;23 import java.awt.Graphics;45 public interface Renderer {6 public void render(Graphics g);7 }

That is all. It contains one single method: render(Graphics g). The Graphics g is the canvas that is passed from the applet. Ideally the interface will be agnostic of this and each implementation will use a different back-end but the purpose of this exercise is to describe the MVC not to create a full framework. Because we have chosen applet we need the Graphics object.The concrete implementation looks like this:

Page 150: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

SimpleArenaRenderer.java (in the view package)

view source

print?

01 package net.obviam.droids.view;0203 import java.awt.Color;04 import java.awt.Graphics;0506 import net.obviam.droids.model.Arena;07 import net.obviam.droids.model.Droid;08 import net.obviam.droids.model.Enemy;09 import net.obviam.droids.model.Obstacle;1011 public class SimpleArenaRenderer implements Renderer {1213 private Arena arena;1415 public SimpleArenaRenderer(Arena arena) {16 this.arena = arena;17 }1819 @Override20 public void render(Graphics g) {21 // render the grid22 int cellSize = 32; // hard coded23 g.setColor(new Color(0, 0.5f, 0, 0.75f));24 for (int i = 0; i <= Arena.WIDTH; i++) {25 g.drawLine(i * cellSize, 0, i * cellSize, Arena.HEIGHT * cellSize);26 if (i <= Arena.WIDTH)27 g.drawLine(0, i * cellSize, Arena.WIDTH * cellSize, i * cellSize);28 }2930 // render the obstacles31 g.setColor(new Color(0, 0, 1f));32 for (Obstacle obs : arena.getObstacles()) {33 int x = (int) (obs.getX() * cellSize) + 2;34 int y = (int) (obs.getY() * cellSize) + 2;35 g.fillRect(x, y, cellSize - 4, cellSize - 4);36 }3738 // render the enemies39 g.setColor(new Color(1f, 0, 0));40 for (Enemy enemy : arena.getEnemies()) {41 int x = (int) (enemy.getX() * cellSize);42 int y = (int) (enemy.getY() * cellSize);

Page 151: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

43 g.fillOval(x + 2, y + 2, cellSize - 4, cellSize - 4);44 }4546 // render player droid47 g.setColor(new Color(0, 1f, 0));48 Droid droid = arena.getDroid();49 int x = (int) (droid.getX() * cellSize);50 int y = (int) (droid.getY() * cellSize);51 g.fillOval(x + 2, y + 2, cellSize - 4, cellSize - 4);52 // render square on droid53 g.setColor(new Color(0.7f, 0.5f, 0f));54 g.fillRect(x + 10, y + 10, cellSize - 20, cellSize - 20);55 }56 }

Lines #13 – #17 declare the Arena object and make sure that it is set when the renderer is constructed. I called it ArenaRenderer because we will render the arena (world).

The only method in the renderer is the render() method. Let’s see what it does step by step.#22 – Declare a cell size in pixels. It is 32. It’s hard coded as in the Arena class.#23 – #28 – The grid is being drawn. It is a simple grid. First the colour is set to dark green and lines are drawn at equal distance.

Drawing the obstacles – blue squares#31 – Set the brush color to blue.#32 – #36 – Iterate through all the obstacles in the arena and for each it draws a blue filled rectangle slightly smaller than the cell on the grid.#39 – #44 – Sets the color to red and by iterating through the enemies in the arena, it draws a circle at the respective position.#47 – #54 – Finally draws the droid as a green circle with a brown square on top.

Note that the arena in the real world has a width of 15 (480 / 32). So the droid will always be at the same position (7, 5) and the renderer works out its position on the screen by using a unit measure conversion. In this case is 1 unit in world coordinate is 32 pixels on the screen.By modifying the GameEngine to use the newly created view (SimpleArenaRenderer) we get the result.

view source

print?

01 public class GameEngine {0203 private Arena arena;04 private Droid droid;05 private Renderer renderer;

Page 152: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

0607 public GameEngine() {08 droid = new Droid();09 // position droid in the middle10 droid.setX(Arena.WIDTH / 2);11 droid.setY(Arena.HEIGHT / 2);12 arena = new Arena(droid);1314 // setup renderer (view)15 renderer = new SimpleArenaRenderer(arena);16 }1718 /** ... code stripped ... **/1920 /** this will render the whole world **/21 public void render(Graphics g) {22 renderer.render(g);23 }24 }

Pay attention to the highlighted lines (5, 15, 22). These are the lines where the renderer (view) is added to the game.The result should look like the following image (the positions are random apart from the player’sdroid):

The result of the first view

This is a great view to test out the arena and see the models. It’s extremely easy to create a new view that instead of shapes (squares and circles) displays actual sprites.

Page 153: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Controller for Handling Input and Update Models

So far the game does nothing but displays the current state of the world (arena). For simplicity we will update just one state of the droid, its position.

The steps to move the droid based on user input are:

On mouse up check if the clicked cell on the grid is empty. This means that it does contain any objects which can be Enemy or Obstacle instances.

If the cell is empty, the controller will create an action that will move the droid at a constant speed until it reaches the destination.

view source

print?

01 package net.obviam.droids.controller;0203 import net.obviam.droids.model.Arena;04 import net.obviam.droids.model.Droid;0506 public class ArenaController {0708 private static final int unit = 32;09 private Arena arena;1011 /** the target cell **/12 private float targetX, targetY;13 /** true if the droid moves **/14 private boolean moving = false;1516 public ArenaController(Arena arena) {17 this.arena = arena;18 }1920 public void update(float delta) {21 Droid droid = arena.getDroid();22 if (moving) {23 // move on X24 int bearing = 1;25 if (droid.getX() > targetX) {26 bearing = -1;27 }28 if (droid.getX() != targetX) {29 droid.setX(droid.getX() + bearing * droid.getSpeed() * delta);30 // check if arrived31 if ((droid.getX() < targetX && bearing == -1)

Page 154: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

32 || (droid.getX() > targetX && bearing == 1)) droid.setX(targetX);33 }34 // move on Y35 bearing = 1;36 if (droid.getY() > targetY) {37 bearing = -1;38 }39 if (droid.getY() != targetY) {40 droid.setY(droid.getY() + bearing * droid.getSpeed() * delta);41 // check if arrived42 if ((droid.getY() < targetY && bearing == -1)43 || (droid.getY() > targetY && bearing == 1)) droid.setY(targetY);44 }45 // check if arrived46 if (droid.getX() == targetX && droid.getY() == targetY)47 moving = false;48 }49 }5051 /** triggered with the coordinates every click **/52 public boolean onClick(int x, int y) {53 targetX = x / unit;54 targetY = y / unit;55 if (arena.getGrid()[(int) targetY][(int) targetX] == null) {56 // start moving the droid towards the target57 moving = true;58 return true;59 }60 return false;61 }62 }

The following breakdown explains the logic and important bits.

#08 – The unit represents how many pixels are in a cell which represents 1 unit in world coordinates. It’s hard-coded and not optimal but for the demo is good enough.#09 – The Arena the controller will control. It is set when the controller is constructed (line #16).#12 – The target coordinates of the click in world units.#14 – It is true when the droid is moving. This is the “move” actions’ state. Ideally this should be a stand alone class, but to demonstrate the controller and keep it concise, we’ll hack an action together inside the controller.#20 – The update method that updates the position of the droid according to the time passed at a constant speed. It is extremely simple, it checkes both X and Y positions and if they are not the same as the target position, it updates the droid’s respective position (X or Y) considering its speed. If the droid is in the target position, then the move state variable is updated completing the move action.

Page 155: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

This is not a very well written action, there is no collision checking on obstacles or enemies found along the way, no path finding. It just updates state.

#52 – The onClick(int x, int y) method will be called when the “mouse up” event occurs. Itchecks if the clicked cell is empty and if so, then it starts the “move” action by setting the state variable to true#53-#54 – Converts screen coordinates to world coordinates.This is the controller. To use it, the GameEngine needs to be updated.

The updated GameEngine.java

view source

print?

01 package net.obviam.droids.controller;0203 import java.awt.Event;04 import java.awt.Graphics;0506 import net.obviam.droids.model.Arena;07 import net.obviam.droids.model.Droid;08 import net.obviam.droids.view.Renderer;09 import net.obviam.droids.view.SimpleArenaRenderer;1011 public class GameEngine {1213 private Arena arena;14 private Droid droid;15 private Renderer renderer;16 private ArenaController controller;1718 public GameEngine() {19 droid = new Droid();20 // position droid in the middle21 droid.setX(Arena.WIDTH / 2);22 droid.setY(Arena.HEIGHT / 2);23 arena = new Arena(droid);2425 // setup renderer (view)26 renderer = new SimpleArenaRenderer(arena);27 // setup controller28 controller = new ArenaController(arena);29 }3031 /** handle the Event passed from the main applet **/32 public boolean handleEvent(Event e) {33 switch (e.id) {

Page 156: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

34 case Event.KEY_PRESS:35 case Event.KEY_ACTION:36 // key pressed37 break;38 case Event.KEY_RELEASE:39 // key released40 break;41 case Event.MOUSE_DOWN:42 // mouse button pressed43 break;44 case Event.MOUSE_UP:45 // mouse button released46 controller.onClick(e.x, e.y);47 break;48 case Event.MOUSE_MOVE:49 // mouse is being moved50 break;51 case Event.MOUSE_DRAG:52 // mouse is being dragged (button pressed)53 break;54 }55 return false;56 }5758 /** the update method with the deltaTime in seconds **/59 public void update(float deltaTime) {60 controller.update(deltaTime);61 }6263 /** this will render the whole world **/64 public void render(Graphics g) {65 renderer.render(g);66 }67 }

The changes are highlighted.#16 – Declare the controller.#28 – Instantiate the controller.#46 – Delegating the mouse up event.#60 – Call the update method on the controller.Run the applet and you can click on the map and if the cell is empty, the droid will move there.

Excercises

Create a view that will display images/sprites for entities instead of the drawn shapes.Hint: Use BufferedImage to achieve that.

Extract the move action into a new class.

Page 157: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Add new actions (attack) when an enemy is clicked

Hint:Create a bullet entity that gets fired to the target. You can use the move action with ahigher speed. When the hitpoint gets down to 0, then the enemy is destroyed. Use a different image to represent different states.

Source Code

https://github.com/obviam/mvc-droids or download as zip file.

You can also use git$ git clone git://github.com/obviam/mvc-droids.git

Reference: Building Games Using the MVC Pattern – Tutorial and Introduction from our JCG partner Impaler at the Against the Grain blog.

18

Android Game Development with libgdx – Prototype in a day, Part 1aPublished on May 3, 2012 | 12,104 views | Filed in: Android Games

In this article I will take a detour from the building blocks of a game engine and components andI will demonstrate how to prototype a game quickly using the libgdx library.

What you will learn:

Create a very simple 2D shooter platformer game.

What a complete game architecture looks like.

How to use 2D Graphics with OpenGL without knowing anything about OpenGL.

What different entities make up a game and how they are tied together in a game world.

How to add sound to your game.

How to build your game on the desktop and deploy in onto Android – yes, it’s that magic.

Steps to create a game

1. Have an idea for a game.

2. Draft up some scenarios on paper to resemble your vision and how will it look like.

Page 158: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

3. Analyse the idea, iterate over a few versions by tweaking it and decide what the game will have in its initial version.

4. Pick a technology and start prototyping.

5. Start coding and creating the assets for the game.

6. Play-test, improve, and continuously make small steps towards finishing it.

7. Polish and release!

The Game Idea

Because this will be a one day project, there is very limited time at disposal and the goal is to learn the technology to make games, not the actual process. For this purpose I took the liberty to borrow ideas from other games and focus on the technical aspects of this process.I will be borrowing heavily from a game called Star Guard. It’s a little gem made by Vacuum Flowers. Go get the game and check it out. A very simple shooter platformer with a simplistic style and old school arcade feel.The idea is to guide our hero through the levels by killing enemies and and dodging everything that tries to kill us.The controls are simple, the arrow keys move the hero to the left or right, Z jumps and X shootsthe laser. The longer the jump button is held, the higher the hero jumps. He can change direction in the air and also shoot. We’ll see how we can translate these controls to Android later on.

The next steps (2 and 3) can be skipped over as we will already have this taken care of because of the functioning game.

Start your Eclipse

This is where we start. I will be using libgdx library to create the game. Why libgdx? It’s the bestlibrary (in my opinion) that makes developing games easy without knowing much about the underlying technology. It allows developers to create their games on the desktop and deploy it to Android without any modification. It offers all the elements to use it in games and hides the complexity of dealing with specific technologies and hardware. It will become more obvious as we go along.

Setting up the project

By following the instructions from libgdx’s documentation we have to first download the library.Go to http://libgdx.badlogicgames.com/nightlies/ and download the libgdx-nightly-latest.zip file and unpack it.

Create a simple java project in eclipse. I will call it star-assault.

Page 159: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Leave the default settings and once the project was created, right click on it and select New->Folder and create a directory named libs.From the unpacked libgdx-nighly-latest directory, copy the gdx.jar file into the newly created libs directory. Also copy the the gdx-sources.jar file into the libs directory. It is in the sources sub-directory of the unpacked gdx directory. You can do this by simply dragging thejar files into your directories in eclipse. If you copy them using explorer, or finder or any other means, don’t forget to refresh your eclipse project after by pressing F5.

The structure should look like the following image:

Add gdx.jar as a dependency to the project. Do this by right-clicking the project title and select Properties. On this screen pick Java Build Path and click onto the Libraries tab. Click Add JARs…, navigate to the libs directory and select gdx.jar, then click OK.

In order to have access to the gdx source code and to be able to debug our game easily, it’s a good idea to add the sources to the gdx.jar file. To do this, expand the gdx.jar node, select

Page 160: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Source attachment, click Edit…, then Workspace… and pick gdx-sources.jar then OK until all the pop-up windows are closed.

The complete documentation for setting up projects with libgdx can be found on the official wiki.

This project will be the core project for the game. It will contain the game mechanics, the engine,everything. We will need to create two more projects, basically launchers for the 2 platforms we are targeting. One for Android and one for Desktop. These projects will be extremely simple and will contain only the dependencies required to run the game on the respective platforms. Think of them as the class containing the main method.

Why do we need separate projects for these? Because libgdx hides the complexity of dealing with the underlying operating system (graphics, audio, user input, file i/o, etc.), Each platform has a specific implementation and we will need to include only those implementations (bindings)that are required targeted. Also because the application life-cycle, the asset loading (loading of images, sounds, etc) and other common aspects of an application are heavily simplified, the platform specific implementations reside in different JAR files and only those need to be included that are required for the platform we are targeting.

The Desktop Version

Create a simple java project as in the previous step and name it star-assault-desktop. Also follow the steps to create the libs directory. This time the required jar files from the downloaded zip file are:gdx-natives.jar,

Page 161: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

gdx-backend-lwjgl.jar,gdx-backend-lwjgl-natives.jar.Also add these jar files as dependencies to the project as in the previous project. (right click theproject -> Properties -> Java Build Path -> Libraries -> Add JARs, select the three JARs andclick OK.)We also need to add the star-assault project to the dependencies. To do this, click the Projects tab, click Add, check the star-assault project and click OK.

Important! We need to make the star-assault project a transitive dependency, meaning that dependencies for this project to be made dependencies of projects depending on this. To do this: right click on the main project -> Properties -> Java Build Path -> Order and Export -> check the gdx.jar file and click OK.

The Android Version

For this you will need the Android SDK installed.Create a new Android project in eclipse: File -> New -> Project -> Android Project.Name it star-assault-android. For build target, check “Android 2.3?. Specify a package name net.obviam or your own preference. Next to “Create Activity” enter StarAssaultActivity. Click Finish.

Go to the project directory and create a sub-directory named libs (you can do this from eclipse). From the nightly zip, place gdx-backend-android.jar and the armeabi and armeabi-v7a directories in the newly created libs directory.

Page 162: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

In eclipse, right click the project -> Properties -> Java Build Path -> Libraries -> Add JARs, select gdx-backend-android.jar and click OK.

Click Add JARs again, select gdx.jar under the main project (star-assault) and click OK.Click the Projects tab, click Add, check the main project and click OK twice.This is how the structure should look like:

Important!For ADT release 17 and newer, the gdx jar files need to be explicitly marked to be exported.To do thisClick on the Android ProjectSelect PropertiesSelect Java Build Path (step 1)Select Order and Export (step 2)Check all the references, e.g. the gdx.jar, the gdx-backend-android.jar, the main project etc.(step 3).The following image shows the new state.

Page 163: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Also, more information on this issue here.

Sharing the Assets (images, sounds and other data)

Because the game will be identical on both desktop and Android but each version requires to be built separately from different projects, we want to keep the images, sounds and other data files in a shared location. Ideally this would be in the main project as it is included in both Android and desktop bu because Android has a strict rule on where to keep all these files, we will have to keep the assets there. It is in the automatically created assets directory in the Android project. In eclipse there is the possibility to link directories as in symbolic links on linux/mac or shortcutsin windows. To link the assets directory from the Android project to the desktop project do the following:Right click the star-assault-desktop project -> Properties -> Java Build Path -> Source tab -> Link Source… -> Browse… -> browse to the asssets directory in the star-assault-android project and click Finish. You can also extend the Variables… instead of browsing to the assets directory. It is recommended as it makes the project file system independent.

Also make sure the assets directory is included as a source folder. To do that, right click on the assets directory in eclipse (the desktop project), select Build Path -> Use as Source Folder.

At this stage we are ready with the setup and we can go ahead to work on the game.

Creating the Game

A computer application is a piece of software that runs on a machine. It starts up, does something(even if that’s nothing) and stops in a way or another. A computer game is a specific type of application in which the “does something” part is filled with a game. The start and end is common to all applications. Also the game has a very straight forward architecture based around an continuous loop. You can find out more about the architecture and the loop here and here.

Page 164: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Thanks to libgdx our game can be pieced together as a staged play in a theatre. All you need to do is, to think of the game as a theatrical play. We will define the stages, the actors, their roles and behaviours, but we will delegate the choreography to the player.

So to set up our game/play we need to take the following steps:

1. Start application.

2. Load up all the images and sounds and store them in memory.

3. Create the stages for our play along with the actors and their behaviours (rules for interactions between them).

4. Hand the control to the player.

5. Create the engine that will manipulate the actors on the stage based on the input received from the controller.

6. Determine when the play ends.

7. End the show.

It looks quite simple and it really is. I will be introducing the notions and elements as they appear.

To create the Game we simply need just one class.Let’s create StarAssault.java in the star-assault project. Every class will be created in this project with 2 exceptions.

view source

print?

01 package net.obviam.starassault;0203 import com.badlogic.gdx.ApplicationListener;0405 public class StarAssault implements ApplicationListener {0607 @Override08 public void create() {09 // TODO Auto-generated method stub10 }1112 @Override13 public void resize(int width, int height) {

Page 165: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

14 // TODO Auto-generated method stub15 }1617 @Override18 public void render() {19 // TODO Auto-generated method stub20 }2122 @Override23 public void pause() {24 // TODO Auto-generated method stub25 }2627 @Override28 public void resume() {29 // TODO Auto-generated method stub30 }3132 @Override33 public void dispose() {34 // TODO Auto-generated method stub35 }36 }

Just implement ApplicationListener from gdx and eclipse will generate the stubs for the methods needed to be implemented.These are all the methods that we need to implement from the application lifecycle. It is very simple considering all the setup code needed for Android, or on desktop to initialise the OpenGL context and all those boring (and difficult) tasks.

The method create() is called first. This happens when the application is ready and we can startloading our assets and create the stage and actors. Think of building the stage for the play in a theatre AFTER all the things have been shipped there and prepared. Depending on where the theatre is and how you get there, the logistic can be a nightmare. You can ship things by hand, or by plane or trucks…we don’t know. We’re inside and have the stuff ready and we can start to assemble it. This is what libgdx is doing for us. Shipping our stuff and delivering it regardless of the platform.

The method resize(int width, int height) is called every time the drawable surface is resized. This gives us the chance to rearrange the bits before we go on to start the play. It happens when the window (if the game runs in one) is resized for example.

The heart of every game is the render() method which is nothing more than the infinite loop. This gets called continuously until we decide that the game is over and want to terminate the program. This is the play in progress.

Page 166: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Note: For computers the game over is not equivalent of program over. So it’s just a state. The program is in a state of game over, but is still running.

Of course that the play can be interrupted bu pauses and they can be resumed. The pause() method will be called whenever the application enters into the background on the desktop or Android. When the application comes to the foreground it resumes and the resume() method is being called.When the game is done and the application is being closed, the dispose() is called and this is the time to do some cleanup. It’s similar when the play is over, spectators have left and the stage is being dismantled. No more coming back. More on the lifecycle here.

The Actors

Let’s start taking steps towards the actual game. The first mile-stone is to have a world in which our guy can move. The world is composed of levels and each level is composed of a terrain. The terrain is nothing more than some blocks through which our guy can’t go.

Identifying the actors and entities so far in the game is easy.

We have the guy (let’s call him Bob – libgdx has tutorials with Bob) and the blocks that make up the world.

Having played Star Guard we can see that Bob has a few states. When we don’t touch anything, Bob is idle. He can also move (in both directions) and he can also jump. Also when he’s dead, hecan’t do anything. Bob can be in only one of the 4 identified states at any given time. There are other states as well but we’ll leave them out for now.

The states for Bob:

Idle – when not moving or jumping and is alive

Moving – either left or right at a constant speed.

Jumping – also facing left or right and high or low.

Dead – he’s not even visible and respawning.

The Blocks are the other actors. For simplicity we have just blocks. The level consists of blocks placed in a 2 dimensional space. For simplicity we will use a grid.Turn the start of Star Guard into a block and Bob structure, will look something like this:

Page 167: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The top one is the original and the bottom one is our world representation.

We have imagined the world but we need to work in a measure system that we can make sense of. For simplicity we will say that one block in the world is one unit wide and 1 unit tall. We can use meters to make it even simpler but because Bob is half a unit, it makes him half a meter. Let’s say 4 units in the game world make up 1 meter so Bob will be 2 meters tall.

Page 168: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

It is important because when we will calculate the speed with which Bob runs for example, we need to know what we’re doing.

Let’s create the world.

Our main playable character is Bob.The Bob.java class looks like this:

view source

print?

01 package net.obviam.starassault.model;0203 import com.badlogic.gdx.math.Rectangle;04 import com.badlogic.gdx.math.Vector2;0506 public class Bob {0708 public enum State {09 IDLE, WALKING, JUMPING, DYING10 }1112 static final float SPEED = 2f; // unit per second13 static final float JUMP_VELOCITY = 1f;14 static final float SIZE = 0.5f; // half a unit1516 Vector2 position = new Vector2();17 Vector2 acceleration = new Vector2();

Page 169: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

18 Vector2 velocity = new Vector2();19 Rectangle bounds = new Rectangle();20 State state = State.IDLE;21 boolean facingLeft = true;2223 public Bob(Vector2 position) {24 this.position = position;25 this.bounds.height = SIZE;26 this.bounds.width = SIZE;27 }28 }

Lines #16-#21 define the attributes of Bob. The values of these attributes define Bob’s state at any given time.position – Bob’s position in the world. This is expressed in world coordinates (more on this later).acceleration – This will determine the acceleration when Bob jumps.velocity – Will be calculated and used for moving Bob around.bounds – Each element in the game will have a bounding box. This is nothing more than a rectangle, in order to know if Bob ran into a wall, got killed by a bullet or shot an enemy and hit. It will be used for collision detection. Think of playing with cubes.state – the current state of Bob. When we issue the walk action, the state will be WALKING and based on this state, we know what to draw onto the screen.facingLeft – represents Bob’s bearing. Being a simple 2D platformer, we have just 2 facings. Left and right.

Lines #12-#15 define some constants we will use to calculate the speed and positions in the world. These will be tweaked later on.

We also need some blocks to make up the world.The Block.java class looks like this:

view source

print?

01 package net.obviam.starassault.model;0203 import com.badlogic.gdx.math.Rectangle;04 import com.badlogic.gdx.math.Vector2;0506 public class Block {0708 static final float SIZE = 1f;0910 Vector2 position = new Vector2();11 Rectangle bounds = new Rectangle();

Page 170: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

1213 public Block(Vector2 pos) {14 this.position = pos;15 this.bounds.width = SIZE;16 this.bounds.height = SIZE;17 }18 }

Blocks are nothing more than rectangles placed in the world. We will use these blocks to make up the terrain. We have one simple rule. Nothing can penetrate them.

libgdx note

You might have noticed that we are using the Vector2 type from libgdx. This makes our life considerably easier as it provides everything we need to work with Euclidean vectors. We will use vectors to position entities, to calculate speeds, and to move thing around.

About the coordinate system and units

As the real world, our world has dimensions. Think of a room in a flat. It has a width, height and depth. We will make it 2 dimensional and will get rid of the depth. If the room is 5 meters wide and 3 meters tall we can say that we described the room in the metric system. It is easy to imagine placing a table 1 meter wide and 1 meter tall in the middle. We can’t go through the table, to cross it, we will need to jump on top of it, walk 1 meter and jump off. We can use multiple tables to create a pyramid and create some weird designs in the room.

In our star assault world, the world represents the room, the blocks the table and the unit, the meter in the real world.

If I run with 10km/h that translates to 2.77777778 metres / second ( 10 * 1000 / 3600). To translate this to Star Assault world coordinates, we will say that to resemble a 10km/h speed, we will use 2.7 units/second.

Examine the following diagram of representing the bounding boxes and Bob in the world coordinate system.

Page 171: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The red squares are the bounding boxes of the blocks. The green square is Bob’s bounding box. The empty squares are just empty air. The grid is just for reference. This is the world we will be creating our simulations in. The coordinate system’s origin is at the bottom left, so walking left at10.000 units/hour means that Bob’s position’s X coordinate will decrease with 2.7 units every second.

Also note that the access to the members is package default and the models are in a separate package. We will have to create accessor methods (getters and setters) to get access to them fromthe engine.

Creating the World

As a first step we will just create the world as a hard-coded tiny room. It will be 10 units wide and 7 units tall. We will place Bob and the blocks following the image shown below.

Page 172: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The World.java looks like this:

view source

print?

01 package net.obviam.starassault.model;0203 import com.badlogic.gdx.math.Vector2;04 import com.badlogic.gdx.utils.Array;0506 public class World {0708 /** The blocks making up the world **/09 Array<Block> blocks = new Array<Block>();10 /** Our player controlled hero **/11 Bob bob;1213 // Getters -----------14 public Array<Block> getBlocks() {15 return blocks;16 }17 public Bob getBob() {18 return bob;19 }20 // --------------------2122 public World() {23 createDemoWorld();24 }2526 private void createDemoWorld() {27 bob = new Bob(new Vector2(7, 2));2829 for (int i = 0; i < 10; i++) {30 blocks.add(new Block(new Vector2(i, 0)));31 blocks.add(new Block(new Vector2(i, 7)));32 if (i > 2)33 blocks.add(new Block(new Vector2(i, 1)));34 }35 blocks.add(new Block(new Vector2(9, 2)));36 blocks.add(new Block(new Vector2(9, 3)));37 blocks.add(new Block(new Vector2(9, 4)));38 blocks.add(new Block(new Vector2(9, 5)));3940 blocks.add(new Block(new Vector2(6, 3)));41 blocks.add(new Block(new Vector2(6, 4)));42 blocks.add(new Block(new Vector2(6, 5)));

Page 173: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

43 }44 }

It is a simple container class for the entities in the world. Currently the entities are the blocks andBob. In the constructor the blocks are added to the blocks array and Bob is created. It’s all hard-coded for the time being.

Remember that the origin is in the bottom left corner.

Check out the rest of the tutorial here.

Reference: Getting Started in Android Game Development with libgdx – Create a Working Prototype in a Day – Tutorial Part 1 from our JCG partner Impaler at the Against the Grain blog.

19

Android Game Development with libgdx – Prototype in a day, Part 1bPublished on May 3, 2012 | 6,304 views | Filed in: Android Games

Creating the Game and Displaying the World

To render the world onto the screen, we need to create a screen for it and tell it to render the world. In libgdx there is a convenience class called Game and we will rewrite the StarAssault class a subclass of the Game class provided by libgdx.

About Screens

A game can consist of multiple screens. Even our game will have 3 basic screens. The Start Game screen, the Play Screen and the Game Over screen. Each screen is concerned with the things happening on it and they don’t care about each other. The Start Game screen for examplewill contain the menu options Play and Quit. It has two elements (buttons) and it is concerned about handling the clicks/touches on those elements. It renders tirelessly those two buttons and ifthe Play button is clicked/touched, it notifies the main Game to load the Play Screen and get rid of the current screen. The Play Screen will run our game and will handle everything regarding the game. Once the Game Over state is reached, it tells the main Game to transition to the GameOver screen, whose sole purpose is to display the high scores and listen to clicks on the Replay button.

Let’s refactor the code and create just the main screen for the game for the time being. We will skip the start and game over screens.

The GameScreen.java

view source

Page 174: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

01 package net.obviam.starassault.screens;0203 import com.badlogic.gdx.Screen;0405 public class GameScreen implements Screen {0607 @Override08 public void render(float delta) {09 // TODO Auto-generated method stub10 }1112 @Override13 public void resize(int width, int height) {14 // TODO Auto-generated method stub15 }1617 @Override18 public void show() {19 // TODO Auto-generated method stub20 }2122 @Override23 public void hide() {24 // TODO Auto-generated method stub25 }2627 @Override28 public void pause() {29 // TODO Auto-generated method stub30 }3132 @Override33 public void resume() {34 // TODO Auto-generated method stub35 }3637 @Override38 public void dispose() {39 // TODO Auto-generated method stub40 }41 }

The StarAssault.java will become very simple.

view source

Page 175: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

print?

01 package net.obviam.starassault;0203 import net.obviam.starassault.screens.GameScreen;0405 import com.badlogic.gdx.Game;0607 public class StarAssault extends Game {0809 @Override10 public void create() {11 setScreen(new GameScreen());12 }13 }

GameScreen implements the Screen interface which is very much like an ApplicationListener but it has 2 important methods added.show() – this is called when the main game makes this screen activehide() – this is called when the main game makes another screen active

StarAssault has just one method implemented. The create() does nothing more than to activate the newly instantiated GameScreen. In other words, it creates it, calls the show() methodand will subsequently call its render() method every cycle.

The GameScreen becomes our focus for the next part as it is where the game will live. Remember that the game loop is the render() method. But to have something to render we first need to create the world. The world can be created in the show() method as we don’t have any other screens that can interrupt our gameplay. Currently, the GameScreen is shown only when thegame starts.

We will add two members to the class and implement the render(float delta) method.

view source

print?

01 private World world;02 private WorldRenderer renderer;0304 /** Rest of methods ommited **/0506 @Override07 public void render(float delta) {08 Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);09 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

Page 176: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

10 renderer.render();11 }

The world attribute is the World instance which holds the blocks and Bob.The renderer is a class which will draw/render the world onto the screen (I will reveal it shortly).The render(float delta)Let’s create the WorldRenderer class.WorldRenderer.java

view source

print?

01 package net.obviam.starassault.view;0203 import net.obviam.starassault.model.Block;04 import net.obviam.starassault.model.Bob;05 import net.obviam.starassault.model.World;06 import com.badlogic.gdx.graphics.GL10;07 import com.badlogic.gdx.graphics.OrthographicCamera;08 import com.badlogic.gdx.graphics.glutils.ShapeRenderer;09 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;10 import com.badlogic.gdx.math.Rectangle;1112 public class WorldRenderer {1314 private World world;15 private OrthographicCamera cam;1617 /** for debug rendering **/18 ShapeRenderer debugRenderer = new ShapeRenderer();1920 public WorldRenderer(World world) {21 this.world = world;22 this.cam = new OrthographicCamera(10, 7);23 this.cam.position.set(5, 3.5f, 0);24 this.cam.update();25 }2627 public void render() {28 // render blocks29 debugRenderer.setProjectionMatrix(cam.combined);30 debugRenderer.begin(ShapeType.Rectangle);31 for (Block block : world.getBlocks()) {32 Rectangle rect = block.getBounds();33 float x1 = block.getPosition().x + rect.x;34 float y1 = block.getPosition().y + rect.y;

Page 177: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

35 debugRenderer.setColor(new Color(1, 0, 0, 1));36 debugRenderer.rect(x1, y1, rect.width, rect.height);37 }38 // render Bob39 Bob bob = world.getBob();40 Rectangle rect = bob.getBounds();41 float x1 = bob.getPosition().x + rect.x;42 float y1 = bob.getPosition().y + rect.y;43 debugRenderer.setColor(new Color(0, 1, 0, 1));44 debugRenderer.rect(x1, y1, rect.width, rect.height);45 debugRenderer.end();46 }47 }

The WorldRenderer has only one purpose. To take the current state of the world and render its current state to the screen. It has a single public render() method which gets called by the main loop (GameScreen). The renderer needs to have access to the world so we will pass it in when we instantiate the renderer. For the first step, we will render the bounding boxes of the elements (blocks and Bob) to see what we have so far. Drawing primitives in OpenGL is quite tedious but libgdx comes with a ShapeRenderer which makes this task very easy.The important lines are explained.

#14 – Declares the world as a member variable.#15 – We declare an OrthographicCamera. We will use this camera to “look” at the world from an orthographic perspective. Currently the world is very small and it fits onto one screen, but when we will have an extensive level and Bob moves around in it, we will have to move the camera following Bob. It’s analogous to a real life camera. More on orthographic projections canbe found here.#18 – The ShapeRenderer is declared. We will use this to draw primitives (rectangles) for the entities. This is a helper renderer that can draw primitives like lines, rectangles, circles. For anyone familiar with canvas based graphics, this should be easy.#20 – The constructor which takes the world as the parameter.#22 – We create the camera with a viewport of 10 units wide and 7 units tall. This means that filling up the screen with unit blocks (width = height = 1) will result in showing 10 boxes on the X axis and 7 on the Y.Important: This is resolution independent. If the screen resolution is 480×320, that means that 480 pixels represent 10 units, so a box will be 48 pixels wide. It also means that 320 pixels represent 7 units so the boxes on the screen will be 45.7 pixels tall. It won’t be a perfect square. This is due to the aspect ratio. The aspect ratio in our case is 10:7.#23 – This lines positions the camera to look at the middle of the room. By default it looks at (0,0) which is the corner of the room. The camera’s (0,0) is in the middle as you would expect from a normal camera. The following image shows the world and camera set-up coordinates.

Page 178: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

#24 – The internal matrices of the camera are updated. The update method must be called every time the camera is acted upon (move, zoom, rotate, etc). OpenGL hidden beautifully.The render() method:#29 – We apply the matrix from the camera to the renderer. This is necessary as we positioned the camera and we want them to be the same.#30 – We tell the renderer that we want to draw rectangles.#31 – We will draw the blocks so we iterate through all of them in the world.#32 – #34 – Extract the coordinates of the each block’s bounding rectangle. OpenGL works with vertices (points) so for it to draw a rectangle have to know the coordinates for the starting point and the width. Notice that we work in camera coordinates which coincides with the world coordinates.#35 – Set the color of the rectangles to red.#36 – Draw the rectangle at the x1, y1 with the given width and height.#39 – #44 – We do the same with Bob, but this time the rectangle is green.#45 – We let the renderer know that we’re done drawing rectangles.

We need to add the renderer and the world to the GameScreen (main loop) and see it in action.Modify the GameScreen like this:

view source

print?

01 package net.obviam.starassault.screens;0203 import net.obviam.starassault.model.World;04 import net.obviam.starassault.view.WorldRenderer;0506 import com.badlogic.gdx.Gdx;07 import com.badlogic.gdx.Screen;08 import com.badlogic.gdx.graphics.GL10;0910 public class GameScreen implements Screen {

Page 179: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

1112 private World world;13 private WorldRenderer renderer;1415 @Override16 public void show() {17 world = new World();18 renderer = new WorldRenderer(world);19 }2021 @Override22 public void render(float delta) {23 Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);24 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);25 renderer.render();26 }2728 /** ... rest of method stubs omitted ... **/2930 }

The render(float delta) method has 3 lines. The first 2 lines clear the screen with black and the 3rd line simply calls the renderer’s render() method.The World and WorldRenderer are created when the screen is shown.

To test it on both the desktop and Android, we have to create the launchers for both platforms. Creating the Desktop and Android Launchers

We have created 2 more projects in the beginning.star-assault-desktop and star-assault-android, the latter being an Android project.For the desktop project is dead simple. We need to create a class with a main method in it which instantiates an application provided by libgdx.Create the StarAssaultDesktop.java class in the desktop project.

view source

print?

1 package net.obviam.starassault;23 import com.badlogic.gdx.backends.lwjgl.LwjglApplication;45 public class StarAssaultDesktop {6 public static void main(String[] args) {7 new LwjglApplication(new StarAssault(), "Star Assault", 480, 320, true);8 }9 }

Page 180: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

This is it. Line #7 is where everything happens. It instantiates a new LwjglApplication application passing in a new StarAssault instance which is a Game implementation. The 2nd and 3rd parameters tell the window’s dimension. I opted for 480×320 because it is a resolution supported on many Android phones and I want to resemble it on the desktop. The last parameter tells libgdx to use OpenGL ES 2.Running the application as a normal Java program should produce the following result:

If you are getting some errors, track back and make sure the set-up is correct and all the steps arefollowed, including checking gdx.jar at the export tab on the star-guard Project properties -> Build Path.

The Android Version

In the star-assault-android project there is a single java class called StarAssaultActivity.Change it to:StarAssaultActivity.java

view source

print?

01 package net.obviam.starassault;0203 import android.os.Bundle;0405 import com.badlogic.gdx.backends.android.AndroidApplication;06 import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;07

Page 181: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

08 public class StarAssaultActivity extends AndroidApplication {09 /** Called when the activity is first created. */10 @Override11 public void onCreate(Bundle savedInstanceState) {12 super.onCreate(savedInstanceState);13

AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();

14

config.useAccelerometer = false;

15 config.useCompass = false;16 config.useWakelock = true;17 config.useGL20 = true;18 initialize(new StarAssault(), config);19 }20 }

Pay attention that the new activity extends AndroidApplication.In line #13 an AndroidApplicationConfiguration object is created. We can set all types of configurations regarding the Android platform. They are self explanatory but note that if we wantto use the Wakelock, the AndroidManifest.xml file also needs to be modified. This asks permission from Android to keep the device on and to prevent dimming the screen if we don’t touch it.Add the following line to the AndroidManifest.xml file somewhere inside the <manifest>tags.

view source

print?

1 <uses-permission android:name="android.permission.WAKE_LOCK"/>

Also in line #17 we tell Android to use OpenGL ES 2. This means we will be able to test it only on a device as the emulator does not support OpenGL ES 2. In case there is a problem with it, switch this to false.Line #18 initialises the Android application and launches it.Having a device connected to eclipse, it gets directly deployed and below you can see a photo of the application running on a nexus one. It looks identical to the desktop version.

Page 182: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

The MVC Pattern

It’s quite impressive how far we came in such a short time. Note the use of the MVC pattern. It’s very efficient and simple. The models are the entities we want to display. The view is the renderer. The view draws the models onto the screen. Now we need to interact with the entities (especially Bob) and we will introduce some controllers too.To read more on the MVC pattern, check out my other article or search for it on the net. It’s very useful.

Adding Images

So far it’s all nice but definitely we want to use some proper graphics. The power of MVC comesin handy and we will modify the renderer so it will draw images instead of rectangles.In OpenGL to display an image is quite a complicated process. First it needs to be loaded, turned into a texture and then mapped to a surface which is described by some geometry. libgdx makes this extremely easy. To turn an image from the disk into a texture is a one liner.We will use 2 images hence 2 textures. One texture for Bob and one for the blocks. I have created two images, a block and Bob. Bob is a copycat of the Star Guard chap. These are simple png files and I will copy them into the assets/images directory. I have two images: block.png and bob_01.png. Eventually Bob will become an animated character so I suffixed it with a number (panning for the future).First let’s clean up the WorldRenderer a bit, namely, to extract the drawing of rectangles into a separate method as we will be using it for debug purposes.We will need to load the textures and render them accordingly to the screen.Take a look at the new WorldRenderer.java

view source

print?

01 package net.obviam.starassault.view;0203 import net.obviam.starassault.model.Block;04 import net.obviam.starassault.model.Bob;

Page 183: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

05 import net.obviam.starassault.model.World;06 import com.badlogic.gdx.Gdx;07 import com.badlogic.gdx.graphics.Color;08 import com.badlogic.gdx.graphics.OrthographicCamera;09 import com.badlogic.gdx.graphics.Texture;10 import com.badlogic.gdx.graphics.g2d.SpriteBatch;11 import com.badlogic.gdx.graphics.glutils.ShapeRenderer;12 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;13 import com.badlogic.gdx.math.Rectangle;1415 public class WorldRenderer {1617 private static final float CAMERA_WIDTH = 10f;18 private static final float CAMERA_HEIGHT = 7f;1920 private World world;21 private OrthographicCamera cam;2223 /** for debug rendering **/24 ShapeRenderer debugRenderer = new ShapeRenderer();2526 /** Textures **/27 private Texture bobTexture;28 private Texture blockTexture;2930 private SpriteBatch spriteBatch;31 private boolean debug = false;32 private int width;33 private int height;34 private float ppuX; // pixels per unit on the X axis35 private float ppuY; // pixels per unit on the Y axis36 public void setSize (int w, int h) {37 this.width = w;38 this.height = h;39 ppuX = (float)width / CAMERA_WIDTH;40 ppuY = (float)height / CAMERA_HEIGHT;41 }4243 public WorldRenderer(World world, boolean debug) {44 this.world = world;45 this.cam = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);46 this.cam.position.set(CAMERA_WIDTH / 2f, CAMERA_HEIGHT / 2f, 0);47 this.cam.update();48 this.debug = debug;49 spriteBatch = new SpriteBatch();50 loadTextures();51 }52

Page 184: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

53 private void loadTextures() {54 bobTexture = new Texture(Gdx.files.internal("images/bob_01.png"));55 blockTexture = new Texture(Gdx.files.internal("images/block.png"));56 }5758 public void render() {59 spriteBatch.begin();60 drawBlocks();61 drawBob();62 spriteBatch.end();63 if (debug)64 drawDebug();65 }6667 private void drawBlocks() {68 for (Block block : world.getBlocks()) {69

spriteBatch.draw(blockTexture, block.getPosition().x * ppuX, block.getPosition().y * ppuY, Block.SIZE * ppuX, Block.SIZE * ppuY);

70

}

71 }7273 private void drawBob() {74 Bob bob = world.getBob();75

spriteBatch.draw(bobTexture, bob.getPosition().x * ppuX, bob.getPosition().y * ppuY, Bob.SIZE * ppuX, Bob.SIZE * ppuY);

76

}

7778 private void drawDebug() {79 // render blocks80 debugRenderer.setProjectionMatrix(cam.combined);81 debugRenderer.begin(ShapeType.Rectangle);82 for (Block block : world.getBlocks()) {83 Rectangle rect = block.getBounds();84 float x1 = block.getPosition().x + rect.x;85 float y1 = block.getPosition().y + rect.y;86 debugRenderer.setColor(new Color(1, 0, 0, 1));87 debugRenderer.rect(x1, y1, rect.width, rect.height);88 }89 // render Bob90 Bob bob = world.getBob();91 Rectangle rect = bob.getBounds();92 float x1 = bob.getPosition().x + rect.x;93 float y1 = bob.getPosition().y + rect.y;94 debugRenderer.setColor(new Color(0, 1, 0, 1));95 debugRenderer.rect(x1, y1, rect.width, rect.height);96 debugRenderer.end();97 }98 }

Page 185: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

I’ll point out the important lines:#17 & #18 – Declared constants for the viewport’s dimensions. It’s used for the camera.#27 & #28 – Declare the 2 textures that will be used for Bob and the blocks.#30 – The SpriteBatch is declared. The SpriteBatch takes care of all the texture mapping, displaying and so on for us.#31 – It’s an attribute set in the constructor to know if we need to render the debug screen too or not. Remember, the debug rendering will just render the boxes for the game elements.#32 – #35 – these variables are necessary to correctly display the elements. The width and height hold the screen size in pixels and are passed in from the operating system at the resize step. The ppuX and ppuY are the number of pixels per unit.Because we set the camera to have a view port of 10×7 in world coordinates (meaning we can display 10 boxes horizontally and 7 boxes vertically) and we are dealing with pixels on the end result, we need to map those values to the actual pixel coordinates. We have chosen to work in a 480×320 resolution. That means that 480 pixels horizontally are equivalent of 10 units, meaning a unit will consists of 48 pixels on the screen.If we try to use the same unit for the height (48 pixels) we get 336 pixels (48 * 7 = 336). But we have only 320 pixels available and we want to show the whole 7 blocks height. Doing the same for the vertical part, we get that 1 unit vertically will be 320 / 7 = 45.71 pixels. We need to distortevery image a bit to fit in our world.It’s perfectly fine and OpenGL does that very easily. This happens when we change the aspect ratio on our TV set and sometimes the image gets elongated or squashed to fit everything on the screen, or we just simply choose the option to cut the image off but maintain the aspect ratio.Note: we use float for this, even if the screen resolution deals with ints, OpenGL prefers floats and so do we. OpenGL will work out the dimensions and where to place pixels.#36 – The setSize (int w, int h) method will be called every time the screen is resized and it simply (re)calculates the units in pixels.#43 – The constructor changed just a little but it does very important things. It instantiates the SpriteBatch and loads the textures (line #50).#53 – loadTextures() does what it says: loads the textures. Look how incredibly simple it is. To create a texture, we need to pass in a file handler and it creates a texture out of it. The file handlers in libgdx are very helpful, as we don’t differentiate between Android or deskop, we just specify that we want to use an internal file and it knows how to load it. Note that for the path weskipped assets because assets is used as a source directory, meaning everything from that directory gets copied into the root of the final bundle. So assets acts as a root directory.#58 – the new render() method contains just a few lines.#59 & #62 – enclose a SpriteBatch drawing block/session. Every time we want to render images in OpenGL through the SpriteBatch we have to call begin(), draw our stuff and end()when we’re done. It is important to do that, otherwise it won’t work. You can read more on SpriteBatch here.#60 & #61 – simply call 2 methods to render first the blocks and then Bob.#63 & #64 – if debug is enabled, call the method to render the boxes. The drawDebug method was detailed previously.#67 – #76 – the drawBlocks and drawBob methods are similar. Each method calls the draw method of the spriteBatch with a texture. It is important to understand this.The first parameter is the texture (the image loaded from the disk).The second and third parameters tell the spriteBatch where to display the image. Note that we

Page 186: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

use the conversion of coordinates from world coordinates to screen coordinates. Here is where the ppuX and ppuY are used. You can do the calculations by hand and see where the images get displayed. SpriteBatch by default uses a coordinate system with the origin (0, 0) in the bottom left corner.

That’s it. Just make sure you modify the GameScreen class so the resize gets called on the renderer and also to set the renderer’s debug to true.The modified bits of GameScreen

view source

print?

01 /** ... omitted ... **/02 public void show() {03 world = new World();04 renderer = new WorldRenderer(world, true);05 }0607 public void resize(int width, int height) {08 renderer.setSize(width, height);09 }10 /** ... omitted ... **/

Running the application should produce the following result:without debug

and with debug rendering

Page 187: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Great! Give it a try on Android too and see how it looks.

Processing Input – on Desktop & Android

We’ve come a long way but so far the world is static and nothing interesting is going on. To make it a game, we need to add input processing, to intercept keys and touches and create some action based on those.The control schema on the Desktop is very simple. The arrow keys will move Bob to the left and right, z will make Bob jump and x will fire the weapon. On Android we will have a different approach. We will designate some buttons for these functions and will lay it down on the screen and by touching the respective areas we will consider one of the keys pressed.

To follow the MVC pattern, we’ll separate the class that controls Bob and the rest of the world from the model and view classes. Create the package net.obviam.starassault.controller and all controllers will go there.For the start we will control Bob by key presses. To play the game we to track the status of 4 keys: move left, move right, jump and fire. Because we will use 2 types of input (keyboard and touch-screen), the actual events need to be fed into a processor that can trigger the actions.Each action is triggered by an event.The move left action is triggered by the event when the left arrow key is pressed or a certain area of the screen is touched.The jump action is triggered when the z key is pressed and so on.Let’s create a very simple controller called WorldController.WorldController.java

view source

print?

01 package net.obviam.starassault.controller;

Page 188: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

0203 import java.util.HashMap;04 import java.util.Map;05 import net.obviam.starassault.model.Bob;06 import net.obviam.starassault.model.Bob.State;07 import net.obviam.starassault.model.World;0809 public class WorldController {1011 enum Keys {12 LEFT, RIGHT, JUMP, FIRE13 }1415 private World world;16 private Bob bob;1718

static Map<Keys, Boolean> keys = new HashMap<WorldController.Keys, Boolean>();

19 static {20 keys.put(Keys.LEFT, false);21 keys.put(Keys.RIGHT, false);22 keys.put(Keys.JUMP, false);23 keys.put(Keys.FIRE, false);24 };2526 public WorldController(World world) {27 this.world = world;28 this.bob = world.getBob();29 }3031 // ** Key presses and touches **************** //3233 public void leftPressed() {34 keys.get(keys.put(Keys.LEFT, true));35 }3637 public void rightPressed() {38 keys.get(keys.put(Keys.RIGHT, true));39 }4041 public void jumpPressed() {42 keys.get(keys.put(Keys.JUMP, true));43 }4445 public void firePressed() {46 keys.get(keys.put(Keys.FIRE, false));47 }

Page 189: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

4849 public void leftReleased() {50 keys.get(keys.put(Keys.LEFT, false));51 }5253 public void rightReleased() {54 keys.get(keys.put(Keys.RIGHT, false));55 }5657 public void jumpReleased() {58 keys.get(keys.put(Keys.JUMP, false));59 }6061 public void fireReleased() {62 keys.get(keys.put(Keys.FIRE, false));63 }6465 /** The main update method **/66 public void update(float delta) {67 processInput();68 bob.update(delta);69 }7071 /** Change Bob's state and parameters based on input controls **/72 private void processInput() {73 if (keys.get(Keys.LEFT)) {74 // left is pressed75 bob.setFacingLeft(true);76 bob.setState(State.WALKING);77 bob.getVelocity().x = -Bob.SPEED;78 }79 if (keys.get(Keys.RIGHT)) {80 // left is pressed81 bob.setFacingLeft(false);82 bob.setState(State.WALKING);83 bob.getVelocity().x = Bob.SPEED;84 }85 // need to check if both or none direction are pressed, then Bob is idle86 if ((keys.get(Keys.LEFT) && keys.get(Keys.RIGHT)) ||87 (!keys.get(Keys.LEFT) && !(keys.get(Keys.RIGHT)))) {88 bob.setState(State.IDLE);89 // acceleration is 0 on the x90 bob.getAcceleration().x = 0;91 // horizontal speed is 092 bob.getVelocity().x = 0;93 }94 }95 }

Page 190: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

#11 – #13 – define an enum for the actions Bob will perform. Each keypress/touch can trigger one action.#15 – declare the World that is in the game. We will be controlling the entities found in the world.#16 – declare Bob as a private member and it is just a reference to Bob in the game world, but we will need it as it’s easier to refer to it than retrieving it every time we need him.#18 – #24 – it’s a static HashMap of the keys and their statuses. If the key is pressed, it’s true, false otherwise. It is statically initialised. This map will be used in the controller’s update method to work out what to do with Bob.#26 – This is the constructor that takes the World as the parameter and gets the reference to Bob as well.#33 – #63 – These methods are simple callbacks that are called whenever an action button was pressed or a touch on a designated area happened. These methods are the ones that get called from whatever input we’re using. They simply set the the value of the respective pressed keys in the map. As you can see, the controller is a state machine too and its state is given by the keys map.#66 – #69 – the update method which gets called every cycle of the main loop. currently it does 2 things: 1 – processes the input and 2 – updates Bob. Bob has a dedicated update method whichwe will see later.#72 – #92 – the processInput method polls the keys map for the keys and sets the values on Bob accordingly. For example lines #73 – #78 check if the key is pressed for the movement to the left and if so, then sets the facing for Bob to the left, his state to State.WALKING and his velocity to Bob’s speed but with a negative sign. The sign is because on the screen, left the negative direction (origin is in the bottom left and points to the right).The same thing for the right. There are some extra checks if both keys are pressed or none and in this case, Bob becomes State.IDLE and his horizontal velocity will be 0.

Let’s see what changed in Bob.java.

view source

print?

1 public static final float SPEED = 4f; // unit per second23 public void setState(State newState) {4 this.state = newState;5 }67 public void update(float delta) {8 position.add(velocity.tmp().mul(delta));9 }

Just changed the SPEED constant to 4 units (blocks) per second.Also added the setState method because I forgot it before.The most interesting is the newly acquired update(float delta) method, which is called from

Page 191: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

the WorldController. This method simply updates Bob’s position based on his velocity. For simplicity we do only that without checking his state and because the controller takes care to set the velocity for Bob according to his facing and state. We use vector math here and libgdx helps a lot.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. In Java we have to be careful on how we’re using references as velocity and position are both Vector2 objects. More on vectors here http://en.wikipedia.org/wiki/Euclidean_vector.

We have almost everything, we just need to call the correct events when they happen. libgdx has an input processor which has a few callback methods. Because we are using the GameScreen as the playing surface, it makes sense to use it as the input handler too. To do this, the GameScreen will implement the libgdx InputProcessor.The new GameScreen.java

view source

print?

001 package net.obviam.starassault.screens;002003 import net.obviam.starassault.controller.WorldController;004 import net.obviam.starassault.model.World;005 import net.obviam.starassault.view.WorldRenderer;006007 import com.badlogic.gdx.Gdx;008 import com.badlogic.gdx.Input.Keys;009 import com.badlogic.gdx.InputProcessor;010 import com.badlogic.gdx.Screen;011 import com.badlogic.gdx.graphics.GL10;012013 public class GameScreen implements Screen, InputProcessor {014015 private World world;016 private WorldRenderer renderer;017 private WorldController controller;018019 private int width, height;020021 @Override022 public void show() {023 world = new World();024 renderer = new WorldRenderer(world, false);025 controller = new WorldController(world);026 Gdx.input.setInputProcessor(this);027 }

Page 192: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

028029 @Override030 public void render(float delta) {031 Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);032 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);033034 controller.update(delta);035 renderer.render();036 }037038 @Override039 public void resize(int width, int height) {040 renderer.setSize(width, height);041 this.width = width;042 this.height = height;043 }044045 @Override046 public void hide() {047 Gdx.input.setInputProcessor(null);048 }049050 @Override051 public void pause() {052 // TODO Auto-generated method stub053 }054055 @Override056 public void resume() {057 // TODO Auto-generated method stub058 }059060 @Override061 public void dispose() {062 Gdx.input.setInputProcessor(null);063 }064065 // * InputProcessor methods ***************************//066067 @Override068 public boolean keyDown(int keycode) {069 if (keycode == Keys.LEFT)070 controller.leftPressed();071 if (keycode == Keys.RIGHT)072 controller.rightPressed();073 if (keycode == Keys.Z)074 controller.jumpPressed();075 if (keycode == Keys.X)

Page 193: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

076 controller.firePressed();077 return true;078 }079080 @Override081 public boolean keyUp(int keycode) {082 if (keycode == Keys.LEFT)083 controller.leftReleased();084 if (keycode == Keys.RIGHT)085 controller.rightReleased();086 if (keycode == Keys.Z)087 controller.jumpReleased();088 if (keycode == Keys.X)089 controller.fireReleased();090 return true;091 }092093 @Override094 public boolean keyTyped(char character) {095 // TODO Auto-generated method stub096 return false;097 }098099 @Override100 public boolean touchDown(int x, int y, int pointer, int button) {101 if (x < width / 2 && y > height / 2) {102 controller.leftPressed();103 }104 if (x > width / 2 && y > height / 2) {105 controller.rightPressed();106 }107 return true;108 }109110 @Override111 public boolean touchUp(int x, int y, int pointer, int button) {112 if (x < width / 2 && y > height / 2) {113 controller.leftReleased();114 }115 if (x > width / 2 && y > height / 2) {116 controller.rightReleased();117 }118 return true;119 }120121 @Override122 public boolean touchDragged(int x, int y, int pointer) {123 // TODO Auto-generated method stub124 return false;

Page 194: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

125 }126127 @Override128 public boolean touchMoved(int x, int y) {129 // TODO Auto-generated method stub130 return false;131 }132133 @Override134 public boolean scrolled(int amount) {135 // TODO Auto-generated method stub136 return false;137 }138 }

The changes:#13 – the class implements the InputProcessor#19 – the width and height of the screen used by the Android touch events.#25 – instantiate the WorldController with the world.#26 – set the this screen as the current input processor for the the application. libgdx treats this asa global input processor so each screen has to set a different one if they don’t share the same. In this case the screen itself handles the input.#47 & #62 – we set the active global input processor to null just for cleanup.#68 – the method keyDown(int keycode) is triggered whenever a key is pressed on the physicalkeyboard. The parameter keycode is the value of the pressed key and this way we can poll it and in case it’s a desired key, do something. This is exactly what’s happening. Based on the keys we want, we pass on the event to the controller. The method also returns true to let the input processor know that the input was handled.#81 – the keyUp is the exact inverse of the keyDown method. When the key is released, it simply delegates to the WorldController.#111 – #118 – this is where it gets interesting. This happens only on touch-screens and the coordinates are passed in along with the pointer and button. The pointer is for multi-touch and represents the id of the touch it captures.The controls are utterly simple and are made just for simple demo purposes. The screen is divided into 4 and if the touch falls int to lower left quadrant, it is treated as a move left action trigger and passes the same event as the desktop to the controller.Exactly the same thing for the touchUp.

Warning: – This is very buggy and unreliable, as the touchDragged is not implemented and whenever the finger is dragged across quadrants it will mess up things. This will be fixed of course, the purpose is to demonstrate the multiple hardware inputs and how to tie them together.

Running the application on both desktop and Android will demonstrate the controls. On desktop the arrow keys and on Android by touching the lower corners of the screen will move Bob.On desktop you will notice that using the mouse to simulate touches will also work. This is because touchXXX also handles mouse input on desktop. To fix this add the following line to the beginning of touchDown and touchUp methods:

Page 195: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

view source

print?

1 if (!Gdx.app.getType().equals(ApplicationType.Android))2 return false;

This returns false if the application is not Android and does not execute the rest of the method. Remember that false means that the input was not handled.

As we can see, Bob has moved.

Short Recap

So far we have covered quite a bit of game development and we already have something to show.Gradually we have introduced working pieces into our app and step by step we have achieved something.

We still need to add:

Terrain interaction (block collision, jump)

Animation

A big level and camera to follow Bob

Enemies and a gun to blast them

Sounds

Page 196: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Refined controls and fine tuning

More screens for game over and start

Have more fun with libgdx

Make sure you check out Part 2 (which is still in progress) in order to tick the aforementioned list. But go ahead and do it yourself by all means and any feedback is much appreciated.

Also check out libgdx and its awesome community. The source code for this project can be found here: https://github.com/obviam/star-assault

To check it out with git:git clone [email protected]:obviam/star-assault.git

You can also download it as a zip file.

Reference: Getting Started in Android Game Development with libgdx – Create a Working Prototype in a Day – Tutorial Part 1 from our JCG partner Impaler at the Against the Grain blog.

20

Android Game Postmortem – ArkDroid DevelopmentPublished on December 30, 2011 | 5,334 views | Filed in: Android Games Tags: featured

Hello guys,

As you might have noticed, we have recently delved into the world of mobile game programming. This was done after creating JCG Studios, an independent mobile game studio based on Athens, Greece.

JCG here stands for Just Cool Games, it is our other acronym, except for Java Code Geeks of course.

Our platform of choice is Android and our first attempt of developing a game from scratch resulted in the creation of ArkDroid. As its name suggests, ArkDroid is an Arkanoid clone for Android. It is what we would like to call “Brick Breaker Evolved”.

Page 197: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

ArkDroid features cinematic story line, appealing visual effects, deep space music themes, campaign and free play modes and sophisticated weaponry system among others. We would loveit if you took a look at it and let us know what you think about it.

Having finished the development of ArkDroid a while ago, I would like to share some of the experiences I gathered while being a member of the development team. Consider this as a basic game postmortem, similar to the ones you might have read if you have some experience in game programming.

Let’s begin with a short overview of the game creation. The development team consisted of two people, Byron and me. The development lasted about 4 months, each of us dedicating about 15 hours per week during that period. It was actually a side project running along with our regular jobs and Java Code Geeks. We followed the usual approach of creating both a full version and a lite version.

Following are some insights regarding game programming in general and more specifically about programming for the Android platform.

Page 198: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

R.T.F.M. (Read The Fine Manual)Do yourself a favor and make sure you have a good grasp of the Android fundamentals before embarking on the journey of making an Android game. Check out the developer’s guide and make sure to bookmark the Javadoc pages. These are also available in the Android SDK for offline browsing. It would be quite easy to get started if you have previous experience into making games, but make sure you dedicate the appropriate time before delving into the magic world of Android game programming. Our Android tutorials could be of help for this. We also recently introduced Android Game Development Tutorials.

Collaborate EfficientlyCollaboration is critical when a distributed team is involved. Don’t worry, nothing fancy is required. For our online communication, we used Skype and for a loose “project management” we played with Google Docs. A text document and a spreadsheet should be more than enough fortwo people in order to track bugs and assign new features. Regarding the code itself, a versioningsystem goes without saying. We decided to go with good-old Subversion, since this is what we have the most experience with, but any modern source management tool would be fine. There arealso a bunch of sites that provide private repositories, do your search.

Rev up your engineResist falling victim of the “Not Invented Here” syndrom and embrace the power that a game engine can give you. When starting development, we evaluated some of the available Android game engines and we decided to go with the very nice AndEngine. AndEngine is quite mature, provides an abundance of features and shortcuts and I guarantee that it will help you kick-start your project in no time. It should definitely be noted tha libgdx was a close second and we decided to skip it because it is a bit low level for us. We decided in favour of the lower development time that AndEngine ensures. That being said, if performance is critical to your game’s success, libgdx is a no-brainer. As an added bonus, libgdx is cross-platform, meaning thatit can be used to write both desktop and mobile (Android) games.

Page 199: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Know thy engineAs stated above, AndEngine was used to provide the core framework for building our game. Before writing a single line code however, we made sure to got through all the available tutorials. Unfortunately, there are no Javadocs (weird) so you will have to rely only on the examples and the public forums. And hey, you got the source code available, right?

Hit that deviceOne of the most major issues we had during development was the ridicuslouly slow time that the applications take in order to be deployed into the SDK’s emulator. I mean come on, I have a cutting edge laptop and it takes forever (ok about a minute and so) to redeploy the game on it. For this reason, Byron and I made sure to purchase real devices for ourselves and perform the majority of debugging and testing on them instead of the emulator.

Test, test, testAnd yes, as you might have guessed, I mean test in the real device. You have to test the game in every possible way. Act as a non-experienced mobile user. Provide random input and witness how your game is going to react on that. Make sure that all corners are covered. Be warned, due to the nature of games, it might be difficult to even reproduce a bug, let alone debug the game and fix it.

Cover the spectrumAndroid fragmentation is a real thing and it can be a major PITA. Different resolutions, screen sizes, CPU powers and the list goes on. So, if you are thinking of Android game programming in a more professional way, you will have to get more that one device in order to cover all bases, from low-end to the high-end devices.

GC is your enemyGood games provide first of all a smooth experience to their players. You have to avoid hiccups

Page 200: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

during game play and as you might have guessed, hiccups are caused by Garbage Collections in Android. It is really a “stop the world” procedure which unfortunately gets noticed by the users. The best advice on this is to make absolutely sure that you do not create unnecessary objects. Your game consists actually of a main loop, that is executed multiple times per second, so this makes things worse. The resources are rather scarce in the mobile world, so proceed with big caution.

Be PatientYou probably have heard all those stories about creating a “game” in a weekend or a “few hours”time. Yeah, right… Let me warn you, creating a non-trivial game requires a great amount of effort and above all, patience.

Assets? What is this?Ok, Byron and I are programmers at heart. Hardcore. Creating “art” sounds a bit bizarre to us. I believe that the term programmer’s art is a very successful and representative one. If you can afford to hire someone to create your graphics and sound, do it without thinking twice. Otherwise, you will have to make the most out of the available tools. We used GIMP for our image editing needs and I think that we actually managed to create some decent art work (mainlyByron).

Beta testers wantedWhen near the end of development, make sure to beta test your game. Find some friends or relatives and let them experiment with your game. Ideally, you should be around when they play with it. Watch them and see what they liked, what troubled them and what felt weird to them. This feedback is invaluable, trust me on that. We were lucky enough to have some great beta testers which helped us track some bugs and gave helpful advice (thank you Pelagia, Eleftheria, Ben).

Page 201: Android Game Development Tutorialsdocshare03.docshare.tips/files/25375/253753972.pdf · Android platform. A new category named “Android Games” has been created in order to contain

Just shipIt is quite common among developers to find unfinished projects. Applications that could have changed the world and games that could have written history, but instead they gather dust forgotten inside old hard disks. Fight all excuses and take the dive:- I cannot ship yet, it is not done…- Just ship…- Hey, this function does not perform as well…- Just ship!- But I haven’t finished feature X…- Just ship!!- Yes, but my competition has feature Y…- Just ship!!- With only 100 levels?…- Just ship!!!Just ship the thing, get your user’s feedback and build on that.

Don’t quit your day job just yetThis is a very common advice but I would like to repeat it here. Don’t rush into making quick decisions like quitting your day job. Mobile market is a very strange beast and while it could make you a millionnaire, it could also leave you scratching your head as why your super-duper game does not make a damned sell.

Game development is life changingI personally come from a hardcore enterprise programming background (JEE to the max). You probably know the drill: persist some data, commit that transaction, generate some reports, movethe data again, etc etc. This can get boring after a while. Game dev however is a totally refreshing change, a brave new world that I am happy to have found.

Enjoy the gameFinally, make sure that you make something you actually like yourself. If you get bored by your very own game, it is almost certain that you will drop out midway… or that you will end up witha horrible game. We decided to start our endeavor with an all-time classic. Who does not love Arkanoid?

So, that’s all folks… Don’t forget to share! And of course, do not forget to check out our new Android Game, ArkDroid. You feedback will be more than helpful!