4-Displaying Images with Android

在开始实际的游戏循环之前,让我们先显示一些图片,使得我们能够得到一些尺寸的概念(不太清楚这句什么意思)。如果还没有看到线程更新屏幕的内容,强烈推荐先看一下(上篇博客)

在android上面显示图片非常的简单

为了让问题简单,我们在左上角显示图形,我们需要 一个图片,我更喜欢png,我创建了一个名为droid_1.png的文件,大小是20*20 像素,你可以选择自己喜欢的工具,我用gimp或者ps

为了让程序可以使用,把图片拷贝到/res/drawable-mdpi目录下,我选择mdpi,它的意思是平常屏幕 中等密度,关于屏幕类型,可以求助 android文档

修改MainGamePanel文件,修改onDraw函数

1 protected void onDraw(Canvas canvas) {  

2     canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);  

3 } 

drawbitmap把droid_1画到了坐标10,10位置上

我们传递图片id给程序的资源管理部分以获得bitmap,当我们拷贝png到资源目录时候,插件会自动在R.java里面生成标识

也影响了线程的一部分code,检查下面的run函数

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 on the surface  

07             try {  

08                 canvas = this.surfaceHolder.lockCanvas();  

09                 synchronized (surfaceHolder) {  

10                     // update game state  

11                     // draws the canvas on the panel  

12                     this.gamePanel.onDraw(canvas);  

13                 }  

14             } finally {  

15                 // in case of an exception the surface is not left in  

16                 // an inconsistent state  

17                 if (canvas != null) {  

18                     surfaceHolder.unlockCanvasAndPost(canvas);  

19                 }  

20             }   // end finally  

21         }  

22     } 


第二行 我们声明了我们要画图形的画布,画布是surface的图形要画的地方,也是我们编辑像素的地方,8行我们得到了画布,12行我们触发了onDraw函数,并把画布传递过去,注意这是同步块,别人是无法使用的。

这个函数很简单和基础,每次执行的时候,游戏循环得到画布,传递给game panel去画东西,game panel把图片画到坐标10,10处。回到FPS,如果每秒图片显示的次数低于20,就会被人注意到,我们的挑战就是保持到一定的水平以上,很快我们就会看到

运行一下代码,我们看到droid在左上角显示了

Droid in top left corner

移动图形

我们已经显示图形了,让我们移动它,怎么移动呢?用我们的手指。 我们会实现一个拖放的操作。为了选择一个图片,我们只是触摸它,当我们的手指还在屏幕的时候,我们的也会更新图片的坐标,当触摸接触,图片会放到最后触摸的位置

我们需要创建一个对象来保存图片和坐标

我创建了Droid.java,放到了net.obviam.droidz.model包下

01 package net.obviam.droidz.model;  

02    

03 import android.graphics.Bitmap;  

04    

05 public class Droid {  

06    

07     private Bitmap bitmap;  // the actual bitmap  

08     private int x;          // the X coordinate  

09     private int y;          // the Y coordinate  

10    

11     public Droid(Bitmap bitmap, int x, int y) {  

12         this.bitmap = bitmap;  

13         this.x = x;  

14         this.y = y;  

15     }  

16    

17     public Bitmap getBitmap() {  

18         return bitmap;  

19     }  

20     public void setBitmap(Bitmap bitmap) {  

21         this.bitmap = bitmap;  

22     }  

23     public int getX() {  

24         return x;  

25     }  

26     public void setX(int x) {  

27         this.x = x;  

28     }  

29     public int getY() {  

30         return y;  

31     }  

32     public void setY(int y) {  

33         this.y = y;  

34     }  

35 } 

 

这是个只有几个属性和一个构造函数的简单类

droid的x和y坐标,还有要显示的bitmap

还没有什么特殊的,但是为了要运行起来,我们需要增加一些状态,为了保持简单,droid就有俩状态,被触摸和么有被触摸,触摸 就是说手指在屏幕上按着droid,按到droid的时候我们就保持触摸状态为真,否则就是假了

看一下新的droid的类

1 package net.obviam.droidz.model;  

02    

03 import android.graphics.Bitmap;  

04 import android.graphics.Canvas;  

05 import android.view.MotionEvent;  

06    

07 public class Droid {  

08    

09     private Bitmap bitmap;  // the actual bitmap  

10     private int x;          // the X coordinate  

11     private int y;          // the Y coordinate  

12     private boolean touched;    // if droid is touched/picked up  

13    

14     public Droid(Bitmap bitmap, int x, int y) {  

15         this.bitmap = bitmap;  

16         this.x = x;  

17         this.y = y;  

18     }  

19    

20     public Bitmap getBitmap() {  

21         return bitmap;  

22     }  

23     public void setBitmap(Bitmap bitmap) {  

24         this.bitmap = bitmap;  

25     }  

26     public int getX() {  

27         return x;  

28     }  

29     public void setX(int x) {  

30         this.x = x;  

31     }  

32     public int getY() {  

33         return y;  

34     }  

35     public void setY(int y) {  

36         this.y = y;  

37     }  

38    

39     public boolean isTouched() {  

40         return touched;  

41     }  

42    

43     public void setTouched(boolean touched) {  

44         this.touched = touched;  

45     }  

46    

47     public void draw(Canvas canvas) {  

48         canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y - (bitmap.getHeight() / 2), null);  

49     }  

50    

