Android开发教程:游戏过程中按Home键后返回游戏界面


症状:游戏过程中,按下Home键返回手机主菜单,再点击游戏图标试图返回游戏的时候屏幕黑的一片!

以前一直没在意只有结束线程在运行游戏,今天觉得改仔细琢磨一下这个问题了!

首先第一件事:打印Logo看看按下Home键后会调用哪些方法,结果如下:

游戏过程中按下Home后:

11-29 20:42:07.090: I/System.out(18835): Activity onPause...
11-29 20:42:14.190: I/System.out(18835): Activity  onStop...
11-29 20:42:14.260: I/System.out(18835): SurfaceView surfaceDestroyed...

可见SurfaceView 在返回手机主菜单的时候被销毁了,而我的SurfaceView 主线程是在构造方法里创建的

那么我们返回游戏的时候会调哪些方法呢?接着看Log:

11-29 20:48:06.940: I/System.out(18835): Activity  onRestart...
11-29 20:48:06.950: I/System.out(18835): Activity  onResume...
11-29 20:48:07.230: I/System.out(18835): SurfaceView  surfaceCreated...
11-29 20:48:07.240: I/System.out(18835): SurfaceView  surfaceChanged...

surfaceDestroyed 的时候线程已经退出了运行,这时再返回到游戏刷屏的线程就没了,任何绘制方法都没调用,所以你看到的只有黑漆漆的屏幕啦!
明白了运行原理我们就知道改怎么做啦!

首先创建线程放在 surfaceCreated ,并启动线程,

当 surfaceDestroyed 调用的时候,线程已经无效了,我们把线程对象设为null释放他,

然后不管怎么返回线程都会继续运行你的游戏也就不会中断了,来段简单的代码更具表达力度!

  1. package com.game.view;  
  2.   
  3. import Android.content.Context;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Paint;  
  6. import android.graphics.Paint.Style;  
  7. import android.graphics.Rect;  
  8. import android.view.SurfaceHolder;  
  9. import android.view.SurfaceHolder.Callback;  
  10. import android.view.SurfaceView;  
  11.   
  12. public class TestView extends SurfaceView implements Callback, Runnable{  
  13.     public static final int GAME_HEART = 1000/30;   //每秒刷新30次   
  14.       
  15.     public static int screenW, screenH;  
  16.       
  17.     private Thread thread;  
  18.     private SurfaceHolder holder;  
  19.     private Paint paint;  
  20.       
  21.     public TestView(Context context) {  
  22.         super(context);  
  23.         // TODO Auto-generated constructor stub   
  24.         holder = getHolder();  
  25.         holder.addCallback(this);  
  26.           
  27.         paint = new Paint(Paint.ANTI_ALIAS_FLAG);// 无锯齿   
  28.         paint.setStyle(Style.FILL); //填充样式   
  29.         paint.setTextSize(16); // 字体大小   
  30.     }  
  31.   
  32.     /** 
  33.      * 执行游戏逻辑方法 
  34.      */  
  35.     private void update() {  
  36.           
  37.     }  
  38.       
  39.     /** 
  40.      * 执行游戏绘制 
  41.      */  
  42.     private Rect rect = new Rect();  
  43.     private void draw(){  
  44.         Canvas canvas = holder.lockCanvas();  
  45.           
  46.         String text = "天使之翼���示例Demo";  
  47.         //获取文本宽高   
  48.         paint.getTextBounds(text, 0, text.length(), rect);  
  49.         //在屏幕中央位置显示文本   
  50.         paint.setColor(0xfff000f0); //注意最高两位 ff 代表画笔透明度,不设置的画就是完全透明了,看不到任何效果   
  51.         canvas.drawText(text,   
  52.                 (screenW - rect.width())/2,   
  53.                 screenH/2 + rect.height()/2,   
  54.                 paint);  
  55.           
  56.         holder.unlockCanvasAndPost(canvas);  
  57.     }  
  58.       
  59.     @Override  
  60.     public void surfaceCreated(SurfaceHolder holder) {  
  61.         // TODO Auto-generated method stub   
  62.         screenW = getWidth();  
  63.         screenH = getHeight();  
  64.           
  65.         thread = new Thread(this);  
  66.         isRun = true;  
  67.         thread.start();  
  68.     }  
  69.   
  70.     @Override  
  71.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  72.         // TODO Auto-generated method stub   
  73.         //当屏幕旋转的时候重新获取屏幕宽高   
  74.         screenW = getWidth();  
  75.         screenH = getHeight();  
  76.     }  
  77.   
  78.     @Override  
  79.     public void surfaceDestroyed(SurfaceHolder holder) {  
  80.         // TODO Auto-generated method stub   
  81.         isRun = false;  
  82.         thread = null;  
  83.     }  
  84.   
  85.     private boolean isRun;  //线程运行标志   
  86.     private int useTime;    //记录每次刷屏使用的时间   
  87.     @Override  
  88.     public void run() {  
  89.         // TODO Auto-generated method stub   
  90.         long start, end;  
  91.           
  92.         while(isRun){  
  93.             start = System.currentTimeMillis();  
  94.             update(); // 刷新界面上所有元素   
  95.             draw(); // 绘制界面元素   
  96.             end = System.currentTimeMillis();  
  97.             useTime = (int) (end - start);  
  98.               
  99.             if(useTime < GAME_HEART){    //保证每次刷屏时间间隔相同   
  100.                 try {  
  101.                     Thread.sleep(GAME_HEART - useTime);  
  102.                 } catch (InterruptedException e) {  
  103.                     // TODO Auto-generated catch block   
  104.                     e.printStackTrace();  
  105.                 }  
  106.             }  
  107.         }  
  108.     }  
  109. }  

相关内容