这两天,没事想学习游戏开发,看了一些资料之后准备开始。为了将来编码方便,先写了一个简单的游戏框架方便自己以后做练习用。
如果以后没有什么特殊的需求--比如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;
}
}
}

希望大家多多指正。因为本来有好多线程同步的东西,有问题是难免的。

[android游戏开发初学]简单的游戏框架的更多相关文章

  1. 【读书笔记《Android游戏编程之从零开始》】10.游戏开发基础(View 游戏框架)

    对于玩家来说,游戏是动态的:对于游戏开发人员来说,游戏是静态的,只是不停地播放不通的画面,让玩家看到了动态的效果. 进入Android之前,首先要熟悉三个重要的类:View(视图).Canvas(画布 ...

  2. Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状)

    Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状) 本篇博客来给大家介绍怎样使用Lua这门语言来开发一个简单的小游戏-记数字踩白块. 游戏的流程是这种:在界面上生成5个数1~5字并显 ...

  3. 【HTML5游戏开发】简单的《找不同汉字版》,来考考你的眼力吧

    一,准备工作 本次游戏开发需要用到lufylegend.js开源游戏引擎,版本我用的是1.5.2(现在最新的版本是1.6.0). 引擎下载的位置:http://lufylegend.googlecod ...

  4. Unity 2D游戏开发教程之为游戏场景添加多个地面

    Unity 2D游戏开发教程之为游戏场景添加多个地面 为游戏场景添加多个地面 显然,只有一个地面的游戏场景太小了,根本不够精灵四处活动的.那么,本节就来介绍一种简单的方法,可以为游戏场景添加多个地面. ...

  5. Libgdx游戏开发(2)——接水滴游戏实现

    原文:Libgdx游戏开发(2)--接水滴游戏实现 - Stars-One的杂货小窝 本文使用Kotlin语言开发 通过本文的学习可以初步了解以下基础知识的使用: Basic file access ...

  6. C#游戏开发中快速的游戏循环

    C#游戏开发中快速的游戏循环的实现.参考<精通C#游戏编程>一书. using System; using System.Collections.Generic; using System ...

  7. Unity 2D游戏开发教程之2D游戏的运行效果

    Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑问 ...

  8. 【读书笔记《Android游戏编程之从零开始》】11.游戏开发基础(SurfaceView 游戏框架、View 和 SurfaceView 的区别)

    1. SurfaceView 游戏框架实例 实例效果:就是屏幕上的文本跟着点击的地方移动,效果图如下: 步骤: 新建项目“GameSurfaceView”,首先自定义一个类"MySurfac ...

  9. 《MFC游戏开发》笔记九 游戏中的碰撞判定初步&怪物运动简单AI

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9374935 作者:七十一雾央 新浪微博:http:// ...

随机推荐

  1. LAMP环境的搭建(四)----Apache下部署项目

    根据前文完成了LAMP基本环境的安装,那么接下来就是部署线上的环境了. yum 安装的apache 目录存在于  /etc/httpd apache最重要的文件就是 httpd.conf.  目录再 ...

  2. Gitlab-CI持续集成之Runner配置和CI脚本

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...

  3. Android事件传递机制详解及最新源码分析——Activity篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在前两篇我们共同探讨了事件传递机制<View篇>与<ViewGroup篇>,我们知道View触摸事件是ViewGroup传递 ...

  4. github+hexo搭建自己的博客网站(七)注意事项(避免read.me,CNAME文件的覆盖,手动改github page的域名)

    详细的可以查看hexo博客的演示:https://saucxs.github.io/ 绑定域名可以查看:http://www.chengxinsong.cn 可以查看在github上生成的静态文件(如 ...

  5. HTML中document.getElementById()方法的操作

    转自:http://blog.csdn.net/pyffcwj/article/details/7240232/ obj = document.getElementById("cc" ...

  6. 简单理解java中timer的schedule和scheduleAtFixedRate方法的区别

    timer的schedule和scheduleAtFixedRate方法一般情况下是没什么区别的,只在某个情况出现时会有区别--当前任务没有来得及完成下次任务又交到手上. 我们来举个例子: 暑假到了老 ...

  7. Jquery 绑定标签事件

    为子元素绑定: $('#foreachResult').delegate('td', 'click', function () {            alert($(this).text());  ...

  8. Java线程调度—休眠

    线程休眠的方法是Thread.sleep(long millis) 和Thread.sleep(long millis, int nanos) ,均为静态方法,那调用sleep休眠的哪个线程呢?简单说 ...

  9. C# xml增删查改

    C# XML XmlDocument 添加命名空间: using System.Xml; 定义公共对象: XmlDocument xmldoc ; XmlNode xmlnode ; XmlEleme ...

  10. linux模拟实现主机跨路由通信

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...