(游戏)打飞机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){ }
}

Android_(游戏)打飞机01:前言的更多相关文章

  1. Android_(游戏)打飞机06:后续

    (游戏)打飞机01:前言 传送门 (游戏)打飞机02:游戏背景滚动 传送门 (游戏)打飞机03:控制玩家飞机 传送门 (游戏)打飞机04:绘画敌机.添加子弹   传送门 (游戏)打飞机05:处理子弹, ...

  2. Android_(游戏)打飞机05:处理子弹,击中敌机,添加计分板

    (游戏)打飞机01:前言 传送门 (游戏)打飞机02:游戏背景滚动 传送门 (游戏)打飞机03:控制玩家飞机 传送门 (游戏)打飞机04:绘画敌机.添加子弹   传送门 (游戏)打飞机05:处理子弹, ...

  3. Android_(游戏)打飞机04:绘画敌机、添加子弹

    (游戏)打飞机01:前言 传送门 (游戏)打飞机02:游戏背景滚动 传送门 (游戏)打飞机03:控制玩家飞机 传送门 (游戏)打飞机04:绘画敌机.添加子弹   传送门 (游戏)打飞机05:处理子弹, ...

  4. Android_(游戏)打飞机03:控制玩家飞机

    (游戏)打飞机01:前言 传送门 (游戏)打飞机02:游戏背景滚动 传送门 (游戏)打飞机03:控制玩家飞机 传送门 (游戏)打飞机04:绘画敌机.添加子弹   传送门 (游戏)打飞机05:处理子弹, ...

  5. Android_(游戏)打飞机02:游戏背景滚动

    (游戏)打飞机01:前言 传送门 (游戏)打飞机02:游戏背景滚动 传送门 (游戏)打飞机03:控制玩家飞机 传送门 (游戏)打飞机04:绘画敌机.添加子弹   传送门 (游戏)打飞机05:处理子弹, ...

  6. Python之游戏开发-飞机大战

    Python之游戏开发-飞机大战 想要代码文件,可以加我微信:nickchen121 #!/usr/bin/env python # coding: utf-8 import pygame impor ...

  7. Python小游戏之 - 飞机大战美女 !

    用Python写的"飞机大战美女"小游戏 源代码如下: # coding=utf-8 import os import random import pygame # 用一个常量来存 ...

  8. 01 前言/基础设施 - DevOps之路

    01 前言/基础设施 - DevOps之路 文章Github地址,欢迎start:https://github.com/li-keli/DevOps-WiKi 简介 基础架构采用DevOps设计思想, ...

  9. 微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)

    微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞 ...

随机推荐

  1. 最短meeting路线(树的直径)--牛客第四场(meeting)

    题意: 给你一棵树,树上有些点是有人的,问你选一个点,最短的(最远的那个人的距离)是多少. 思路: 其实就是树的直径,两遍dfs,dfs第二遍的时候遇到人就更新直径就行了,ans是/2,奇数的话+1. ...

  2. IDEA2018.2.6激活(可用)

    破解插件下载: 链接:https://pan.baidu.com/s/1j2_kEm_Akcph6Qb8hr6soQ 提取码:hv64 将下载包放入bin文件夹下,修改bin中的两个文件 idea.e ...

  3. golang中格式化符号说明

    %v 值的默认格式表示 %+v 类似%v,但输出结构体时会添加字段名 %#v 值的Go语法表示 %T 值的类型的Go语法表示 %% 百分号 布尔值: %t 单词true或false 整数: %b 表示 ...

  4. linux安装git服务器和svn服务器

    linux版本 linux版本为CentOS 6.8 (要注意有些软件的安装方法在各个linux版本之间也是存在差异的) git服务器 git服务器需要提供一个UI供开发人员创建项目管理项目,选择使用 ...

  5. Java 类的构造器中this()和super()的困惑

    关于构造器中super的使用,书本上这样写: “super是指向父类的引用,如果构造方法没有显示地调用父类的构造方法,那么编译器会自动为它加上一个默认的super()方法调用.如果父类由没有默认的无参 ...

  6. [Next] next中文文档

    Next.js 是一个轻量级的 React 服务端渲染应用框架. 怎么使用 安装 在项目文件夹中运行: npm install --save next react react-dom 将下面脚本添加到 ...

  7. linux环境下tomcat启动成功,部分请求页面出现404

    这种情况很多,本文记录我遇到比较奇葩的情况. 第一种情况: 第一次tomact启动成功,访问404,乱捣鼓不知怎么好了:第二次tomcat启动成功,可以访问部分链接,有些却报404,但是代码和数据都还 ...

  8. 第一篇 jQuery

    1-1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...

  9. 对xxl-job进行simpleTrigger并动态创建任务扩展

    业务场景 需求上要求能实现quartz的simpleTrigger任务,同时还需要动态的创建任务而非在控制面板上创建,查阅xxl-job官方文档发现simpelTrigger其暂时还躺在to do l ...

  10. python 出现OSError: [Errno 8] Exec format error的原因

    访问 .py文件的网页的时候会出现 Exec format error的问题, 一般情况下是由于基于Unix(Linux,Mac OS)系统下的问题,办法如下 1 .chmod +x  filenam ...