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

    本文地址:http://www.cnblogs.com/yc-755909659/p/4179436.html

    PS:本文由Y灬叶小超原创,如有转载请注明出处,谢谢!

  • 相关阅读:
    Unix&Linux下常见的性能分析工具介绍
    理解Load Average做好压力测试
    cron 的配置和说明
    原生js模仿下拉刷新功能
    webpack初步了解
    数组的迭代方法
    webpack4
    反思面向对象
    C和lua的互相调用
    对Zookeeper的一些分析
  • 原文地址:https://www.cnblogs.com/yc-755909659/p/4179436.html
Copyright © 2020-2023  润新知