首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 平面设计 > 图形图像 >

四-Displaying Images with Android

2013-11-09 
4-Displaying Images with Android在开始实际的游戏循环之前,让我们先显示一些图片,使得我们能够得到一些

4-Displaying Images with Android

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

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

四-Displaying Images with 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在左上角显示了

四-Displaying Images with Android

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 coordinates50,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 theDroid.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 touchedsetTouched(true);} else {setTouched(false);}} else {setTouched(false);}}

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

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

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

就是这样

 

热点排行