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.

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:

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.

Moving Droid

Download the full source code and eclipse project here.
LinkedInRedditTumblrDiggTechnorati FavoritesShare

57 Responses - Add Yours+

  1. Angel says:

    First of all thanks..
    I want to move 4 images on the screen with background set..
    And I want that when i touch any image it should stop moving randomly and move when i want with touch listener…

    Moreover, I want to handle click of those imageviews..
    please help me out to modify your code to meet my requirement

  2. fahim says:

    thanks to all

  3. Nonceba says:

    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.

  4. Kees Koenen says:

    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.

  5. andgregor says:

    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..

  6. adrian says:

    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);

  7. 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() );

    }

    }

    /////////////////////////////////////////

  8. JavaGuy says:

    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() );

    }

    }
    ///////////////////////////////////////////

  9. Mooonbuggy says:

    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!

  10. Francisco says:

    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

  11. dee says:

    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))) {

    • dee says:

      Cut my comment off

      to

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

  12. dee says:

    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?

    • Impaler says:

      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.

      • dee says:

        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();

        }

  13. Ali says:

    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…

  14. Matt says:

    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

  15. mooper says:

    Is it ok if we use this code in part if we are developing our own android apps?

  16. manuel says:

    Great tutorial

  17. Mark says:

    Do you have any Collision tutorials or a good reference I could look at or read.

  18. Ed says:

    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.

    • Impaler says:

      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

  19. Nan says:

    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.

  20. Nan says:

    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.

  21. allen says:

    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.

  22. Mr. E says:

    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!

  23. Anirudh says:

    @impaler

    i wanna keep a background image instead of just a black screen….
    how do implement this? ur help is much appreciated

    \m/

    • Impaler says:

      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.

      • natthawoot says:

        I am not understanding that you say. Because I bad english

        please, explain with code example.

        Thank you

      • Anirudh says:

        @impaler

        hey…thanx…
        now i’m trying to make the background image scrollable….i’m thinking Parallax scrolling….
        any ideas??

        \m/

  24. Sintu says:

    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

  25. Suhas says:

    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?

  26. 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.

    • Impaler says:

      I’ll try to answer briefly:
      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 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.
      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 = false
      When 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 false on the MotionEvent.ACTION_UP event.

      Hope this helps.

  27. Kratos says:

    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…

  28. rock84 says:

    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);

    • rock84 says:

      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.

  29. rock84 says:

    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?

  30. Kyle Hatch says:

    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.

    • Kyle Hatch says:

      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.

    • Impaler says:

      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.

  31. saurabh TRIVEDI says:

    sir , how to develop application,when we leave the dragging object it comes down automatically,as gravity ……

    • Impaler says:

      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.

  32. Andranik says:

    how to i can add second droid ???

  33. Subhajit says:

    if i want to set any background image instead of

    canvas.drawColor(Color.BLACK);

    How do i set this ?

  34. Ramon says:

    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;
    }

    }

  35. Ramon says:

    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.

    • Impaler says:

      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);
      	}
      
      • Ramon says:

        Yes, I forget renaming onDraw in my gamePanel. As you say, I needed to delete the @Override.

        All right, thanks. Now the next step.