This semester Robert Sommeregger, Thomas Czernik and I will create an Android game
The goal of the game will be to get out of the way of obstacles using the Androids phone acceleration sensors. The setting will be under water.
In order to get into Android programming we wanted to test how fluid a 4 megapixel image could be moved around the screen. To be able to move such an image we needed a thread to update the position and to redraw our Canvas view.
The first idea was to have a thread which updates the coordinates where the picture should be drawn on the screen and then call a redraw() function. We soon realized that a Canvas could only be forced to redraw itself by invalidating it. But there is a security feature of android that only allows Activities to invalidate Views if it is a children of the Activity. We had a Class UpdateThread which implements the Runnable interface: (Game extends Canvas and draws our Picture)
public class main extends Activity {
private Game game;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
game = new Game(this);
setContentView(game);
Thread myThread = new Thread(new UpdateThread());
myThread.start();
}
public class UpdateThread implements Runnable {
@Override
public void run() {
//... code to manipulate position
}
}
}
}
If you now try to call game.invalidate() from this run() function Android will throw an exception because game is not a child of UpdateThread. The solution is to implement a handler which can communicate with our thread – it is building a interface between our thread and the main class. We insert the following in the main class:
public Handler updateHandler = new Handler(){
/** Gets called on every message that is received */
// @Override
public void handleMessage(Message msg) {
game.update();
game.invalidate();
super.handleMessage(msg);
}
};
We fill our run() method with this code:
while(true){
main.this.updateHandler.sendEmptyMessage(0);
}
Now each thime main.this.updateHandler.sendEmptyMessage(0) is called the handler reacts. The point is that our handler now can call game.invalidate() because game is a child of main.
Here is the full code:
main.java
package muhkuh.app;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
public class main extends Activity {
private Game game;
public Handler updateHandler = new Handler(){
/** Gets called on every message that is received */
// @Override
public void handleMessage(Message msg) {
game.update();
game.invalidate();
super.handleMessage(msg);
}
};
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
game = new Game(this);
setContentView(game);
Thread myThread = new Thread(new UpdateThread());
myThread.start();
}
public class UpdateThread implements Runnable {
@Override
public void run() {
while(true){
main.this.updateHandler.sendEmptyMessage(0);
}
}
}
}
game.java
package muhkuh.app;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class Game extends View {
private Bitmap image;
private Paint paint;
private int x=0;
public Game(Context context) {
super(context);
image = Bitmap.createBitmap(BitmapFactory.decodeResource(this.getResources(), R.drawable.test));
paint = new Paint();
}
// called every Frame
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(image, x, 0, paint);
}
// called by thread
public void update() {
if(x < 200)
x++;
else
x=0;
}
}
Thanks for this useful snippet of code – it is just what I am looking for with regards to my own Android tutorial: http://www.quesucede.com/page/show/id/conway_game_of_life_android.
Brett Kromkamp
Nice site. I just bookmarked you on my bloglines.
Sent from my iPad 4G
Does the iPad automatically put a signature inside blog responses like the one above? Or does the user have to type it in? It’s lame either way.
thanks for sharing this good post