【讀書筆記《Android遊戲編程之從零開始》】17.遊戲開發基礎(遊戲適屏的簡述和作用、讓遊戲主角動起來),從零開始學android
1.遊戲適屏的簡述和作用
由於市面上安裝 Android 系統的手機不斷增多,出現了各種解析度、各種螢幕尺寸的Android 系統手機。為了保證一個遊戲或者一個軟體能在所有的 Android 手機上正常顯示,常用的適屏做法有:利用螢幕寬高、位元影像寬高來設定一些遊戲元素的位置;字型的適屏做法最好的使用字型圖,這樣文字不會因為手機解析度不同而不同,畢竟圖片大小是固定不變的。
2.讓遊戲主角動起來
執行個體示範將一張由多行多列的動作幀組成的圖片實現動態效果。
建立項目,遊戲架構為SurfaceView 架構,準備圖片robot.png如下:
修改MySurfaceView 類,代碼如下:
package com.example.ex4_13;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.view.KeyEvent;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;public class MySurfaceView extends SurfaceView implements Callback,Runnable { private SurfaceHolder sfh; private Canvas canvas; private Paint paint; private boolean flag; private Thread th; //機器人位元影像 private Bitmap bmpRobot ; //機器人的方向常量 private final int DIR_LEFT =0; private final int DIR_RIGHT=1; //機器人當前的方向 private int dir = DIR_RIGHT; //動作幀下標 private int currentFrame; //機器人的X,Y位置 private int robot_x,robot_y; //處理按鍵卡現象 private boolean isUp, isDown, isLeft, isRight; public MySurfaceView(Context context) { super(context); sfh = this.getHolder(); sfh.addCallback(this); paint = new Paint(); paint.setColor(Color.WHITE); paint.setAntiAlias(true); setFocusable(true); bmpRobot = BitmapFactory.decodeResource(this.getResources(), R.drawable.robot); } /** * SurfaceView視圖建立,響應此函數 */ @Override public void surfaceCreated(SurfaceHolder holder) { flag = true; //執行個體線程 th = new Thread(this); //啟動線程 th.start(); } /** * SurfaceView檢視狀態發生改變,響應此函數 */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * SurfaceView視圖消亡時,響應此函數 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { flag = false; } /** * 繪製函數 */ private void myDraw() { try { canvas = sfh.lockCanvas(); if(canvas!=null) { canvas.drawColor(Color.BLACK); drawFrame(currentFrame,canvas,paint); } } catch (Exception e) { // TODO: handle exception }finally{ if(canvas!=null) { sfh.unlockCanvasAndPost(canvas); } } } /** * * @param currentFrame 繪製幀 * @param frameW * 每幀的高 * @param frameH * 每幀的高 * @param canvas * 畫布執行個體 * @param paint * 畫筆執行個體 */ private void drawFrame(int currentFrame,Canvas canvas,Paint paint) { //每幀的寬 int frameW = bmpRobot.getWidth() / 6; //每幀的高 int frameH = bmpRobot.getHeight() / 2; //得到位元影像的列數 int col = bmpRobot.getWidth() / frameW; //得到當前幀相對於位元影像的X座標 int x = currentFrame % col * frameW; //得到當前幀相對於位元影像的Y座標 int y = currentFrame / col * frameH; canvas.save(); //設定一個寬高與機器人每幀相同大小的可視地區 canvas.clipRect(robot_x, robot_y, robot_x + bmpRobot.getWidth() / 6, robot_y + bmpRobot.getHeight() / 2); if (dir == DIR_LEFT) {//如果是向左側移動 //鏡像操作 - 反轉 - 改變機器人動畫的朝向 canvas.scale(-1, 1, robot_x - x + bmpRobot.getWidth() / 2, robot_y - y + bmpRobot.getHeight() / 2); } canvas.drawBitmap(bmpRobot, robot_x - x, robot_y - y, paint); canvas.restore(); } /** * 遊戲邏輯 */ private void logic() { //控制機器人位移方向 if (isUp) { robot_y -= 5; } if (isDown) { robot_y += 5; } if (isLeft) { robot_x -= 5; } if (isRight) { robot_x += 5; } //動作幀數的迴圈控制,讓其動作幀不斷重複播放 currentFrame++; if (currentFrame >= 12) { currentFrame = 0; } } @Override public void run() { while (flag) { long start = System.currentTimeMillis(); myDraw(); logic(); long end = System.currentTimeMillis(); try { if (end - start < 50) { Thread.sleep(50 - (end - start)); } } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 按鍵事件監聽 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { isUp = true; } if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { isDown = true; } if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { isLeft = true; dir = DIR_LEFT; } if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { isRight = true; dir = DIR_RIGHT; } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { isUp = false; } if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { isDown = false; } if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { isLeft = false; } if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { isRight = false; } return super.onKeyUp(keyCode, event); } }