Android Game Development - Moving Images on Screen

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.
01 package net.obviam.droidz.model.components;
02  
03 public class Speed {
04  
05     public static final int DIRECTION_RIGHT = 1;
06     public static final int DIRECTION_LEFT  = -1;
07     public static final int DIRECTION_UP    = -1;
08     public static final int DIRECTION_DOWN  = 1;
09  
10     private float xv = 1;   // velocity value on the X axis
11     private float yv = 1;   // velocity value on the Y axis
12  
13     private int xDirection = DIRECTION_RIGHT;
14     private int yDirection = DIRECTION_DOWN;
15  
16     public Speed() {
17         this.xv = 1;
18         this.yv = 1;
19     }
20  
21     public Speed(float xv, float yv) {
22         this.xv = xv;
23         this.yv = yv;
24     }
25  
26     public float getXv() {
27         return xv;
28     }
29     public void setXv(float xv) {
30         this.xv = xv;
31     }
32     public float getYv() {
33         return yv;
34     }
35     public void setYv(float yv) {
36         this.yv = yv;
37     }
38  
39     public int getxDirection() {
40         return xDirection;
41     }
42     public void setxDirection(int xDirection) {
43         this.xDirection = xDirection;
44     }
45     public int getyDirection() {
46         return yDirection;
47     }
48     public void setyDirection(int yDirection) {
49         this.yDirection = yDirection;
50     }
51  
52     // changes the direction on the X axis
53     public void toggleXDirection() {
54         xDirection = xDirection * -1;
55     }
56  
57     // changes the direction on the Y axis
58     public void toggleYDirection() {
59         yDirection = yDirection * -1;
60     }
61 }

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:
1 this.gamePanel.update();

The  run()  method:
01 public void run() {
02     Canvas canvas;
03     Log.d(TAG, "Starting game loop");
04     while (running) {
05         canvas = null;
06         // try locking the canvas for exclusive pixel editing
07         // in the surface
08         try {
09             canvas = this.surfaceHolder.lockCanvas();
10             synchronized (surfaceHolder) {
11                 // update game state
12                 this.gamePanel.update();
13                 // render state to the screen
14                 // draws the canvas on the panel
15                 this.gamePanel.render(canvas);
16             }
17         finally {
18             // in case of an exception the surface is not left in
19             // an inconsistent state
20             if (canvas != null) {
21                 surfaceHolder.unlockCanvasAndPost(canvas);
22             }
23         }   // end finally
24     }
25 }

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
01 public void update() {
02     // check collision with right wall if heading right
03     if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
04             && droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
05         droid.getSpeed().toggleXDirection();
06     }
07     // check collision with left wall if heading left
08     if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
09             && droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
10         droid.getSpeed().toggleXDirection();
11     }
12     // check collision with bottom wall if heading down
13     if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
14             && droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
15         droid.getSpeed().toggleYDirection();
16     }
17     // check collision with top wall if heading up
18     if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
19             && droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
20         droid.getSpeed().toggleYDirection();
21     }
22     // Update the lone droid
23     droid.update();
24 }

getWidth()  and  getHeight()  return the width and height of the view. The panel is a view, remember?

The  Droid.java  file’s  update()  method:
1 public void update() {
2     if (!touched) {
3         x += (speed.getXv() * speed.getxDirection());
4         y += (speed.getYv() * speed.getyDirection());
5     }
6 }

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 .


Reference:   Moving Images on the Screen with Android  from our  JCG  partner Tamas Jano from " Against The Grain " blog.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值