Android游戏开发–使用Android显示图像

在进入实际游戏循环之前,让我们显示一些图形,以便完成一些测量。 如果您尚未签出,请执行此操作,因为您必须了解线程如何更新屏幕。 您可以在这里查看

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

这是具有一些属性和构造函数的普通类。
xy是机器人的坐标。 位图保存将显示为机器人的图像。 它是它的图形表示。

到目前为止,没有什么特别的。 但是要使用它,我们需要添加一些状态。 为了简单起见,机器人只有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时,将执行一个代码块(第8186行 )。 当我们的手指开始在屏幕上移动时,就会发生此事件。 很简单。 我们检查机器人是否被触摸 ,如果是,我们将相应地更新其坐标。
这就对了。 这是更新游戏的状态。 我们已经更新了游戏中唯一对象的状态。 触摸状态和坐标。 现在是时候显示它了。

检查onDraw方法。 这是在线程内部每次执行主循环时触发的,还记得吗?
它包含2行。 第99行只是用黑色填充画布,而第100行则告诉机器人在提供的画布上绘制自己。 这样做就像我给你一张纸来画自己的纸,然后把纸还给我,这样我就可以继续我的画了。

检查Droid.java的绘图实现。 这很简单。 它获取实例化的位图,然后将其绘制到当时机器人所在坐标处的画布上。 请注意,机器人的坐标恰好在位图的中心,因此我们需要将指针移至图像的左上角并在此处绘制。 我相信您不会觉得很难理解。

而已。 运行它并玩一下。

此处下载该项目的代码(droidz.android.02.3-graphics.tar.gz)

参考:来自我们的JCG合作伙伴Tamas Jano的Android中的图像显示,来自“ Against The Grain ”博客。

不要忘记查看我们的新Android游戏 ArkDroid (以下屏幕截图) 。 您的反馈将大有帮助!
相关文章:

翻译自: https://www.javacodegeeks.com/2011/07/android-game-development-displaying.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值