分享一个android真正实用的游戏框架(来自安卓航班网)

其主要“实用”之处在于:
1.框架整体很小,上手快,做大游戏的公司没多少,做小游戏的个人开发者铺天盖地,相比动则上升到引擎级的庞然大物,小型的框架更加实用,更加考虑大多数开发者的利益。
2.小不等于不完善,之所以剥SDK的游戏示例代码的框架出来,就是学习后发现它对于系统事件的处理比较完善,另外我个人还修正了它对于来电处理等异常事件不完美之处,使其更加完善。
R.layout.main 布局文件
  1.    
  2.    
  3.         xmlns:android="http://schemas.android.com/apk/res/android"
  4.         android:orientation="vertical"
  5.         android:layout_width="match_parent"
  6.         android:layout_height="match_parent">
  7.         
  8.             android:id="@+id/gameview"
  9.             android:layout_width="match_parent"
  10.             android:layout_height="match_parent" />
  11.         
  12.             android:layout_width="match_parent"
  13.             android:layout_height="match_parent">
  14.             
  15.                 android:id="@+id/textview"
  16.                 android:layout_width="wrap_content"
  17.                 android:layout_height="wrap_content"
  18.                 android:layout_centerInParent="true"
  19.                 android:gravity="center_horizontal"
  20.                 android:textColor="#88ffffff"
  21.                 android:textSize="24sp" />
  22.         
  23.    
复制代码
Activity类
  1.     package com.mstanford.gameframework;
  2.     import com.mstanford.gameframe.R;
  3.     import android.app.Activity;
  4.     import android.os.Bundle;
  5.     import android.util.Log;
  6.     import android.view.Menu;
  7.     import android.view.MenuItem;
  8.     import android.widget.TextView;
  9.     public class GameActivity extends Activity {
  10.     private GameSurfaceView gameSurfaceView;
  11.     private GameThread gameThread;
  12.     @Override
  13.     public void onCreate(Bundle savedInstanceState) {
  14.       super.onCreate(savedInstanceState);
  15.       setContentView(R.layout.main);
  16.       gameSurfaceView = (GameSurfaceView) this.findViewById(R.id.gameview);
  17.       gameThread = gameSurfaceView.getThread();
  18.       gameSurfaceView.setTextView((TextView) findViewById(R.id.textview));
  19.       if (savedInstanceState == null) {
  20.        // 游戏第一次启动时,初始化游戏状态
  21.        gameThread.doStart();
  22.        Log.w(this.getClass().getName(), "SIS is null");
  23.       }
  24.       else {
  25.        // 从其他应用界面切回游戏时,如果Activity重新创建,则恢复上次切出游戏时的各项数据
  26.        gameThread.restoreState(savedInstanceState);
  27.        Log.w(this.getClass().getName(), "SIS is nonnull");
  28.       }
  29.     }
  30.     /**
  31.       * 当Activity被切换到后台时调用,存储Activity重新创建时需要恢复的游戏数据
  32.       */
  33.     @Override
  34.     protected void onSaveInstanceState(Bundle outState) {
  35.       super.onSaveInstanceState(outState);
  36.       gameThread.saveState(outState);
  37.       Log.w(this.getClass().getName(), "SIS called");
  38.     }
  39.     /**
  40.       * 当Activity被切换到后台时调用,在这里对游戏做"暂停"的处理
  41.       */
  42.     @Override
  43.     protected void onPause() {
  44.       super.onPause();
  45.       // 暂停游戏
  46.       gameSurfaceView.getThread().pause();
  47.     }
  48.     /**
  49.       * 当Activity切换到前台时调用
  50.       */
  51.     @Override
  52.     protected void onResume() {
  53.       super.onResume();
  54.       // 游戏结束暂停状态,游戏正常进行
  55.       gameSurfaceView.getThread().unpause();
  56.     }
  57.     /**
  58.       * 创建游戏菜单
  59.       */
  60.     @Override
  61.     public boolean onCreateOptionsMenu(Menu menu) {
  62.       // TODO Auto-generated method stub
  63.       return super.onCreateOptionsMenu(menu);
  64.     }
  65.     /**
  66.       * 定义游戏菜单的点击事件处理
  67.       */
  68.     @Override
  69.     public boolean onOptionsItemSelected(MenuItem item) {
  70.       // TODO Auto-generated method stub
  71.       return super.onOptionsItemSelected(item);
  72.     }
  73.     @Override
  74.     protected void onDestroy() {
  75.       super.onDestroy();
  76.       Log.v(this.getClass().getName(), "onDestroy");
  77.       
  78.       //停止游戏
  79.       gameThread.setRunning(false);
  80.       boolean retry = true;
  81.       while (retry) {
  82.        try {
  83.         //阻塞Activity的主线程直到游戏线程执行完
  84.         gameThread.join();
  85.         retry = false;
  86.        } catch (InterruptedException e) {
  87.        }
  88.       }
  89.     }
  90.     }
