【读书笔记《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);
    }

}
时间: 2024-11-10 01:18:21

【读书笔记《Android游戏编程之从零开始》】17.游戏开发基础(游戏适屏的简述和作用、让游戏主角动起来)的相关文章

【读书笔记-《Android游戏编程之从零开始》】3.Android 游戏开发常用的系统控件(Button、Layout、ImageButton)

3.1 Button Button这控件不用多说,就是一个按钮,主要是点击后进行相应事件的响应. 给组件添加ID属性:定义格式为 android:id="@+id/name",这里的name是自定义的,不是索引变量."@+"表示新声明,"@"表示引用,例如:"@+id/tv" 表示新声明一个id,是id名为tv的组件:"@id/tv" 表示引用id名为tv的组件. 给按钮添加点击事件响应  想知道按钮是否被

【读书笔记-《Android游戏编程之从零开始》】1.Android 平台简介与环境搭建

简单的记录下笔记,具体可百度! Android SDK (Software Development Kit)- Android 软件开发工具包,用于辅助Android 操作系统软件开发,是开发Android 软件.文档.范例.工具的一个集合.Android NDK (Native Development Kit) - 类似 Android SDK,可用C/C++语言编写Android程序. developer.android.com - 可查阅到 Android SDK. 开发指南.API说明等

【读书笔记-《Android游戏编程之从零开始》】8.Android 游戏开发常用的系统控件(系统控件常见问题)

Android 中常用的计量单位Android有时候需要一些计量单位,比如在布局Layout文件中可能需要指定具体单位等.常用的计量单位有:px.dip(dp).sp,以及一些不常用的pt.in.mm.下面详细介绍下这些计量单位之间的区别和联系.in:英寸(长度单位):mm:毫米(长度单位):pt:磅/点,1/72英寸(一个标准的长度单位):sp:全名 scaled pixels-best for text size,放大像素,与刻度无关,可以根据用户的字体大小就行缩放,主要用来处理字体的大小:

【读书笔记-《Android游戏编程之从零开始》】5.Android 游戏开发常用的系统控件(ProgressBar、Seekbar)

3.7 ProgressBar ProgressBar类官方文档地址:http://developer.android.com/reference/android/widget/ProgressBar.html 在Android应用开发中,ProgressBar(运行进度条)是比较常用到的组件,例如下载进度.安装程序进度.加载资源进度显示等.在Android中提供了两种样式来分别表示在不同状态下显示的进度条,下面来实现这两种样式.默认进度条是圆形,通过style属性来指定系统进度条的大小:sty

【读书笔记-《Android游戏编程之从零开始》】4.Android 游戏开发常用的系统控件(EditText、CheckBox、Radiobutton)

3.4 EditText EditText类官方文档地址:http://developer.android.com/reference/android/widget/EditText.html EditText继承TextView,所以EditText具有TextView的属性特点,下面主要介绍一些EditText的特有的输入法的属性特点android:layout_gravity="center_vertical":设置控件显示的位置:默认top,这里居中显示,还有bottomand

【读书笔记-《Android游戏编程之从零开始》】6.Android 游戏开发常用的系统控件(TabHost、ListView)

3.9 TabSpec与TabHost TabHost类官方文档地址:http://developer.android.com/reference/android/widget/TabHost.html Android 实现tab视图有2种方法,一种是在布局页面中定义<tabhost>标签,另一种就是继承tabactivity.但是我比较喜欢第二种方式,应为如果页面比较复杂的话你的XML文件会写得比较庞大,用第二种方式XML页面相对要简洁得多. <?xml version="1

Android游戏编程之从零开始pdf

下载地址:网盘下载 <Android游戏编程之从零开始>主要系统地讲解了Android游戏开发,从最基础部分开始,让零基础的Android初学者也能快速学习和掌握Android游戏开发.<Android游戏编程之从零开始>一共8章,内容包括Android平台介绍与环境搭建.Hello,Android!项目剖析.游戏开发中常用的系统组件.游戏开发基础.游戏开发实战.游戏开发提高篇.Box2d物理引擎.物理游戏实战.随书光盘包括全书65个项目源代码.<Android游戏编程之从零

Windows游戏编程之从零开始d

I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来浅墨的博客逛一下看有没有更新,"每天都来就像看女神那般不依不舍",弄得我再不更新都不好意思了,哈哈~怎么说呢,前段时间忙毕设,回国,暑假,间隔年旅行休整,然后是适应新的生活,各种事情,也真正没有心境来更新博客了,最近正好心境安定下来,就继续开始写博.额,关于思想汇报改天我专门写一篇文章和大家交流交流,现在先打住说正事吧~ 首

读书笔记-----Java并发编程实战(一)线程安全性

线程安全类:在线程安全类中封装了必要的同步机制,客户端无须进一步采取同步措施 示例:一个无状态的Servlet 1 @ThreadSafe 2 public class StatelessFactorizer implements Servlet{ 3 public void service(ServletRequest req,ServletResponse resp){ 4 BigInteger i = extractFromRequest(req); 5 BigInteger[] fact