Smartphones

Capture the flag: A tutorial on Android's Canvas class and Touch event handler

Android developer William Francis takes a break from writing business apps and shows how to code a simple electronic game of capture the flag.

Several weeks ago I wrote a tutorial aimed at helping budding developers play around with Android's multimedia libraries, and I've received a good response from aspiring young developers (my teenage son was the inspiration for the post) and educators alike. The positive reaction is why I decided to write another tutorial of a similar vein. This tutorial will demonstrate Android's Canvas class, and a simple technique for drawing bitmaps on it. The tutorial also covers getting Touch events from the user, and a rudimentary collision detection algorithm.

There is a little more code involved in this tutorial than its predecessor, but don't fret -- none of it is complicated and in the end you will be rewarded with a complete (albeit simple) electronic game of capture the flag (Figure A). Let's get started. (If you prefer to download and import the entire project into Eclipse, you can grab it here.) Figure A

Instructions on how to create capture the flag

Step one: Create a new Android project inside of Eclipse. There are some advanced Touch event techniques (such as multi-touch) that can only be accessed in later versions of the Android SDK, but for our game we'll just use a simple ACTION_DOWN motion. This means you are free to target any SDK greater or equal to 1.6. Step two: Find an image to represent the flag. Create a /drawble folder under your /res directory and copy your image into it. Step three: Now we need a layout. Edit the main.xml file in the /res/layout folder. The layout is straight-forward with one exception: It has an element called com.authorwjf.GameBoard that we will create ourselves and include in the project. According to the Android SDK documentation, you can reference any class in your layout this way as long as that class extends the built-in View class. Nifty!
main.xml
<?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:id="@+id/the_label"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:gravity="center"

android:textSize="20sp"

android:layout_marginBottom="10dip"

android:text="Custom drawing surface demo."/>

<Button

android:id="@+id/the_button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:gravity="center"

android:layout_marginBottom="10dip"

android:text="Hide the Flag!"/>

<com.authorwjf.GameBoard

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:id="@+id/the_canvas"/>

</LinearLayout>
Step four: Define an enum called Indicators in our /src directory before moving on to the GameBoard class.
Indicators.java
package com.authorwjf;
public enum Indicators {

BULLSEYE,

HOT,

WARM,

COLD;

}
Step five: Turn your attention to the GameBoard class, which is the heart of our project. The GameBoard class extends the View class, and acts as our canvas where we do our drawing. To start with, let's concentrate on the constructor. There are several private variables as well as imports not used at this point. Don't worry -- we'll get to them. For now just pay attention to the fact that we are creating a global instance of our bitmap, as well as a paintbrush.
Main.java
package com.authorwjf;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
public class GameBoard extends View{
private int mFlagX = -1;
private int mFlagY = -1;
private Bitmap mBitmap = null;
private Paint mPaint = null;
private boolean isFlagHidden = false;
private int mBoundX = -1;
private int mBoundY = -1;
public final int CLOSER = 50;
public final int CLOSE = 100;
public GameBoard(Context context, AttributeSet aSet) {
super(context, aSet);

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.white_flag);

mPaint = new Paint();

mPaint.setColor(Color.DKGRAY);

}

}

Gotcha! If you want to reference a class inside your own layouts as we have done, you must implement the constructor for the View class that includes the AttributeSet parameter. Failing to do so will result in a vague runtime error that will have you scratching your head and scouring the Android news groups.

Step six: Create a public method our Main.java class can use to hide the flag. We will use the math libraries to create a random number between 0 and the max view width and height. I'll discuss getting the view width and height later. For the purpose of this method, know that mBoundX contains the view width, and mBoundY contains the view height. Also, in case you are wondering, the call to the function invalidate() forces our re-draw code to execute.
public void hideTheFlag(){
mFlagX = (int) Math.ceil(Math.random() * mBoundX);
mFlagY = (int) Math.ceil(Math.random() * mBoundY);
isFlagHidden = true;

invalidate();

}
See steps seven through 12 of this Android tutorial.

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

1 comments
Paulo Cezar
Paulo Cezar

Great article, presenting a complete app step by step. Thanks for sharing.