Moving Images on the Screen with Android
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
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 this we 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.
package net.obviam.droidz.model.components;
public class Speed {
public static final int DIRECTION_RIGHT = 1;
public static final int DIRECTION_LEFT = -1;
public static final int DIRECTION_UP = -1;
public static final int DIRECTION_DOWN = 1;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
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.
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:
this.gamePanel.update();
The run() method:
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// update game state
this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
this.gamePanel.render(canvas);
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
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 droid is moving we will introduce a basic collision detection with the walls. The logic is simple. Check if 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
public void update() {
// check collision with right wall if heading right
if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
droid.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
droid.getSpeed().toggleXDirection();
}
// check collision with bottom wall if heading down
if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
droid.getSpeed().toggleYDirection();
}
// check collision with top wall if heading up
if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
droid.getSpeed().toggleYDirection();
}
// Update the lone droid
droid.update();
}
getWidth() and getHeight() return the width and height of the view. The panel is a view, remember?
The Droid.java file’s update() method:
public void update() {
if (!touched) {
x += (speed.getXv() * speed.getxDirection());
y += (speed.getYv() * speed.getyDirection());
}
}
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.


thanks to all
Hi
Thank you very much for this tutorial…
I am currently working on a horse riding app and I have a problem when moving a horse image. It can move but it is always facing the same direction how do I change the horse to face the direction its moving to?
Thanking you inadvance..
Nonceba.
Hey Impaler,
Supercool that you made these tutorials. I started copying and modifying your code and ended up with http://bit.ly/HWapplez .. now,I’m working on extra levels, moving fruits and so on. So I’m glad I can use this Speed tutorial and in time, will start looking for one on rotation
Keep it up!
Regards, Kees.
Hi, Great tutorials, using this code I am making the droid go in a circle by changing public void update() to :
public void update() {
intTmpX=0;
intTmpY=0;
random = angle * 2.0 * Math.PI/360.0;
intTmpX = (int) (Math.cos(random) * 200);
intTmpY = (int) (Math.sin(random) * 200);
intTmpX += intAppWidth/2;
intTmpY += intAppHeight/2;
droid.setX(intTmpX);
droid.setY(intTmpY);
angle++;
//Log.d(TAG, “Menu | Angle:”+angle+” | X:”+intTmpX+” | Y:”+intTmpY);
droid.update();
}
It runs great except when I open a menu, the menu freezes and eventually the app becomes un-responsive. The droid is still merrily going round and round though..
i am trying to start the bot on the bottom of the page. when he is created i cant seem to put any dynamic values in that register the 50 works and 300 is roughly where i want but if its a different size screen then it falls apart based on what i am doing.
droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 50, 50);
Hi,
First, thank you for the time and effort to share this most ~awesome~ tutorial.
I’ve done a bit of game programming myself (though not in android) and I thought I’d share an alternative approach to moving sprites about the screen with a vector class. I have created a general purpose Java vector class that represents the a vector as X, Y coords in the cartesian coordinate system. I’ve provided methods and utilities to compute magnitude and orientation in degrees.
The vector makes moving sprites about easy:
– Simply give each sprite two vector memember variables; (a) location and (b) velocity.
– To update a sprite’s position in the game loop update simply add velocity to the given location at update time:
location.add( velocity )
– Also, it’s easy to move in any direction given that the velocity has orientation built in. You can set the sprites direction of movement by simply by specifying the speed and orientation of the velocity vector. Just be careful, because the Y axis is inverted in the Android view pane, so you have to account for that when you specify orientation (i.e., invert the Y axis.
Here’s the code. I’m interested to know what game dev enthusiasts think.
///// Nick’s Vector Code ///////////////
package nn.ff;
/**
* Dr. Nick’s Vector Class
*
* This class defines a vector for use in moving 2D Sprites.
* In addition to basic vector operations the class contains
* utility functions for such things as getting a vector given
* magnitude and orientation, and adding two vectors.
*
* @author Nick Nagel
* @date 2010.02.02
*/
public class Vector2D
{
private static final String TAG = Vector2D.class.getSimpleName();
private double x, y;
/**
* Constructs a vector instance given x, y coordinates…
*
* @param x vector coord x
* @param y vector coord y
*/
public Vector2D( double x, double y )
{
this.x = x;
this.y = y;
}
/**
* Set the x and y coordinates of this vector.
*
* @param x
* @param y
*/
public void setVectorCoords(double x, double y)
{
this.x = x;
this.y = y;
}
/**
* Accessor for x component
* @return
*/
public double getX()
{
return x;
}
/**
* Accessor for y component
* @return
*/
public double getY()
{
return y;
}
public String toString( )
{
return “[" + x + ", " + y + "]“;
}
/**
* Adds a vector to THIS vector (changing THIS vector’s x, y coords)
*/
public void addVector( Vector2D vAdd )
{
this.x = this.x + vAdd.x;
this.y = this.y + vAdd.y;
}
/**
* Returns a scalar representing the vector’s orientation in degrees
* FROM X AXIS.
*
* @return orientation (in degrees) of vector
*/
public double getOrientation()
{
// GIVEN X AND Y COORDINATES…
// (1) COMPUTE TANGENT
// (2) GET ARCTAN
// (3) CONVERT TO DEGREES
double tan = 0;
if( this.x != 0 )
{
tan = this.y / this.x;
}
else
{
if( y > 0 ) return( 90 );
else if( y 0 ) && (this.y==0) )
{
degrees = 0; // because division by 0 is undefined
}
else if( (this.x > 0) && (this.y > 0) ) // Quadrant I
{
degrees = degrees;
}
else if( (this.x 0) ) // Quadrant II
{
degrees = degrees + 180; // theta is given in – degrees
}
else if( (this.x < 0) && (this.y 0) && (this.y < 0) ) // Quadrant IV
{
degrees = degrees + 360; // theta is given in – degrees
}
return degrees;
}
/**
* Returns a scalar representing the vector's magnitude.
*
* @return magnitude of vector
*/
public double getMagnitude()
{
return( Math.sqrt( x*x + y*y ) );
}
/**
* Adds two vector objects and returns a new
* vector representing the sum.
*/
public static Vector2D addVectors( Vector2D v1, Vector2D v2 )
{
return new Vector2D( (v1.x + v2.x), (v1.y + v2.y) );
}
/**
* Vector Utility Returns a new vector given magnitude
* and orientation in degrees from x-axis…
*
*/
public static Vector2D getVector2D( double magnitude, double orientation )
{
// Implementation notes:
//
// The vector components are:
//
// (1) Vx is determinable from the cosine of
// the angle as follows:
//
// Vx = |v| cos theta[x]
//
// (2) Vy is determinable from the sine of
// the angle:
//
// Vy = |v| cos theta[y] = |v| sin theta[x]
double x = magnitude * Math.cos( orientation * (Math.PI / 180) );
double y = magnitude * Math.sin( orientation * (Math.PI / 180) );
return( new Vector2D( x, y ) );
}
/**
* Just used main for TDD…
*
* @param args
*/
public static void main(String[] args)
{
//Log.d(TAG, "TEST");
Vector2D vTestObj = new Vector2D( 100d, 100d );
System.out.println(vTestObj);
System.out.println( vTestObj.getMagnitude() );
System.out.println( vTestObj.getOrientation() );
/* orientation tests
vTestObj.setVectorCoords( 0, 0 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 100, 0 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 0, 100 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( -100, -100 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 100, 10 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 10, -100 );
System.out.println( vTestObj.getOrientation() );
*/
Vector2D vTestObj2 = Vector2D.getVector2D(1.4, 45);
System.out.println( vTestObj2 );
vTestObj.addVector(vTestObj2);
System.out.println( vTestObj );
System.out.println( Vector2D.addVectors(vTestObj, vTestObj2) );
vTestObj.setVectorCoords(1, 0.5);
System.out.println( vTestObj.getOrientation() );
}
}
/////////////////////////////////////////
First, THANK YOU FOR THIS AWESOME TUTORIAL.
Second; not to detract, but I have a different vector class which I developed for my own game dev efforts and have found quite easy to use (though painful to develop
) Anyway, I post it here ‘cuz it’s a nice alternative to consider for moving sprites around. Also, it encapsulates the vector operations in a single class. The trig is all spelled out for those who’ve wrestled with understanding the vector math…
////////////////////////////////////////////////
package nn.ff;
/**
* My Vector Class
*
* This class defines a vector for use in moving 2D Sprites.
* In addition to basic vector operations the class contains
* utility functions for such things as getting a vector given
* magnitude and orientation, and adding two vectors.
*
* @author Nick
* @date 2010.08.15
*/
public class Vector2D
{
private double x, y;
/**
* Constructs a vector instance given x, y coordinates…
*
* @param x vector coord x
* @param y vector coord y
*/
public Vector2D( double x, double y )
{
this.x = x;
this.y = y;
}
/**
* Set the x and y coordinates of this vector.
*
* @param x
* @param y
*/
public void setVectorCoords(double x, double y)
{
this.x = x;
this.y = y;
}
/**
* Accessor for x component
* @return
*/
public double getX()
{
return x;
}
/**
* Accessor for y component
* @return
*/
public double getY()
{
return y;
}
public String toString( )
{
return “[" + x + ", " + y + "]“;
}
/**
* Adds a vector to THIS vector (changing THIS vector’s x, y coords)
*/
public void addVector( Vector2D vAdd )
{
this.x = this.x + vAdd.x;
this.y = this.y + vAdd.y;
}
/**
* Returns a scalar representing the vector’s orientation in degrees
* FROM X AXIS.
*
* @return orientation (in degrees) of vector
*/
public double getOrientation()
{
// GIVEN X AND Y COORDINATES…
// (1) COMPUTE TANGENT
// (2) GET ARCTAN
// (3) CONVERT TO DEGREES
double tan = 0;
if( this.x != 0 )
{
tan = this.y / this.x;
}
else
{
if( y > 0 ) return( 90 );
else if( y 0 ) && (this.y==0) )
{
degrees = 0; // because division by 0 is undefined
}
else if( (this.x > 0) && (this.y > 0) ) // Quadrant I
{
degrees = degrees;
}
else if( (this.x 0) ) // Quadrant II
{
degrees = degrees + 180; // theta is given in – degrees
}
else if( (this.x < 0) && (this.y 0) && (this.y < 0) ) // Quadrant IV
{
degrees = degrees + 360; // theta is given in – degrees
}
return degrees;
}
/**
* Returns a scalar representing the vector's magnitude.
*
* @return magnitude of vector
*/
public double getMagnitude()
{
return( Math.sqrt( x*x + y*y ) );
}
/**
* Adds two vector objects and returns a new
* vector representing the sum.
*/
public static Vector2D addVectors( Vector2D v1, Vector2D v2 )
{
return new Vector2D( (v1.x + v2.x), (v1.y + v2.y) );
}
/**
* Vector Utility Returns a new vector given magnitude
* and orientation in degrees from x-axis…
*
*/
public static Vector2D getVector2D( double magnitude, double orientation )
{
// Implementation notes:
//
// The vector components are:
//
// (1) Vx is determinable from the cosine of
// the angle as follows:
//
// Vx = |v| cos theta[x]
//
// (2) Vy is determinable from the sine of
// the angle:
//
// Vy = |v| cos theta[y] = |v| sin theta[x]
double x = magnitude * Math.cos( orientation * (Math.PI / 180) );
double y = magnitude * Math.sin( orientation * (Math.PI / 180) );
return( new Vector2D( x, y ) );
}
/**
* Just used main for TDD…
*
* @param args
*/
public static void main(String[] args)
{
//Log.d(TAG, "TEST");
Vector2D vTestObj = new Vector2D( 100d, 100d );
System.out.println(vTestObj);
System.out.println( vTestObj.getMagnitude() );
System.out.println( vTestObj.getOrientation() );
/* orientation tests
vTestObj.setVectorCoords( 0, 0 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 100, 0 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 0, 100 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( -100, -100 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 100, 10 );
System.out.println( vTestObj.getOrientation() );
vTestObj.setVectorCoords( 10, -100 );
System.out.println( vTestObj.getOrientation() );
*/
Vector2D vTestObj2 = Vector2D.getVector2D(1.4, 45);
System.out.println( vTestObj2 );
vTestObj.addVector(vTestObj2);
System.out.println( vTestObj );
System.out.println( Vector2D.addVectors(vTestObj, vTestObj2) );
vTestObj.setVectorCoords(1, 0.5);
System.out.println( vTestObj.getOrientation() );
}
}
///////////////////////////////////////////
Just a quick thought, are you moving the sprite by an absolute/explicit value? (i.e, specifying 1 pixel)? If so, will this not cause the sprite to move slower on a higher density screen and faster on a lower density screen? If so, how do you get around this? Thanks!
does anyone know how to pause the thread when i start a new activity and how to resume it when a button is pressed on that new activity?
Thanks
I also found a bug in the droid class , handleActionDown method.
I changed this line
if (eventY >= (y – bitmap.getHeight() / 2) && (y = (y – bitmap.getHeight() / 2) && (eventY <= (y + bitmap.getHeight() / 2))) {
Cut my comment off
to
if (eventY >= (y – bitmap.getHeight() / 2) && (eventY <= (y + bitmap.getHeight() / 2))) {
I have the same issue mentioned above , when i exit the app using home and come back, the touch events no longer work and the app becomes unresponsive, any ideas?
I guess it is because of the multithreaded nature and the update thread is not stopped when the the onPause is triggered.
I think on Android, the multi-threaded approach is better to be avoided. In the case multiple threads are used, the threads need to be stopped or suspended when Android goes switches to another app and onResume the threads should be resumed or re-created.
View.invalidate() should be used to redraw the screen.
I’ll try to find some time to rework it a bit.
i fixed it adding two lines , in two methods, if any one is interested.
@Override
public void surfaceCreated(SurfaceHolder holder) {
//Added below line
thread = new MainThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
…
try {
//Added the line below
thread.setRunning(false);
thread.join();
…
}
Hi Impaler
Can u tell me how to create Grid Structure and move these images in that grid structure…similar to coins moving in chess board and checker game..do u know how to do that…
Hi, First off I really enjoyed this tutorial!
I noticed that the app messes up when you press the home button and enter back into it. The bitmap does not remain in the location it was in when home is pressed, and the app no longer registers when I touch the screen. Furthermore if I enter back in and wait a few seconds I get “application is not respnding”. I’m guessing this is something to do with onPause and onResume? How can I fix this?
Thanks
I have the same problem, whats the solution?
Is it ok if we use this code in part if we are developing our own android apps?
Sure, feel free to use it.
Great tutorial
Do you have any Collision tutorials or a good reference I could look at or read.
I currently don’t have tutorials on this subject, but there are quite a few good ones out there.
You have to pick the right one for your needs.
A good compilation of them can be found here: http://www.gamespp.com/algorithms/collisiondetection/
I was wondering if I could combine this with the onTouch method to where ex.: ObjectA is at PointA and where ever I, touch it moves ObjectA to that point. But I love your tutorials they’re easy to follow and understand compared to most of the tutorials I am reading or looking at.
Sure you can.
You need to add a member to the droid, like destination, which is a vector (has x and y coordinates).
In the update method you work out the direction and the speed for both axis. On the onTouch method, you set the destination’s coordinates to the actual event coordinates and let the update method adjust the speeds so that the speed vector points to the destination.
You also need to check whether the droid reached the destination.
Hint, check out steering behaviours, especially the arrival one:
Steering behaviours
Arrival
Thanks a lot for the help.
Hi, thank you for your great tutorial, I am new to android and currently doing a project and find your site very useful.
I followed your tutorial to achieve moving object on the screen, however, my project requires moving a object on top of another SurfaceView. So I have to make the top object Transparent. If I do that to your code, it looks like every frame the program update the position of the object from the very beginning instead of staying at its current position. This might sound confusing but if you remove canvas.drawColor(Color.Black), you will know what I am talking about. So how do you simply achieve drawing a object on top of another SurfaceView and move this object around on the screen. Thank you very much.
My project is something like open the preview of the camera and draw a moving object on top of the preview.
Hi, thank you for your great tutorial, I am new to android and currently doing a project and find your site very useful.
I followed your tutorial to achieve moving object on the screen, however, my project requires moving a object on top of another SurfaceView. So I have to make the top object Transparent. If I do that to your code, it looks like every frame the program update the position of the object from the very beginning instead of staying at its current position. This might sound confusing but if you remove canvas.drawColor(Color.Black), you will know what I am talking about. So how do you simply achieve drawing a object on top of another SurfaceView and move this object around on the screen. Thank you very much.
Hi impaler
Thank you for code and guide line. But i have some question related to project.
1.In your given project code i can not find any animation method of image. so my question is that how could u able to move the image?
2.Could please explain the logic of collision in this project.
3.if i want to take two image out of that one is animated and other is static, how can i get the collision of that images.
thank you.
Thank you SO MUCH! I was look for speed calculation for months!
x += 1 * 1;
y += 1 * 1;
That is as simple as pie! (after you told me
Thanks!
@impaler
i wanna keep a background image instead of just a black screen….
how do implement this? ur help is much appreciated
\m/
In the main panel’s onDraw() method when you clear the screen with a colour, just display an image. Grab a big enough image from the resources at startup, and use it as your background.
It should be a member attribute of the main panel.
Hope it helps.
I am not understanding that you say. Because I bad english
please, explain with code example.
Thank you
@impaler
hey…thanx…
now i’m trying to make the background image scrollable….i’m thinking Parallax scrolling….
any ideas??
\m/
Hello,
Thanks for wonderful tutorial. I have a situation can you please give me an idea. I want to create a moving image every onTouchEvent. Can you please help me out.
Thanks.
Sintu
dude….put this line inside your onTouchEvent(MotionEvent e) method.
droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 50, 50);
I’ll try you suggest but it Force close .
The tutorial was very helpful.
Suppose the droid is moving in x-axis +ve direction and i want it to move in -ve direction of the same axis when i touch it. How do i implement that?
The comments on this part of the tutorial is very relavant for how far I’ve progressed in the lessons.
Pertinent questions are being asked and answered, such as:
(1) How do you create multiple droids?
and
(2) If you have many droids, how to you keep track of them?
and
(3) How do you control dragging?
Thank you very much.
I’ll try to answer briefly: for example in the gamePanel. Yo decide when to create new droids. For example every 10 seconds you add a new one to the list. The update method will iterate through the list’s objects and call update() on them.
1. To have multiple droids I use a container such as an array of droids or lists. The game engine (which currently is the update and render) has to have access to this list.
The simples way is to create an ArrayList
2. The above partially replied to it but to make a better design, you could create some sort of containers for your objects. Containers or layers that are basically lists containing instances of different types of objects (like droids). The game engine (the main update method is one of them) will iterate through them and will work out for each object (the current droid) how to interact with the others. In collision detection for example for each droid you will have to check its position against every other droid in the list and decide if they collided and take action. This to be done in an optimal way is a big challenge as you have limited processing power and very little time.
3. To control dragging of a droid
You could define a state for a droid:
boolean isDragged = falseWhen you touched the droid on a touch event (MotionEvent.ACTION_DOWN) you set the droid’s drag state to
true.On moving the pointer on the screen (MotionEvent.ACTION_MOVE) you update the droid’s position according to the event position. You simply check if the droid is picked up
if (droid.isDragged())and you know it needs its position updated.To release the droid you simply set the dragged state to
falseon theMotionEvent.ACTION_UPevent.Hope this helps.
Can you give a small hint with code to implement the multiple droid.
Hello,
I’m having a problem with screen orientation.
I made a similar program that lets you drag around an image. I installed it on my Galaxy Spica (running 1.5)
The app stops responding after I change orientation, so I force it run on landscape by adding this in onCreate in my Activity.
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
It works, but is it possible for my app to be flexible, to run on landscape and portrait? Could you show me how to properly do it? I read something about resizing…
Thanks for the reply. I had already looked at that article, I have also read this one which provides the source code for a simple multitouch test app http://www.rbgrn.net/content/367-source-code-to-multitouch-visible-test. I have tried creating my own implementation of it within the MainGamePanel. It seems to work when I process the event disregarding the type (MOVE_DOWN or ACTION_POINTER_DOWN). However when I set the condition that an event must be of action type ACTION_POINTER_DOWN for a circle to be drawn, a circle is not drawn when i set my second finger down. My understanding is that Action pointer down happens when a finger touches the screen after a previous has already done so and has not been lifted. And yes, I am testing and coding this for android 2.1-update1. I just want to know if its really possible to implement. This my code for the onTouchEvent:
if (event.getAction() == MotionEvent.ACTION_UP){
for (int i = 0; i < 6; i++) {
pointerData[i]=7;
}
}
else if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
int pointerCount = event.getPointerCount();
for (int i = 0; i < pointerCount; i++) {
pointerData[3*i] = event.getPointerId(i);
pointerData[3*i+1] = (int) event.getX(pointerData[3*i]);
pointerData[3*i+2] = (int) event.getY(pointerData[3*i]);
}
}
return true;
Then i just use canvas.drawCircle in my render method.
canvas.drawCircle(pointerData[1], pointerData[2], 30, paint);
canvas.drawCircle(pointerData[4], pointerData[5], 30, paint);
Hey, I found out that I have to use the switch statement instead of if and else when checking for an event’s action type. I did this and now my controls work.
Hello, I found your tutorial very helpful and have no managed to create a simple game engine with a controllable character and moving enemies that chase you around the screen. I am currently trying to implement multi-touch but my onTouchEvent method in the MainGamePanel doesn’t seem to respond to pointer up/down actions. Am I having difficulties achieving this because I followed your tutorial and your engine does not support handling pointers?
Hi,
There is a good explanation on how to use multi-touch here:
http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-3-understanding-touch-events/1775
Just bear in mind that it is an Android 2.x feature. If you’re using a lower version it won’t work.
To Andranik; you can just simply add a new object and then initialise and draw down the bottom.
ie:
private Object droid;
private Object droid1;
droid = new Object(BitmapFactory.decodeResource(getResources(), R.drawable.circle), 50, 50);
droid1 = new Object(BitmapFactory.decodeResource(getResources(), R.drawable.circle), 150, 150);
circle.draw(canvas);
circle1.draw(canvas);
simple
——————
one thing I would like to ask, anyone. Is I’m trying to draw multiple of the same image (the droid about ten times, random locations) by using a list or an array, but am having absolutely no luck.
I’m an experienced C/C++ programmer new to Java and I’m just going round in circles and Java has been no help.
So any help is appreciated.
Oh and a additionally. Does anyone know how to delete or un render a bitmap. I’ve found things like clear transparency but that doesn’t seem to work. and i don’t want to clear the entire canvas, just one bitmap object.
Thanks.
Have you tried initialising an ArrayList of droids for example and render all the objects from within that list?
You might want to use a synchronised block too as the lists are not thread safe.
This should work on arrays too.
An other alternative would be to declare the list as a volatile variable, that means it is shared among the threads.
sir , how to develop application,when we leave the dragging object it comes down automatically,as gravity ……
You will have to add a drag (a second vector that points downwards) and in the update you will need to add up the speed vectors. Be aware of terminal velocity as for every drag there is also a resistance.
Will cover physics later on a bit.
how to i can add second droid ???
if i want to set any background image instead of
canvas.drawColor(Color.BLACK);
How do i set this ?
wrong previus post is displayed. The good code:
import android.graphics.Bitmap;
import android.graphics.Canvas;
public class Droid {
private Bitmap bitmap;
private int x;
private int y;
private boolean touched;
/*Add by me*/
private Speed speed;
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
/*Add by me*/
speed = new Speed();
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public boolean isTouched() {
return touched;
}
public void setTouched(boolean touched) {
this.touched = touched;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x – (bitmap.getWidth() / 2), y – (bitmap.getHeight() / 2), null);
}
public void handleActionDown(int eventX, int eventY) {
if (eventX >= (x – bitmap.getWidth() / 2) && (eventX = (y – bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {
//Robot tocado
setTouched(true);
} else {
setTouched(false);
}
} else {
setTouched(false);
}
}
public void update() {
if (!touched) {
x += (speed.getXv() * speed.getxDirection());
y += (speed.getYv() * speed.getyDirection());
}
}
/*Add by me*/
public Speed getSpeed() {
return speed;
}
}
A question and a correction:
I try rename onDraw by render in run() method, but this don’t work. How do you operate?
this.gamePanel.onDraw(canvas); <– Work
this.gamePanel.render(canvas); = (x – bitmap.getWidth() / 2) && (eventX = (y – bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {
//Robot tocado
setTouched(true);
} else {
setTouched(false);
}
} else {
setTouched(false);
}
}
public void update() {
if (!touched) {
x += (speed.getXv() * speed.getxDirection());
y += (speed.getYv() * speed.getyDirection());
}
}
/*Add by me*/
public Speed getSpeed() {
return speed;
}
}
Thanks.
You have to have a render method in your gamePanel too.
It is just renaming the onDraw method.
Make sure you delete the @Override annotation as it is a new method not an overriden one.
public void render(Canvas canvas) { canvas.drawColor(Color.BLACK); droid.draw(canvas); }Yes, I forget renaming onDraw in my gamePanel. As you say, I needed to delete the @Override.
All right, thanks. Now the next step.