分享一个android真正实用的游戏框架

前面有些同学已发过几个游戏框架,我把android SDK中游戏示例代码的框架也剥出来共享给大家,自称为真正实用的游戏框架。已拿其开发过一款游戏,感觉还可以。
其主要“实用”之处在于:
1.框架整体很小,上手快,做大游戏的公司没多少,做小游戏的个人开发者铺天盖地,相比动则上升到引擎级的庞然大物,小型的框架更加实用,更加考虑大多数开发者的利益。
2.小不等于不完善,之所以剥SDK的游戏示例代码的框架出来,就是学习后发现它对于系统事件的处理比较完善,另外我个人还修正了它对于来电处理等异常事件不完美之处,使其更加完善。

多的话不说,代码全贴在这吧,做过游戏开发的同学一看就知道好不好用。欢迎大家采用,如对此框架还有修改建议,请QQ联系:76359570,无事还请勿扰。


R.layout.main 布局文件
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout
  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.     <com.mstanford.gameframework.GameSurfaceView
  8.         android:id="@+id/gameview"
  9.         android:layout_width="match_parent"
  10.         android:layout_height="match_parent" />
  11.     <RelativeLayout
  12.         android:layout_width="match_parent"
  13.         android:layout_height="match_parent">
  14.         <TextView
  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.     </RelativeLayout>
  23. </FrameLayout>
复制代码
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. }
复制代码
  GameFramework (1).rar (52.27 KB, 下载次数: 73) 


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值