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
Thanks – I was looking for a demo that shows something basic and this really helped! There isn’t a lot of documentation out there that hides the details so you can focus on the simple things first.
wonderful example of me
Hi , i am using livewallpaper in which i have created a canvas which has many bitmaps drawn over it , now i just want to replace one bitmap by another after specific time interval , but the problem is if load a new bitmap , i lost the old bitmaps which were already drawn … so can you tell me how can i preserve the bitmaps and update only part of a canvas. ?
@hunt why don’t you throw your bitmaps in an array and change which one is displayed in your update code.
Looks great thanks. Small correction: in Java you usually name classes with capital letters (main-> Main).
hey do you have and code snippets for throwing balls(or any object) using slingshot. then please mail it to mohankul123@gmail.com
You’re the best, no other tutorial on threading would work. Thank you so much, I really owe you.
thanks !!! very useful I begin to learn the basics of android programming and your code snipets help a lot !
throwing wxception in oncreate() what is the problem?
Very useful code snippet and good example… Thanks a lot