51     public void handleActionDown(int eventX, int eventY) {  

52         if (eventX >= (x - bitmap.getWidth() / 2) && (eventX <= (x + bitmap.getWidth()/2))) {  

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

54                 // droid touched  

55                 setTouched(true);  

56             } else {  

57                 setTouched(false);  

58             }  

59         } else {  

60             setTouched(false);  

61         }  

62    

63     }  

64 } 


我们加入了touched来记录droid的状态

看一下MainGamePanel,变了可不少呢。

001 package net.obviam.droidz;  

002    

003 import net.obviam.droidz.model.Droid;  

004 import android.app.Activity;  

005 import android.content.Context;  

006 import android.graphics.BitmapFactory;  

007 import android.graphics.Canvas;  

008 import android.graphics.Color;  

009 import android.util.Log;  

010 import android.view.MotionEvent;  

011 import android.view.SurfaceHolder;  

012 import android.view.SurfaceView;  

013    

014 public class MainGamePanel extends SurfaceView implements 

015         SurfaceHolder.Callback {  

016    

017     private static final String TAG = MainGamePanel.class.getSimpleName();  

018    

019     private MainThread thread;  

020     private Droid droid;  

021    

022     public MainGamePanel(Context context) {  

023         super(context);  

024         // adding the callback (this) to the surface holder to intercept events  

025         getHolder().addCallback(this);  

026    

027         // create droid and load bitmap  

028         droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 50, 50);  

029    

030         // create the game loop thread  

031         thread = new MainThread(getHolder(), this);  

032    

033         // make the GamePanel focusable so it can handle events  

034         setFocusable(true);  

035     }  

036    

037     @Override 

038     public void surfaceChanged(SurfaceHolder holder, int format, int width,  

039             int height) {  

040     }  

041    

042     @Override 

043     public void surfaceCreated(SurfaceHolder holder) {  

044         // at this point the surface is created and  

045         // we can safely start the game loop  

046         thread.setRunning(true);  

047         thread.start();  

048     }  

049    

050     @Override 

051     public void surfaceDestroyed(SurfaceHolder holder) {  

052         Log.d(TAG, "Surface is being destroyed");  

053         // tell the thread to shut down and wait for it to finish  

054         // this is a clean shutdown  

055         boolean retry = true;  

056         while (retry) {  

057             try {  

058                 thread.join();  

059                 retry = false;  

060             } catch (InterruptedException e) {  

061                 // try again shutting down the thread  

062             }  

063         }  

064         Log.d(TAG, "Thread was shut down cleanly");  

065     }  

066    

067     @Override 

068     public boolean onTouchEvent(MotionEvent event) {  

069         if (event.getAction() == MotionEvent.ACTION_DOWN) {  

070             // delegating event handling to the droid  

071             droid.handleActionDown((int)event.getX(), (int)event.getY());  

072    

073             // check if in the lower part of the screen we exit  

074             if (event.getY() > getHeight() - 50) {  

075                 thread.setRunning(false);  

076                 ((Activity)getContext()).finish();  

077             } else {  

078                 Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());  

079             }  

080         } if (event.getAction() == MotionEvent.ACTION_MOVE) {  

081             // the gestures  

082             if (droid.isTouched()) {  

083                 // the droid was picked up and is being dragged  

084                 droid.setX((int)event.getX());  

085                 droid.setY((int)event.getY());  

086             }  

087         } if (event.getAction() == MotionEvent.ACTION_UP) {  

088             // touch was released  

089             if (droid.isTouched()) {  

090                 droid.setTouched(false);  

091             }  

092         }  

093         return true;  

094     }  

095    

096     @Override 

097     protected void onDraw(Canvas canvas) {  

098         // fills the canvas with black  

099         canvas.drawColor(Color.BLACK);  

100         droid.draw(canvas);  

101     }  

102 } 



 

Line 28 creates the droid object at the the coordinates 50,50.
It is declared as an attribute in line 20.

In the onTouchEvent (method line 71) if the action is the touch of the screen (MotionEvent.ACTION_DOWN) we want to know if our finger landed on the droid. To do this is easy. We need to check if the event’s coordinates are inside the droid’s bitmap. In order not to clutter the onTouch event we just delegate this to the droid object. Now you can go back to the Droid.java class and check the handleActionDown method.

28行 创建了droid对象,在坐标50,50

在onTouchEvent方法中,如果触摸屏幕的动作,我们确认是否在droid上面,就是看看触摸事件的坐标是否在图形的坐标内。为了不让onTouchEvent杂乱,我们把这个放到droid对象中(其实我觉得在droid内部也可以,要是droid类是怎么设计的),现在回到droid.java,看一下handleActionDown方法。

public void handleActionDown(int eventX, int eventY) {
		if (eventX >= (x - bitmap.getWidth() / 2) && (eventX <= (x + bitmap.getWidth()/2))) {
			if (eventY >= (y - bitmap.getHeight() / 2) && (y <= (y + bitmap.getHeight() / 2))) {
				// droid touched
				setTouched(true);
			} else {
				setTouched(false);
			}
		} else {
			setTouched(false);
		}

	}

很简单,如果在droid内部,把touched状态设成true。

回到onTouched方法,看一下MotionEvent.ACTION_MOVE,如果droid是touched,我们更新一下它的坐标。

而ondraw函数 就是把droid画到surface上。

就是这样

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值