【读书笔记《Android游戏编程之从零开始》】17.游戏开发基础(游戏适屏的简述和作用、让游戏主角动起来)
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); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。