这两天,没事想学习游戏开发,看了一些资料之后准备开始。为了将来编码方便,先写了一个简单的游戏框架方便自己以后做练习用。
如果以后没有什么特殊的需求--比如opengl什么的,会尽量用这个简单框架来实现。有优化的地方会在这个里边一直更新,也希望有问题的地方希望大家帮忙提一些意见
我的刷新线程基础类
/** * 我的刷新线程 */ abstract class LoopThread extends Thread{ private boolean DEBUG = true; private Object lock = new Object(); public static final int RUNNING = 1; public static final int PAUSE = 2; public static final int STOP = 0; public int runState = STOP; private WeakReference<CustomSurfaceViewCallBack> callbackRef ; public LoopThread(CustomSurfaceViewCallBack view){ super(); callbackRef = new WeakReference<CustomSurfaceViewCallBack>(view); } @Override public void run() { try { loop(); } catch (InterruptedException e) { this.interrupt(); }finally{ this.runState = STOP; tRelase(); if(DEBUG){ System.out.println(this.getName()+" exit, lock="+lock); } } } private void loop() throws InterruptedException { while(runState!=STOP){ synchronized (lock) { while (runState == RUNNING) { CustomSurfaceViewCallBack callBack = callbackRef.get(); if (callBack == null) { runState = STOP; break; } onLoop(callBack); if (runState == RUNNING) { lock.wait(500); } else { break; } } if(runState==PAUSE){ lock.wait(); }else if(runState==STOP){ lock.notifyAll(); return; } } } } public abstract void onLoop(CustomSurfaceViewCallBack callBack); public void tRelase(){ callbackRef = null; } public void tResume(){ synchronized (lock) { this.runState = LoopThread.RUNNING; lock.notifyAll(); } } public void tPause(){ synchronized (lock) { this.runState = LoopThread.PAUSE; lock.notifyAll(); } } public boolean tStop(){ synchronized (lock) { this.tRelase(); this.runState = LoopThread.STOP; lock.notifyAll(); } while(true){ try { this.join(); return true; } catch (InterruptedException e) { this.interrupt(); } } } }
刷新接口
public interface CustomSurfaceViewCallBack { public abstract boolean processing(); public abstract void doDraw(Canvas canvas); public SurfaceHolder getSurfaceHolder(); }
游戏的显示界面的基础类
abstract class CustomSurfaceView extends SurfaceView implements Callback,CustomSurfaceViewCallBack{ private LoopThread dt; private ProcessThread pt; private SurfaceHolder sHolder; public CustomSurfaceView(Context context) { super(context); sHolder = getHolder(); sHolder.addCallback(this); } private boolean singleThread = false; /** * 设置是否用单线程来刷新界面和处理数据。 * 一般来说,为了保证流畅性游戏开发刷新界面的线程和数据处理线程是分开的。如果数据处理耗时,最好分开。如果数据处理耗时较少,可以使用单线程 * @param single */ public void setSingleThread(boolean single){ if(dt!=null){ throw new UnsupportedOperationException("must invoke setSingleThread before surfaceCreated"); } this.singleThread = single; } @Override public void surfaceCreated(SurfaceHolder holder) { start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {} @Override public void surfaceDestroyed(SurfaceHolder holder) { stop(); } /** * 进行界面绘制操作 * @param canvas */ public abstract void doDraw(Canvas canvas); /** * 处理数据 并判断是否进行界面重绘 * @return */ public abstract boolean processing(); @Override public SurfaceHolder getSurfaceHolder(){ return getHolder(); } public void start(){ if(singleThread){// 如果是单线程的话,初始化一个整合了数据处理和界面刷新一起处理的线程 stop(); dt= new SingleThread(this); dt.runState = LoopThread.RUNNING; dt.start(); return; } if(stop(dt)){ dt = new DrawThread(this); dt.runState = LoopThread.RUNNING; dt.start(); } if(stop(pt)){ pt = new ProcessThread(this); pt.runState = LoopThread.RUNNING; pt.start(); } } /** * 停止一个LoopThread 停止成功返回false * @param t * @return */ private boolean stop(LoopThread t){ if(t==null){ return true; } return t.tStop(); } /** * 游戏停止 */ public void stop(){ stop(dt); stop(pt); } /** * 游戏暂停 */ public void pause(){ if(dt!=null){ dt.tPause(); } if(pt!=null){ pt.tPause(); } } /** * 只可以从游戏暂停状态让游戏开始 */ public void resume(){ if(dt!=null){ dt.tResume(); } if(pt!=null){ pt.tPause(); } } /** * 界面绘制线程 * @author cs */ private static class DrawThread extends LoopThread{ public DrawThread(CustomSurfaceView view) { super(view); this.setName("DrawThread--"+this.getId()); } @Override public void onLoop(CustomSurfaceViewCallBack callBack) { drawByCallback(callBack); } } /** * 如果是单线程刷新的话,用到的线程类 * @author cs */ private static class SingleThread extends LoopThread{ public SingleThread(CustomSurfaceView view) { super(view); this.setName("SingleThread--"+this.getId()); } @Override public void onLoop(CustomSurfaceViewCallBack callBack) { callBack.processing(); drawByCallback(callBack); } } /** * 数据处理以及逻辑判断线程 * @author cs */ private static class ProcessThread extends LoopThread{ public ProcessThread(CustomSurfaceViewCallBack callBack) { super(callBack); this.setName("ProcessThread--"+this.getId()); } @Override public void onLoop(CustomSurfaceViewCallBack callBack) { if(callBack!=null){ callBack.processing(); } } } private static void drawByCallback(CustomSurfaceViewCallBack callBack) { Canvas canvas = null; try { canvas = callBack.getSurfaceHolder().lockCanvas(); if (canvas != null) { callBack.doDraw(canvas); } } catch (Exception e) { e.printStackTrace(); } finally { if (canvas != null) callBack.getSurfaceHolder().unlockCanvasAndPost(canvas); } } }
显示的实现还是上篇中要显示的贝塞尔曲线。当然,实现起来比原来代码简单多了
public class PathActivity extends Activity { private CustomSurfaceView pathView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); pathView = new PathView(this); pathView.setSingleThread(false); this.setContentView(pathView); } private static class PathView extends CustomSurfaceView{ private int vWidth; private int vHeight; private Paint pPaint; private Path mPath; private float endX; private float endY; private Random random; public PathView(Context context) { super(context); pPaint = new Paint(); pPaint.setAntiAlias(true); pPaint.setColor(0xaf22aa22); pPaint.setStyle(Paint.Style.STROKE); mPath = new Path(); random = new Random(); } private void init(){ vWidth = getWidth(); vHeight = getHeight(); endX = 0.8f*vWidth; endY = 0.8f*vHeight; } @Override public void surfaceCreated(SurfaceHolder holder) { super.surfaceCreated(holder); init(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.surfaceChanged(holder, format, width, height); init(); } @Override public void doDraw(Canvas canvas){ canvas.drawColor(Color.BLACK); canvas.drawPath(mPath, pPaint); } @Override public boolean processing(){ //这里构建贝塞尔曲线 mPath.reset(); mPath.moveTo(50, 50); mPath.quadTo(random.nextInt(vWidth), random.nextInt(vHeight), endX/2, random.nextInt(vHeight)); mPath.quadTo(random.nextInt(vWidth), random.nextInt(vHeight), endX, endY); return true; } } }
希望大家多多指正。因为本来有好多线程同步的东西,有问题是难免的。