植物大战僵尸一:多线程修改UI界面,游戏必备API
2015-09-21 23:36
716 查看
本博文适合刚刚学完android基础准备做做项目实战一下的人看,在我的博文中,我会将这个游戏的开发过程讲得非常详细,所以非常容易理解,植物大战僵尸这个游戏我会出一系列的博文详细解释,所以有兴趣的人可以持续跟进哦!
一:制作游戏必备的三个API
(1)SurfaceView:类似于于展示电影的屏幕,这个API是一个非常强大的API,它的内部是一个双缓冲机制,显示界面的效率非常快。那么什么
是双缓冲机制呢?
例如有一个A和一个B两个线程,
A:如果A先加载数据,加载数据完成之后显示界面
B:同时B先显示界面,显示完成时候B再加载数据
这个双缓冲机制的意思就是这两个线程可以同时存在,一个加载数据,另一个显示界面,这样的交叉加载显示会是游戏的运行效率非常快。
SurfaceView有两个主要的功能:
①提供一个可以绘制的surface
②可以在多个线程同时修改界面,如果想要在多个线程中修改界面,就要注意两个前提条件:
1.将所有的surface在主线程中被调用
2..将所有的surfaceHolder.callback在主线程中被调用
(2)surfaceHolder:类似于展示电影的内容,
(3)Thread:类似于工作人员,
二:多线程同时修改界面UI的前提:
(1)实现调用SurfaceView API的两个前提:
第一步就是创建一个GameUI类,用于进行游戏界面的更新,那么要实现在多个线程中同时修改界面,我们必须要保证surface和
surfaceHolder.callback在主线程中被调用,要实现这个前提,我们可以将GameUI 继承surface类,并实现surfaceHolder.callback,然后我们
再在主函数中调用GameUI,然而要想要surfaceHolder.callback生效,我们必须要调用一下surfaceHolder.addcallback方法,所以我们在刚刚
的构造方法中使用getHolder()方法得到一个surfaceHolder对象,然后我们再用这个对象调用。
注意:当软件运行起来,我们的界面是一片黑色,现在我们看日志,当软件运行起来的时候我们的LogCat中打印出了surfaceCreated,
surfaceChanged的日志,当我们点击返回键的时候会调用销毁的那个方法,但是当我们点击Home键的时候,日志中同样会打印销毁的方法,然
后重新进入软件的时候又会重新打印一次创建和改变的方法,这是因为surface对我们的CPU和内存消耗非常大,所以我们的google工程师为了节
约资源,就设置了这样一个机制,每次重新进入的时候都要重新加载。
(2)创建线程的两个条件:
(1)我们必须要保证线程是有效的,怎么保证线程是有效的呢?
就是我们必须保证我们的线程在 surfaceHolder.callback.surfaceCreated()surfaceHolder.callback.surfaceDestroyed()方法之间,意思就是
我们必须保证我们的线程必须在 surfaceHolder.callback.surfaceCreated()之后创建,在surfaceHolder.callback.surfaceDestroyed()之前停止,
就相当于我们的线程作用范围在这两个方法之间,这样才是一个有效的线程,这样才能够去修改界面。
(2)这样我们再去新建一个RenderThread内部类,实现Thread,这样我们就创建了一个新的线程,然后我们在surfaceCreated()方法中新建
一个 RenderThread对象,再开启线程,在surfaceDestroyed中销毁,由于stop方法存在一些安全隐患,所以google工程师已经不在建议我们使用
stop方法去停止线程了,现在我们可以通过一个线程循环来停止线程,通过循环停止线程很简单,我们现在RenderThread的run方法中新建一个while(true),然后在新建一个flag标记,这个标记代表一个线程运行的标记,然后在开启线程的时候将标记变成true,然后在关闭线程的时候直接将
标记变成false就关闭线程了。
GameUI类:
MainActivity类:
这样我们就将开发游戏的前提全部写完了,然后我们运行软件,出现的界面是一片全黑,如图:
然后我们看到LogCat看到有日志打印,到这里准备工作就全部做完了,自己回去试一试吧!!!
一:制作游戏必备的三个API
(1)SurfaceView:类似于于展示电影的屏幕,这个API是一个非常强大的API,它的内部是一个双缓冲机制,显示界面的效率非常快。那么什么
是双缓冲机制呢?
例如有一个A和一个B两个线程,
A:如果A先加载数据,加载数据完成之后显示界面
B:同时B先显示界面,显示完成时候B再加载数据
这个双缓冲机制的意思就是这两个线程可以同时存在,一个加载数据,另一个显示界面,这样的交叉加载显示会是游戏的运行效率非常快。
SurfaceView有两个主要的功能:
①提供一个可以绘制的surface
②可以在多个线程同时修改界面,如果想要在多个线程中修改界面,就要注意两个前提条件:
1.将所有的surface在主线程中被调用
2..将所有的surfaceHolder.callback在主线程中被调用
(2)surfaceHolder:类似于展示电影的内容,
(3)Thread:类似于工作人员,
二:多线程同时修改界面UI的前提:
(1)实现调用SurfaceView API的两个前提:
第一步就是创建一个GameUI类,用于进行游戏界面的更新,那么要实现在多个线程中同时修改界面,我们必须要保证surface和
surfaceHolder.callback在主线程中被调用,要实现这个前提,我们可以将GameUI 继承surface类,并实现surfaceHolder.callback,然后我们
再在主函数中调用GameUI,然而要想要surfaceHolder.callback生效,我们必须要调用一下surfaceHolder.addcallback方法,所以我们在刚刚
的构造方法中使用getHolder()方法得到一个surfaceHolder对象,然后我们再用这个对象调用。
注意:当软件运行起来,我们的界面是一片黑色,现在我们看日志,当软件运行起来的时候我们的LogCat中打印出了surfaceCreated,
surfaceChanged的日志,当我们点击返回键的时候会调用销毁的那个方法,但是当我们点击Home键的时候,日志中同样会打印销毁的方法,然
后重新进入软件的时候又会重新打印一次创建和改变的方法,这是因为surface对我们的CPU和内存消耗非常大,所以我们的google工程师为了节
约资源,就设置了这样一个机制,每次重新进入的时候都要重新加载。
(2)创建线程的两个条件:
(1)我们必须要保证线程是有效的,怎么保证线程是有效的呢?
就是我们必须保证我们的线程在 surfaceHolder.callback.surfaceCreated()surfaceHolder.callback.surfaceDestroyed()方法之间,意思就是
我们必须保证我们的线程必须在 surfaceHolder.callback.surfaceCreated()之后创建,在surfaceHolder.callback.surfaceDestroyed()之前停止,
就相当于我们的线程作用范围在这两个方法之间,这样才是一个有效的线程,这样才能够去修改界面。
(2)这样我们再去新建一个RenderThread内部类,实现Thread,这样我们就创建了一个新的线程,然后我们在surfaceCreated()方法中新建
一个 RenderThread对象,再开启线程,在surfaceDestroyed中销毁,由于stop方法存在一些安全隐患,所以google工程师已经不在建议我们使用
stop方法去停止线程了,现在我们可以通过一个线程循环来停止线程,通过循环停止线程很简单,我们现在RenderThread的run方法中新建一个while(true),然后在新建一个flag标记,这个标记代表一个线程运行的标记,然后在开启线程的时候将标记变成true,然后在关闭线程的时候直接将
标记变成false就关闭线程了。
GameUI类:
package game.qiu.com.game; import android.content.Context; import android.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * 这是游戏的UI类 * 如果想让SurfaceHolder.Callback生效,我们必须要去调用 * SurfaceHolder.addCallback(SurfaceHolder.Callback) * 这样的一个方法,这样就可以保证实现SurfaceHolder.Callback的这 * 三个方法能够生效 */ public class GameUI extends SurfaceView implements SurfaceHolder.Callback{ private RenderThread renderThread; private boolean flag;// 线程运行的一个标记 public GameUI(Context context) { super(context); SurfaceHolder holder = getHolder(); holder.addCallback(this);//保证surfaceCreated,surfaceChanged,surfaceDestroyed能够生效 } private class RenderThread extends Thread{ @Override public void run() { while(flag){ } } } //当surface创建的时候调用 @Override public void surfaceCreated(SurfaceHolder holder) { Log.d("surfaceCreated----->","surface创建的时候调用"); renderThread = new RenderThread(); flag=true; renderThread.start();//开启线程..... } //当surface的大小改变的时候调用,一般的改变是当前显示的界面的改变 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d("surfaceCreated----->","surface大小改变的时候调用"); } //当surface销毁的时候调用 @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d("surfaceCreated----->","surface销毁的时候调用"); //renderThread.stop();//停止线程,因为这个方法有一些安全隐患,所以java工程师 //已经不建议我们通过这个方法去停止线程了,所以我们停止线程都是通过线程的一个循环,让线程自动停止 flag=false;//停止一个线程只要直接将标记定义为false就行了 } }
MainActivity类:
package game.qiu.com.game; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //因为当前的gameUI是继承了surfacevuew,实现了SurfaceHolder.Callback, // 所以我们认为这行代码在 //主线程中调用了surfaceview,同时也是调用了SurfaceHolder.Callback, // 这样就可以在多个线程中同时修改界面 GameUI gameUI = new GameUI(getApplicationContext()); setContentView(gameUI); } }
这样我们就将开发游戏的前提全部写完了,然后我们运行软件,出现的界面是一片全黑,如图:
然后我们看到LogCat看到有日志打印,到这里准备工作就全部做完了,自己回去试一试吧!!!
相关文章推荐
- IOS开发中针对UIImageView的几种常用手势
- UI:数据的解析
- iOS 手势识别与操作 UIGestureRecognizer
- UITabBarController控件解析
- EasyUI系列学习笔记(一)——注册
- Syngress.Nmap.in.the.Enterprise.Your.Guide.to.Network.Scanning
- 修改Map中确定key对应的value问题
- 修改Map中确定key对应的value问题
- java设计模式:创建者模式Builder pattern
- Xcode Build Search Paths设置
- 关于 java.toString() ,(String),String.valueOf的区别
- CF 一个不知道题号的题。。 B. ShortestPath Query
- android界面UI的构造方式
- String,StringBuffer与StringBuilder的区别
- UIProgressView[进度条][一般型];UIStepper步数器][事件驱动型]
- require.js的使用
- 导入NGUI插件
- KVC中setValuesForKeysWithDictionary:
- UIView层次管理(放到最上层或放到最下层)
- UIView转UIImage