复制代码
SurfaceView类
  1.     package com.mstanford.gameframework;
  2.     import android.content.Context;
  3.     import android.os.Handler;
  4.     import android.os.Message;
  5.     import android.util.AttributeSet;
  6.     import android.util.Log;
  7.     import android.view.KeyEvent;
  8.     import android.view.SurfaceHolder;
  9.     import android.view.SurfaceView;
  10.     import android.view.SurfaceHolder.Callback;
  11.     import android.widget.TextView;
  12.     public class GameSurfaceView extends SurfaceView implements Callback {
  13.     private GameThread gameThread;
  14.     private TextView textview;
  15.     public GameSurfaceView(Context context, AttributeSet attrs) {
  16.       super(context, attrs);
  17.       SurfaceHolder holder = getHolder();
  18.       holder.addCallback(this);
  19.       gameThread = new GameThread(holder, context, new Handler() {
  20.        @Override
  21.        public void handleMessage(Message m) {
  22.         textview.setText(m.getData().getString("text"));
  23.        }
  24.       });
  25.       // 设置可获得焦点,确保能捕获到KeyEvent
  26.       setFocusable(true);
  27.     }
  28.     /**
  29.       * 获取一个Activity传来的View协助SurfaceView显示游戏视图,View的具体类型可以根据游戏需要来定
  30.       */
  31.     public void setTextView(TextView view) {
  32.       this.textview = view;
  33.     }
  34.     public GameThread getThread() {
  35.       return gameThread;
  36.     }
  37.     @Override
  38.     public boolean onKeyDown(int keyCode, KeyEvent event) {
  39.       return gameThread.doKeyDown(keyCode, event);
  40.     }
  41.     @Override
  42.     public boolean onKeyUp(int keyCode, KeyEvent event) {
  43.       return gameThread.doKeyUp(keyCode, event);
  44.     }
  45.     /**
  46.       * 当SurfaceView得到或失去焦点时调用,使游戏暂停/恢复运行,
  47.       */
  48.     @Override
  49.     public void onWindowFocusChanged(boolean hasWindowFocus) {
  50.       if (!hasWindowFocus) {
  51.        gameThread.pause();
  52.       }
  53.       else {
  54.        gameThread.unpause();
  55.       }
  56.     }
  57.     @Override
  58.     public void surfaceChanged(SurfaceHolder holder, int format, int width,
  59.        int height) {
  60.       Log.v(this.getClass().getName(), "surfaceChanged()");
  61.       gameThread.setSurfaceSize(width, height);
  62.       gameThread.setRunning(true);
  63.       if (gameThread.isAlive()) {
  64.        Log.v(this.getClass().getName(), "unpause gameThread");
  65.        gameThread.unpause();
  66.       }
  67.       else {
  68.        Log.v(this.getClass().getName(), "start gameThread");
  69.        gameThread.start();
  70.       }
  71.     }
  72.     @Override
  73.     public void surfaceCreated(SurfaceHolder holder) {
  74.       Log.v(this.getClass().getName(), "surfaceCreated()");
  75.       }
  76.     /**
  77.       * 为防止surface还会被创建(比如来电)导致gameThread再次启动出现错误,且Activity的onPause方法中已做暂停处理,
  78.       * 这边不对gameThread做处理
  79.       * @param holder
  80.       */
  81.     @Override
  82.     public void surfaceDestroyed(SurfaceHolder holder) {
  83.       Log.v(this.getClass().getName(), "surfaceDestroyed");
  84.     }
复制代码
游戏线程类
  1.     package com.mstanford.gameframework;
  2.     import android.content.Context;
  3.     import android.graphics.Canvas;
  4.     import android.os.Bundle;
  5.     import android.os.Handler;
  6.     import android.util.Log;
  7.     import android.view.KeyEvent;
  8.     import android.view.SurfaceHolder;
  9.     public class GameThread extends Thread {
  10.     // 游戏状态值:ready
  11.     public final static int GS_READY = 0;
  12.     //游戏线程每执行一次需要睡眠的时间
  13.     private final static int DELAY_TIME = 100;
  14.     //上下文,方便获取到应用的各项资源,如图片、音乐、字符串等
  15.     private Context context;
  16.     //与Activity其他View交互用的handler
  17.     private Handler handler;
  18.     //由SurfaceView提供的SurfaceHolder
  19.     private SurfaceHolder surfaceHolder;
  20.     //游戏线程运行开关
  21.     private boolean running = false;
  22.     //游戏状态
  23.     private int gameState;
  24.     //当前surface/canvas的高度,在surfaceChanged方法中被设置
  25.         private int mCanvasHeight = 1;
  26.       //当前surface/canvas的宽度,在surfaceChanged方法中被设置
  27.         private int mCanvasWidth = 1;
  28.       
  29.         /**
  30.          * 游戏是否暂停
  31.          */
  32.         private boolean isPaused = false;
  33.     public GameThread(SurfaceHolder holder, Context context, Handler handler) {
  34.       this.surfaceHolder = holder;
  35.       this.context = context;
  36.       this.handler = handler;
  37.     }
  38.     /**
  39.       * 设置游戏状态
  40.       * @param mode 游戏状态
  41.       */
  42.     public void setState(int mode) {
  43.       synchronized (surfaceHolder) {
  44.        setState(mode, null);
  45.       }
  46.     }
  47.     /**
  48.       * 设置游戏状态
  49.       * @param mode 游戏状态
  50.       * @param message 设置游戏状态时的附加文字信息
  51.       */
  52.     public void setState(int mode, CharSequence message) {
  53.       synchronized (surfaceHolder) {
  54.        // TODO
  55.       }
  56.     }
  57.     /**
  58.       * 暂停游戏
  59.       */
  60.     public void pause() {
  61.       synchronized (surfaceHolder) {
  62.        isPaused = true;
  63.       }
  64.     }
  65.     /**
  66.       * 恢复运行游戏
  67.       */
  68.     public void unpause() {
  69.       //如果游戏中有时间,别忘记应将其在这里调整到正常
  70.       synchronized (surfaceHolder) {
  71.        isPaused = false;
  72.       }
  73.     }
  74.     /**
  75.       * 当Activity因销毁而被重新创建时,在这里恢复游戏上次运行的数据
  76.       * @param saveState Activity传来的保存游戏数据的容器
  77.       */
  78.     public void restoreState(Bundle saveState) {
  79.       //TODO
  80.     }
  81.     /**
  82.       * 在Activity切到后台时保存游戏的数据
  83.       * @param outState 保存游戏数据的容器
  84.       */
  85.     public void saveState(Bundle outState)
  86.     {
  87.       //TODO
  88.     }
  89.     /**
  90.       * 设置游戏线程运行开关
  91.       * @param b 开/关
  92.       */
  93.     public void setRunning(boolean b) {
  94.       running = b;
  95.     }
  96.     /**
  97.       * 处理按下按键的事件
  98.       * @param keyCode 按键事件动作值
  99.       * @param msg 按键事件对象
  100.       * @return 是否处理完
  101.       */
  102.     public boolean doKeyDown(int keyCode, KeyEvent msg) {
  103.       synchronized (surfaceHolder) {
  104.        // TODO
  105.        return false;
  106.       }
  107.     }
  108.     /**
  109.       * 处理弹起按键的事件
  110.       * @param keyCode 按键事件动作值
  111.       * @param msg 按键事件对象
  112.       * @return 是否处理完
  113.       */
  114.     public boolean doKeyUp(int keyCode, KeyEvent msg) {
  115.       synchronized (surfaceHolder) {
  116.        // TODO
  117.       }
  118.       return false;
  119.     }
  120.     /**
  121.       * 设置surface/canvas的宽度和高度
  122.       * @param width 由SurfaceHolder传来的宽度
  123.       * @param height 由SurfaceHolder传来的高度
  124.       */
  125.     public void setSurfaceSize(int width, int height) {
  126.       // synchronized to make sure these all change atomically
  127.       synchronized (surfaceHolder) {
  128.        mCanvasWidth = width;
  129.        mCanvasHeight = height;
  130.        //不要忘记每次画布的宽度和高度改变时, 在这里对图片等资源做缩放等相关适配屏幕的处理
  131.        //TODO
  132.       }
  133.     }
  134.     public void run() {
  135.       while (running) {
  136.        if (!isPaused) {
  137.         Canvas c = null;
  138.         try {
  139.          c = surfaceHolder.lockCanvas(null);
  140.          synchronized (surfaceHolder) {
  141.           doDraw(c);
  142.          }
  143.          logic();
  144.         } finally {
  145.          if (c != null) {
  146.           surfaceHolder.unlockCanvasAndPost(c);
  147.          }
  148.         }
  149.         try {
  150.          Thread.sleep(DELAY_TIME);
  151.         } catch (InterruptedException e) {
  152.          e.printStackTrace();
  153.         }
  154.        }
  155.       }
  156.     }
  157.     /**
  158.       * 游戏逻辑处理
  159.       */
  160.     public void logic()
  161.     {
  162.       Log.v(this.getClass().getName(), "logic");
  163.       //TODO
  164.     }
  165.     /**
  166.       * 游戏绘画
  167.       */
  168.     private void doDraw(Canvas canvas) {
  169.       Log.v(this.getClass().getName(), "doDraw");
  170.       //TODO
  171.     }
  172.     /**
  173.       * 初始化游戏开始时的参数
  174.       */
  175.     private void doStart() {
  176.       //TODO
  177.     }
  178.     }

转载于:https://www.cnblogs.com/androidghost/archive/2011/05/06/android2.html

你可能感兴趣的:(分享一个android真正实用的游戏框架(来自安卓航班网))