用SurfaceView制作简单的android游戏 : 重力小球(1)--------创建游戏整体框架
在android平台制作游戏可以用view或者是SurfaceView,前者是当用户产生点击或其他动作,view才会做出相应的更新,可以看成是被动的;
SurfaceView是开一线程让画面在其中描绘(可以看成是缓冲区),每隔一定时间再把描绘好的画面更新到主画面
具体更详细的研究可以点击这里查看.
本文代码参考自某日文教程,可以点击这里查看, 游戏名为IrairaBar, 开发环境为sdk2.2,
因为涉及重力感应器的使用所以需要真机测试
整个游戏的运行逻辑如下图
update负责确定物体位置,检测碰撞,计算各种数值之类的工作, draw就只负责描画
1.首先新建项目后再创建两个文件,如下图
IrairaBarActivity.java代码
public class IrairaBarActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //把目标activity设置为GameSurfaceView setContentView( new GameSurfaceView(this) ); } }
GameSurfaceView.java代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { Thread _thread; public GameSurfaceView(Context context) { super(context); //获取holder并传给callback函数 getHolder().addCallback(this); } //这个函数是当SurfaceView的大小改变了才会调用,这里暂时没用 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { //新开线程 _thread = new Thread(this); _thread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { _thread = null; } @Override public void run() { //游戏运行的主循环 while (_thread!=null) { onDraw(getHolder()); } } private void onDraw(SurfaceHolder holder) { Canvas c = holder.lockCanvas(); //这里用来描绘画面元素 holder.unlockCanvasAndPost(c); } }
2.然后添加一些类来控制fps
Task.java (纯粹是用来继承的抽象类)
public abstract class Task { public boolean onUpdate() { return true; } public void onDraw(Canvas c) { } }
FpsController.java (用来控制fps的, 继承task)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class FpsController extends Task { private long _startTime = 0; // 开始时间 private int _cnt = 0; // 计数 private Paint _paint = new Paint(); // paint情报 private float _fps; // fps private final static int N = 60; // 平均数 private final static int FONT_SIZE = 20; // 字体大小 public FpsController() { _paint.setColor(Color.BLUE); // 设定字体为蓝色 _paint.setTextSize(FONT_SIZE); // 设定字体大小 } @Override public boolean onUpdate() { if (_cnt == 0) { // 第一幀开始记录当前系统时间 _startTime = System.currentTimeMillis(); } if (_cnt == N) { // 第六十幀时计算平均帧数 long t = System.currentTimeMillis(); _fps = 1000.f / ((t - _startTime) / (float) N); _cnt = 0; _startTime = t; } _cnt++; return true; } @Override public void onDraw(Canvas c) { c.drawText(String.format("%.1f", _fps), 0, FONT_SIZE-2, _paint); } }
GameMgr.java (顾名思义,gameManager, 管理所有update和draw)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class GameMgr { //用来装task的容器 private LinkedList<Task> _taskList = new LinkedList<Task>(); //添加task GameMgr(){ _taskList.add( new FpsController() ); } //逐一更新tasklist里面的任务 public boolean onUpdate() { for(int i=0; i<_taskList.size(); i++){ //更新失败的话就把task移除 if(_taskList.get(i).onUpdate() == false){ _taskList.remove(i); i--; } } return true; } //逐一描画 public void onDraw(Canvas c) { //把屏幕涂白,相当于清屏的作用 c.drawColor(Color.WHITE); for(int i=0; i<_taskList.size(); i++){ _taskList.get(i).onDraw(c); } } }
3.最后把gameManager加到GameSurfaceView里面去
代码如下,注释部分为需要加进去的代码(请自行去掉注释的//)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable { // private GameMgr _gameMgr = new GameMgr(); private Thread _thread; public GameSurfaceView(Context context) { super(context); getHolder().addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { _thread = new Thread(this); _thread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { _thread = null; } @Override public void run() { while (_thread!=null) { // _gameMgr.onUpdate(); onDraw(getHolder()); } } private void onDraw(SurfaceHolder holder) { Canvas c = holder.lockCanvas(); // _gameMgr.onDraw(c); holder.unlockCanvasAndPost(c); } }
最后真机测试如下图