• Android_(游戏)打飞机01:前言


    (游戏)打飞机01:前言  传送门

    (游戏)打飞机02:游戏背景滚动  传送门

    (游戏)打飞机03:控制玩家飞机   传送门 

    (游戏)打飞机04:绘画敌机、添加子弹    传送门

    (游戏)打飞机05:处理子弹,击中敌机,添加计分板   传送门

    (游戏)打飞机06:后续  传送门

       

    程序已放到Github上托管 : 传送门

    打飞机游戏效果

    游戏中的二级缓存

      android之surfaceView学习:传送门

      制作游戏时,为了时刻渲染游戏场景,涉及到一个实时画图的问题了,对于实时更新UI这个问题,android的UI更新都需要在主线程中更新,但是如果将一个实时绘图的操作放在主线程,必定会出现阻塞主线程的问题,即便是不阻塞主线程,也会降低程序运行的速度

      surfaceView提供了UI线程。可以自己更新UI,因此,这样我们在surfaceView中进行实时的绘画,然后通过更改其中的绘画的数据,既可以实现我们想要的实时的更新UI的这个问题了,并且消耗较小的资源

      

      surfaceCreated:创建时需要执行的操作

      surfaceView:大小改变时需要执行的操作

      surfaceDestroyed:销毁时进行的操作

      

        //视图创建时通知
        public void surfaceCreated(SurfaceHolder holder) {
            this.holder = holder;
            runState = true;
            //视图创建时开始线程
            new Thread(this).start();
        }
    
        //界面发生改变的时候通知
        public void surfaceChanged(SurfaceHolder holder, int i, int i1, int i2) {
    
        }
    
        //销毁时通知
        public void surfaceDestroyed(SurfaceHolder holder) {
            runState = false;
        }

      线程中的方法

        public void run() {
            Random ran = new Random();
    
            try{
                while(true) {
                    //获得绘画的画布
                    Canvas canvas =  holder.lockCanvas();
    
                    Paint p = new Paint();
                    p.setColor(Color.rgb(ran.nextInt(255),ran.nextInt(255),ran.nextInt(255)));
    
                    canvas.drawLine(ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),p);
    
                    //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁
                    Thread.sleep(1000);
                }
            }catch (Exception e){
    
            }
        }

      锁住画布时,开始编辑要绘画的内容

                 //锁住画布
                 Canvas canvas =  holder.lockCanvas();            

      

      内容绘画好后,开始解锁

                  //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁

     

       制作游戏时,为了时时渲染游戏画面,线程中常用死循环

      while(true) {
                    //锁住画布
                    Canvas canvas =  holder.lockCanvas();
    
                    Paint p = new Paint();
                    p.setColor(Color.rgb(ran.nextInt(255),ran.nextInt(255),ran.nextInt(255)));
    
                    canvas.drawLine(ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),p);
    
                    //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁
                    Thread.sleep(1000);
                }

    实现效果:

      

    package com.example.administrator.myapplication;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    import java.util.Random;
    
    /**
     * Created by Administrator on 2018/8/9.
     */
    
    public class GameView extends SurfaceView implements Runnable, SurfaceHolder.Callback{
    
        public GameView(Context context) {
            super(context);
    
            getHolder().addCallback(this);  //注册回调方法
        }
    
        private boolean runState = false;
        private SurfaceHolder holder = null;
    
        @Override
        public void run() {
            Random ran = new Random();
    
            try{
                while(true) {
                    //获得绘画的画布
                    Canvas canvas =  holder.lockCanvas();
    
                    Paint p = new Paint();
                    p.setColor(Color.rgb(ran.nextInt(255),ran.nextInt(255),ran.nextInt(255)));
    
                    canvas.drawLine(ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),p);
    
                    //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁
                    Thread.sleep(1000);
                }
            }catch (Exception e){
    
            }
        }
    
        //视图创建时通知
        public void surfaceCreated(SurfaceHolder holder) {
            this.holder = holder;
            runState = true;
            new Thread(this).start();
    
    
        }
    
        //界面发生改变的时候通知
        public void surfaceChanged(SurfaceHolder holder, int i, int i1, int i2) {
    
        }
    
        //销毁时通知
        public void surfaceDestroyed(SurfaceHolder holder) {
            runState = false;
        }
    
    
    }
    GameView.java
    package com.example.administrator.myapplication;
    
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity{
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(new GameView(this));
    
        }
    
    }
    MainActivity.java

      随之而来有一个问题。产生新线条的时候会让原本存在线条也会发生位置、颜色的改变,这样绘制游戏时这样不仅会产生大量的游戏内存,也容易使玩家造成晕眩效果

      制作游戏常用二级缓存来解决这个问题(减少游戏运行时内存开销!!!)

    二级缓存工作机制
        所谓二级缓存实际上并不复杂,当Android端需要获得数据时比如获取网络中的图片,我们首先从内存中查找(按键查找),内存中没有的再从磁盘文件或sqlite中去查找,若磁盘中也没有才通过网络获取;当获得来自网络的数据,就以key-value对的方式先缓存到内存(一级缓存),同时缓存到文件或sqlite中(二级缓存)。注意:内存缓存会造成堆内存泄露,所有一级缓存通常要严格控制缓存的大小,一般控制在系统内存的1/4。
    二级缓存

      

      二级缓存:当游戏需要产生新动画时,不改变原场景游戏画面,只要把新加入的绘画内容先放到二级缓存中,绘画好后从二级缓存取出来绘画到游戏界面上

      运用Bitmap实现二级缓存

            private Bitmap gameBitmap = null;
    
            gameBitmap = Bitmap.createBitmap(500,500, Bitmap.Config.ARGB_8888);

      

    public void run() {
            Random ran = new Random();
    
            try{
                while(true) {
                    //获得绘画的画布
                    Canvas canvas =  holder.lockCanvas();
                    Paint p = new Paint();
                    Canvas c = new Canvas(gameBitmap);
    
                    //  p.setColor(Color.WHITE);
                    // c.drawRect(new Rect(0,0,500,500),p);    //白色背景
    
    
                    p.setColor(Color.rgb(ran.nextInt(255),ran.nextInt(255),ran.nextInt(255)));
    
                    c.drawLine(ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),p);
    
                    canvas.drawBitmap(gameBitmap,0,0,new Paint());
    
                    //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁
                    Thread.sleep(1000);
                }
            }catch (Exception e){
    
            }

    实现效果:

      产生新线条时,原本绘画线条不会发生改变

    二级缓存加载图片

    package com.example.administrator.myapplication;
    
    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.graphics.Rect;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    /**
     * Created by Administrator on 2018/8/9.
     */
    
    public class GameView extends SurfaceView implements Runnable, SurfaceHolder.Callback{
    
        public GameView(Context context) {
            super(context);
    
            getHolder().addCallback(this);  //注册回调方法
    
            gameBitmap = Bitmap.createBitmap(1200,1024, Bitmap.Config.ARGB_8888);
    
    
    
            bitmaps.add(BitmapFactory.decodeResource(getResources(),R.drawable.a3));
            bitmaps.add(BitmapFactory.decodeResource(getResources(),R.drawable.a4));
            bitmaps.add(BitmapFactory.decodeResource(getResources(),R.drawable.a5));
        }
    
        private List<Bitmap> bitmaps = new ArrayList<Bitmap>();
    
        private boolean runState = false;
        private SurfaceHolder holder = null;
        private Bitmap gameBitmap = null;
    
        @Override
        public void run() {
            Random ran = new Random();
            int index = 0;
            try{
                while(true) {
                    //获得绘画的画布
                    Canvas canvas =  holder.lockCanvas();
                    Paint p = new Paint();
                    Canvas c = new Canvas(gameBitmap);
    
                    c.drawBitmap( bitmaps.get(index++),0,0,p);
    
                    if(index==bitmaps.size()){
                        index=0;
                    }
                    //  p.setColor(Color.WHITE);
                    // c.drawRect(new Rect(0,0,500,500),p);    //白色背景
                    //  p.setColor(Color.rgb(ran.nextInt(255),ran.nextInt(255),ran.nextInt(255)));
                    //c.drawLine(ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),p);
    
                    canvas.drawBitmap(gameBitmap,0,0,new Paint());
    
                    //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁
                    Thread.sleep(1000);
                }
            }catch (Exception e){
    
            }
        }
    
        //视图创建时通知
        public void surfaceCreated(SurfaceHolder holder) {
            this.holder = holder;
            runState = true;
            new Thread(this).start();
    
    
        }
    
        //界面发生改变的时候通知
        public void surfaceChanged(SurfaceHolder holder, int i, int i1, int i2) {
    
        }
    
        //销毁时通知
        public void surfaceDestroyed(SurfaceHolder holder) {
            runState = false;
        }
    
    
    }
    GameView.java
    package com.example.administrator.myapplication;
    
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity{
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(new GameView(this));
    
        }
    
    }
    MainActivity.java

    添加图片进二级缓存中

    
    
          private List<Bitmap> bitmaps = new ArrayList<Bitmap>();


          bitmaps.add(BitmapFactory.decodeResource(getResources(),R.drawable.a3)); bitmaps.add(BitmapFactory.decodeResource(getResources(),R.drawable.a4)); bitmaps.add(BitmapFactory.decodeResource(getResources(),R.drawable.a5));

    运行程序时

    public void run() {
            Random ran = new Random();
            int index = 0;
            try{
                while(true) {
                    //获得绘画的画布
                    Canvas canvas =  holder.lockCanvas();
                    Paint p = new Paint();
                    Canvas c = new Canvas(gameBitmap);
    
                    c.drawBitmap( bitmaps.get(index++),0,0,p);
    
                    if(index==bitmaps.size()){
                        index=0;
                    }
                    //  p.setColor(Color.WHITE);
                    // c.drawRect(new Rect(0,0,500,500),p);    //白色背景
                    //  p.setColor(Color.rgb(ran.nextInt(255),ran.nextInt(255),ran.nextInt(255)));
                    //c.drawLine(ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),ran.nextInt(1000),p);
    
                    canvas.drawBitmap(gameBitmap,0,0,new Paint());
    
                    //把绘画好的内容提交上去
                    holder.unlockCanvasAndPost(canvas);//解锁
                    Thread.sleep(1000);
                }
            }catch (Exception e){
    
            }
        }
    (如需转载学习,请标明出处)
  • 相关阅读:
    supervisor(一)基础篇
    linux添加开机自启动脚本示例详解
    suse 不能远程登录
    LintCode,hihoCoder,LeetCode有什么区别?
    windows 下安装nodejs 要怎么设置环境变量
    Java 集合:HashSet 与 ArrayList
    Java ArrayList、Vector和LinkedList等的差别与用法(转)
    一行代码实现java list去重
    25 highest paying companies: Which tech co outranks Google, Facebook and Microsoft?
    Chart: Who pays the most in Seattle for software engineers
  • 原文地址:https://www.cnblogs.com/1138720556Gary/p/9451757.html
Copyright © 2020-2023  润新知