使用Android显示图像非常简单。
为了缩小问题的规模,我们将只在左上角显示图像。 我们需要显示图像。 我更喜欢.png格式,并且我刚刚创建了一个名为droid_1.png的格式。 图像尺寸为20×20像素。 您可以使用任何喜欢的工具。 我使用Gimp或Photoshop。
要使其可用于您的应用程序,只需将图像复制到/ res / drawable-mdpi目录中(最简单的方法是将其拖放到该目录中)。
我选择了mdpi,它代表正常的屏幕中等密度。 要阅读屏幕类型,请查看android文档 。
修改MainGamePanel.java类并更改onDraw(Canvas canvas)方法,如下所示:
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 10, 10, null);
}
drawBitmap方法将droid_1图像绘制到坐标10,10。
我们通过传递图像(资源)的ID(在本例中为droid_1 )从应用程序资源中获取位图。 当我们将droid_1.png复制到资源目录时,eclipse检测到了它,并且插件在后台执行了必要的脚本,因此我们在R.java文件中有了droid_1标识符。 R.java保存资源标识符。
该线程也发生了一些变化。 检查新的run()方法。
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing on the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// update game state
// draws the canvas on the panel
this.gamePanel.onDraw(canvas);
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
在第02行中,我们声明将在其上绘制图像的画布。 画布是我们可以在其上绘制并可以编辑其像素的表面位图。 在第08行中,我们尝试获取它;在第12行中,我们触发面板的onDraw事件,将获得的画布传递给该事件。 请注意,这是一个同步块,这意味着我们对此具有独占性,并且在使用它时没有任何东西可以对其进行修改。
该功能非常简单和基本。 在游戏循环的每次执行中,我们都拥有画布,并将其传递给游戏面板以在其上进行绘制。 游戏面板仅在坐标10,10处显示图像。 现在回到FPS。 如果每秒显示图像的次数降到20以下,我们的人类就会开始注意到它。 面临的挑战是将这一比率保持在设定水平之上,我们很快就会看到。
尝试运行代码,您应该看到我们的机器人显示在左上角附近。
机器人在左上角 |
移动影像
现在我们已经显示了它,让我们尝试移动它。 怎么样? 我们将用手指。 我们将实现一个简单的拖放功能。 要拾取图像,我们只需触摸它,而当手指在屏幕上时,我们将相应地更新图像的坐标。 触摸完成后,我们将图像保留在最后一次记录的位置。
我们需要创建一个对象,以保存图像和坐标。
我为此创建了Droid.java 。 请注意,我已经将该类放入net.obviam.droidz.model包中。
package net.obviam.droidz.model;
import android.graphics.Bitmap;
public class Droid {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
}
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;
}
}
这是具有一些属性和构造函数的普通类。
x和y是机器人的坐标。 位图保存将显示为机器人的图像。 它是它的图形表示。
到目前为止,没有什么特别的。 但是要使用它,我们需要添加一些状态。 为了简单起见,机器人只有2个状态。 感动和未 感动 。 触摸是指手指触摸屏幕上的机器人。 我们将手指保持在屏幕上机器人位置的同时保持触摸状态为真 。 否则,机器人将保持不变(状态设置为false )。
签出新的droid类。
package net.obviam.droidz.model;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.MotionEvent;
public class Droid {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
private boolean touched; // if droid is touched/picked up
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
}
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 <= (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);
}
}
}
我们添加了touched字段来跟踪机器人的状态。 您将注意到另外两个方法: public void draw(Canvas canvas)和public void handleActionDown(int eventX,int eventY) 。
这些方法将在后面讨论。
现在让我们看看MainGamePanel.java 。 它改变了很多。
package net.obviam.droidz;
import net.obviam.droidz.model.Droid;
import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainGamePanel extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = MainGamePanel.class.getSimpleName();
private MainThread thread;
private Droid droid;
public MainGamePanel(Context context) {
super(context);
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
// create droid and load bitmap
droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.droid_1), 50, 50);
// create the game loop thread
thread = new MainThread(getHolder(), this);
// make the GamePanel focusable so it can handle events
setFocusable(true);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// at this point the surface is created and
// we can safely start the game loop
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface is being destroyed");
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// delegating event handling to the droid
droid.handleActionDown((int)event.getX(), (int)event.getY());
// check if in the lower part of the screen we exit
if (event.getY() > getHeight() - 50) {
thread.setRunning(false);
((Activity)getContext()).finish();
} else {
Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
}
} if (event.getAction() == MotionEvent.ACTION_MOVE) {
// the gestures
if (droid.isTouched()) {
// the droid was picked up and is being dragged
droid.setX((int)event.getX());
droid.setY((int)event.getY());
}
} if (event.getAction() == MotionEvent.ACTION_UP) {
// touch was released
if (droid.isTouched()) {
droid.setTouched(false);
}
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
// fills the canvas with black
canvas.drawColor(Color.BLACK);
droid.draw(canvas);
}
}
第28 行在坐标50,50处创建机器人对象。
在第20行中将其声明为属性。
在onTouchEvent (方法行71 )中,如果动作是屏幕触摸( MotionEvent.ACTION_DOWN ),我们想知道我们的手指是否落在机器人上。 要做到这一点很容易。 我们需要检查事件的坐标是否在机器人的位图中。 为了不使onTouch事件混乱,我们只是将其委托给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位图区域内,则将其触摸状态设置为true
回到onTouched方法,请注意,当事件类型为MotionEvent.ACTION_MOVE时,将执行一个代码块(第81 – 86行 )。 当我们的手指开始在屏幕上移动时,就会发生此事件。 很简单。 我们检查机器人是否被触摸 ,如果是,我们将相应地更新其坐标。
这就对了。 这是更新游戏的状态。 我们已经更新了游戏中唯一对象的状态。 触摸状态和坐标。 现在是时候显示它了。
检查onDraw方法。 这是在线程内部每次执行主循环时触发的,还记得吗?
它包含2行。 第99行只是用黑色填充画布,而第100行则告诉机器人在提供的画布上绘制自己。 这样做就像我给你一张纸来画自己的纸,然后把纸还给我,这样我就可以继续我的画了。
检查Droid.java的绘图实现。 这很简单。 它获取实例化的位图,然后将其绘制到当时机器人所在坐标处的画布上。 请注意,机器人的坐标恰好在位图的中心,因此我们需要将指针移至图像的左上角并在此处绘制。 我相信您不会觉得很难理解。
而已。 运行它并玩一下。
在此处下载该项目的代码(droidz.android.02.3-graphics.tar.gz)
参考:来自我们的JCG合作伙伴Tamas Jano的Android中的图像显示,来自“ Against The Grain ”博客。
- Android游戏开发教程简介
- Android游戏开发–游戏创意
- Android游戏开发–创建项目
- Android游戏开发–基本游戏架构
- Android游戏开发–基本游戏循环
- Android游戏开发–在屏幕上移动图像
- Android游戏开发–游戏循环
- Android游戏开发–测量FPS
- Android游戏开发–雪碧动画
- Android游戏开发–粒子爆炸
- Android游戏开发–设计游戏实体–策略模式
- Android游戏开发–使用位图字体
- Android游戏开发–从Canvas切换到OpenGL ES
- Android游戏开发–使用OpenGL ES显示图形元素(原语)
- Android游戏开发– OpenGL纹理映射
- Android游戏开发–设计游戏实体–状态模式
- Android游戏文章系列
翻译自: https://www.javacodegeeks.com/2011/07/android-game-development-displaying.html