基于Android平台的星际射击游戏的设计与实现(5)
资料介绍:
/>
</LinearLayout>
</RelativeLayout>
在Activity中通过函数setContentView(R.layout.welcome)应用该布局文件。本界面包括一背景图片,和两个控制按钮,效果图如图5-1。
图5-1 菜单选择界面
5.1.2 设置界面的设计与实现
本界面主要用到Android内部提供的对话框控件,对话框采用自定义对话框,布局文件dialog.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent">
<TextView
Android:text="背景音乐"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"/>
<RadioGroup
Android:id="@+id/rg1"
[资料来源:http://doc163.com]
Android:orientation="horizontal"
Android:layout_height="wrap_content"
Android:layout_width="wrap_content">
<RadioButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:id="@+id/rb1"
Android:text="开"
Android:checked="true"/>
<RadioButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:id="@+id/rb2"
Android:text="关"/>
</RadioGroup>
<TextView
Android:text="音效"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"/>
<RadioGroup
Android:id="@+id/rg2" [资料来源:Doc163.com]
Android:orientation="horizontal"
Android:layout_height="wrap_content"
Android:layout_width="wrap_content">
<RadioButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:id="@+id/rb3"
Android:text="开"
Android:checked="true"/>
<RadioButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:id="@+id/rb4"
Android:text="关"/>
</RadioGroup>
</LinearLayout>
通过Builder类中setView(int)方法应用dialog.xml布局。具体效果图如图5-2。
图5-2 设置界面
5.1.3 游戏主界面
游戏主界面是通过自定义View实现,而不是通过xml文件设计,自定义MyView通过继承SurfaceView,并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口: [资料来源:Doc163.com]
(1) surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不能在这个函数中绘制Surface。
(2) surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。
(3) surfaceDestroyed(SurfaceHolder holder):当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface,一般在该函数中来清理使用的资源。通过SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas(Rect dirty)函数来获取Canvas对象,通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或者尚未创建调用该函数会返回null,在unlockCanvas()和lockCanvas()中Surface的内容是不缓存的,所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分则可以调用lockCanvas(Rect dirty)函数来指定一个dirty区域,这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中不会被改变(被摧毁、修改)。
[版权所有:http://DOC163.com]
Canvas中绘制完成后,调用函数unlockCanvasAndPost(Canvas canvas)来通知系统Surface已经绘制完成,这样系统会把绘制完的内容显示出来。为了充分利用不同平台的资源,发挥平台的最优效果可以通过SurfaceHolder的setType函数来设置绘制的类型,目前接收如下的参数:
SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface。
SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access)引擎和硬件加速的Surface。
SURFACE_TYPE_GPU:适用于GPU加速的Surface。
SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,由Camera负责提供给预览Surface数据,这样图像预览会比较流畅;如果设置这种类型则就不能调用lockCanvas来获取Canvas对象。