[android游戏开发初学]简单的游戏框架
这两天,没事想学习游戏开发,看了一些资料之后准备开始。为了将来编码方便,先写了一个简单的游戏框架方便自己以后做练习用。
如果以后没有什么特殊的需求--比如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游戏开发初学]简单的游戏框架的更多相关文章
- 【读书笔记《Android游戏编程之从零开始》】10.游戏开发基础(View 游戏框架)
对于玩家来说,游戏是动态的:对于游戏开发人员来说,游戏是静态的,只是不停地播放不通的画面,让玩家看到了动态的效果. 进入Android之前,首先要熟悉三个重要的类:View(视图).Canvas(画布 ...
- Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状)
Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状) 本篇博客来给大家介绍怎样使用Lua这门语言来开发一个简单的小游戏-记数字踩白块. 游戏的流程是这种:在界面上生成5个数1~5字并显 ...
- 【HTML5游戏开发】简单的《找不同汉字版》,来考考你的眼力吧
一,准备工作 本次游戏开发需要用到lufylegend.js开源游戏引擎,版本我用的是1.5.2(现在最新的版本是1.6.0). 引擎下载的位置:http://lufylegend.googlecod ...
- Unity 2D游戏开发教程之为游戏场景添加多个地面
Unity 2D游戏开发教程之为游戏场景添加多个地面 为游戏场景添加多个地面 显然,只有一个地面的游戏场景太小了,根本不够精灵四处活动的.那么,本节就来介绍一种简单的方法,可以为游戏场景添加多个地面. ...
- Libgdx游戏开发(2)——接水滴游戏实现
原文:Libgdx游戏开发(2)--接水滴游戏实现 - Stars-One的杂货小窝 本文使用Kotlin语言开发 通过本文的学习可以初步了解以下基础知识的使用: Basic file access ...
- C#游戏开发中快速的游戏循环
C#游戏开发中快速的游戏循环的实现.参考<精通C#游戏编程>一书. using System; using System.Collections.Generic; using System ...
- Unity 2D游戏开发教程之2D游戏的运行效果
Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑问 ...
- 【读书笔记《Android游戏编程之从零开始》】11.游戏开发基础(SurfaceView 游戏框架、View 和 SurfaceView 的区别)
1. SurfaceView 游戏框架实例 实例效果:就是屏幕上的文本跟着点击的地方移动,效果图如下: 步骤: 新建项目“GameSurfaceView”,首先自定义一个类"MySurfac ...
- 《MFC游戏开发》笔记九 游戏中的碰撞判定初步&怪物运动简单AI
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9374935 作者:七十一雾央 新浪微博:http:// ...
随机推荐
- vue.js基础知识篇(4):过滤器、class与style的绑定2
代码下载:网盘 欢迎私信 第一章:过滤器 过滤器是对数据进行处理并返回结果的函数. 1.语法 语法是使用管道符"|"进行连接.过滤器可以接收参数,跟在过滤器后面,带引号的参数被当做 ...
- 欠了好久的CRM帖子,双11来读。
又一年双11了,觉得天猫双11越来越没特色了. 从折扣,音符旋律到红包,今年15年却找不出往年的热度,只是商家还是一样的急,备着活动目标计划,做着库存价格打标视觉设计这种苦逼的日子. 欠了好久的CRM ...
- Retrofit2.0源码解析
欢迎访问我的个人博客 ,原文链接:http://wensibo.net/2017/09/05/retrofit/ ,未经允许不得转载! 今天是九月的第四天了,学校也正式开学,趁着大学最后一年的这大好时 ...
- HTTP手记
---------------------tcp/ip模型和osi模型---------------------tcp/ip协议模型 osi模型应用层 应用层 表示层 会话层传输层 传输层 ...
- keepalive之LVS-DR架构
author:JevonWei 版权声明:原创作品 Keepalive实战之LVS-DR 实验目的:构建LVS-DR架构,为了达到LVS的高可用目的,故在LVS-DR的Director端做Keepal ...
- Docker 集群环境实现的新方式
近几年来,Docker 作为一个开源的应用容器引擎,深受广大开发者的欢迎.随着 Docker 生态圈的不断建设,应用领域越来越广.云计算,大数据,移动技术的快速发展,加之企业业务需求的不断变化,紧随技 ...
- Flask04 后台获取请求数据、视图函数返回类型、前台接受响应数据
1 后台获取请求数据 1.1 提出问题 前台发送请求的方式有哪些 后台如何获取这些请求的参数 1.2 前台发送请求的方式 GET.POST.AJAX 点睛:如果不指定请求方式,浏览器默认使用GET请求 ...
- Serializable序列化的作用
这里转载一篇讲解java序列化(Serializable)和反序列化方面的感觉很好的文章.1.序列化是干什么的?简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的 ...
- java动态代理(JDK和cglib实现对比)
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt214 JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特 ...
- Spring定时任务quartz表达式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp32 0 0 12 * * ?---------------在每天中午12: ...