Android基本游戏循环

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linzhihan7410/article/details/53453426

开始前必须知道的知识:
视觉暂留
视觉暂留现象即视觉暂停现象(Persistence of vision,Visual staying phenomenon,duration of vision)又称“余晖效应”.
1824年由英国伦敦大学教授皮特‘马克’罗葛特在他的研究报告《移动物体的视觉暂留现象》中最先提出.
人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失
这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”.

图像刷新的慢的话,看到的游戏画面就会卡屏,类似FPS(每秒传输帧数(Frames Per Second))
!!!正常情况下,一秒时间内刷新得画面个数是24个

为什么使用SurfaceView:
双缓冲:消除由复杂绘制操作造成的图像闪烁
SurfaceView带有双缓冲机制,但是View没有(双缓冲:在内存中把显示的图像处理好,然后再加载到屏幕,详细可自行百度)

代码流程:
1.创建Android项目(把默认产生的layout文件删除,这里使用自定义视图类实例化图像)

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MySurafaceView(this));  //实例化自定义的视图类
    }
}

2.SurfaceView类的创建 (创建一个新类名字叫MySurafaceView继承SurView)

implements anroid.view.SurfaceHolaer.Callback产生回调

    //在mysurfaceView创建的时候要做什么
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {   

    }

    //在视图改变的时候要做什么
    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {

    }
    //在视图销毁的时候要做什么
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    }

3.创建线程,进行图像的更新

implements Runnable
重写Run方法
  public void draw(){   //实际画图操作

    }

 @Override
    public void run() {     //进行图像更新,不断的绘图
        while (runFLag){
            draw();
        }
    }

4.创建surfaceHolder对象用来操作surfaceView,并添加监听

public SurfaceHolder surfaceHolder;
 在构造方法里面
 public MySurafaceView(Context context) {
        super(context);
        surfaceHolder = this.getHolder();       //实例化
        surfaceHolder.addCallback(this);        //添加监听
    }

5.在surfaceCreated创建Thread类对象(很重要)
为什么要在surfaceCreated创建线程
因为如果是在构造方法中创建线程,会导致图没构造出来就开始画图
所以要在surfaceCreated(画出图形后)才能继续进行想要的绘图操作

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {   //surfaceView创建的时候
        runFLag = true;
        thread = new Thread(this);
        thread.start();
    }

6.完成draw方法的画图操作

 public void draw(){
        try {
            canvas = surfaceHolder.lockCanvas();  //在任意时刻,只有一个线程能够操作屏幕,并且实例化
            if(canvas != null){
                canvas.drawColor(Color.BLACK);
                canvas.drawText("Hello!!",100,100,paint);
            }

        }catch (Exception e){

        }finally {
            surfaceHolder.unlockCanvasAndPost(canvas);   //在最后要做解锁
        }
    }

**为什么要上锁,因为在一个游戏中,有许多线程来对一个屏幕画图(刷新),这时候必须保证一个顺序问题

7.做线程的频率刷新

@Override
    public void run() {                                                     //进行图像更新,不断的绘图
        while (runFLag){
            long start = System.currentTimeMillis();                        //画图执行前时间
        draw();
            long end = System.currentTimeMillis();                          //画图完成后时间
            if(end-start<50){                                               //控制频率为50ms一次   人的暂留视觉大概是1/24 秒,也就是一秒24张图
                try {
                    thread.sleep(50-(end-start));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

8.用户触摸时,可移动画出来的图像

  @Override
    public boolean onTouchEvent(MotionEvent event) {             //触摸监听事件
        x = (int) event.getX();                                  //得到当前事件的x坐标
        y = (int) event.getY();                                  //得到当前事件的y坐标
        return true;
    }
@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {     //按键按下事件
        return super.onKeyDown(keyCode, event);
    }

9.全屏化

    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);  //窗口无标题
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); //设置
        setContentView(new MySurafaceView(this));  //这里不使用默认产生的Layout文件,这里是实例化MySurafaceView,游戏一般都是自定义视图
    }
}

10.线程循环

    while (runFLag){    //满足某个条件
        //do something
    }

完整的代码:

//MainActivity 
package com.example.adminis.newgameapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(new MySurafaceView(this));
    }
}

//MySurafaceView类
package com.example.adminis.newgameapp;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by Adminis on 2016/12/4.
 */
public class MySurafaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable {

    public boolean runFLag = true;
    public SurfaceHolder surfaceHolder;
    private Thread thread;
    public Paint paint;         //画笔
    public Canvas canvas;       //画布
    public int x = 100,y = 100; //用于储存触摸的坐标
    public MySurafaceView(Context context) {
        super(context);
        surfaceHolder = this.getHolder();       //实例化
        surfaceHolder.addCallback(this);        //添加监听
        paint = new Paint();
        paint.setColor(Color.WHITE);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {   //surfaceView创建的时候
        runFLag = true;
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {    //视图进行更新的时候

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {                         //视图进行销毁的时候

    }

    public void draw(){
        try {
            canvas = surfaceHolder.lockCanvas();                                        //在任意时刻,只有一个线程能够操作屏幕,并且实例化
            if(canvas != null){
                canvas.drawColor(Color.BLACK);
                canvas.drawText("Hello!!", x, y, paint);
            }

        }catch (Exception e){

        }finally {
            surfaceHolder.unlockCanvasAndPost(canvas);                                  //在最后要做解锁
        }
    }

    @Override
    public void run() {                                                                 //进行图像更新,不断的绘图
        while (runFLag){
            long start = System.currentTimeMillis();                                    //画图执行前时间
            draw();
            long end = System.currentTimeMillis();                                      //画图完成后时间
            if(end-start<46){                                                           //控制频率为50ms一次   人的暂留视觉大概是1/24 秒,也就是一秒24张图
                try {
                    thread.sleep(46-(end-start));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {             //触摸监听事件
        x = (int) event.getX();                                  //得到当前事件的x坐标
        y = (int) event.getY();                                  //得到当前事件的y坐标
        return true;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {     //按键按下事件
        return super.onKeyDown(keyCode, event);
    }
}

猜你喜欢

转载自blog.csdn.net/linzhihan7410/article/details/53453426
今日推荐