游戏中有些时候需要固定一个时间去刷新画布,例如背景动态的浮云、流水等等,这些元素不会与玩家交互,但它却是动态的。因此游戏中会有一个线程在不停地重绘画布,实时更新游戏背景动态元素的状态。除此之外,游戏中还有其他的逻辑需要不断更新,例如游戏中钱币的更新等等。
public class MySurfaceView extends SurfaceView implementsCallback, Runnable {
...
// 声明一个线程对象
private Thread thread;
// 线程标示符
private boolean threadFlag;
public MySurfaceView(Contextcontext) {
super(context);
// 实例holder
holder = this.getHolder();
// 为SurfaceView添加状态监听
holder.addCallback(this);
// 实例画笔
paint = new Paint();
// 设置画笔颜色为白色
paint.setColor(Color.WHITE);
// 设置焦点
setFocusable(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 初始化屏幕尺寸
SCREEN_W = this.getWidth();
SCREEN_H = this.getHeight();
// 在SurfaceView创建时修改线程标识符为真,表名线程启动
threadFlag = true;
myDraw();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
threadFlag = false;
}
/**
* 自定义绘图函数
*/
public void myDraw() {
...
}
@Override
public boolean onTouchEvent(MotionEvent event) {
textX = (int)event.getX();
textY = (int)event.getY();
myDraw();
return true;
}
/**
* 功能:封装游戏逻辑
*/
public void logic() {
;
}
@Override
public void run() {
while (threadFlag) {
longstartTime = System.currentTimeMillis();
myDraw();
logic();
long endTime= System.currentTimeMillis();
/*
* 1000ms /60 = 16.67ms 这里,我们采用15,使帧率限制在最大66.7帧
*/
if (endTime -startTime < 15) {
try{
Thread.sleep(15- (endTime - startTime));
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
本类中,有以下注意的地方:
1.线程标示符
在代码中“boolean flag;”语句声明一个布尔值,主要用途有:(1)防止重复创建线程。(2)便于销毁线程。
android手机上都有Home键和Back键,当用户按下这个按键,手机无论执行什么程序,都会返回桌面。从而导致SurfaceView状态的改变。Home和Back的区别在于,在用户按下Back键后再重新进入程序,SurfaceView的生命周期调用如下:surfaceDestroyed→ 构造方法 → surfaceCreated → surfaceChanged。在用户按下Home键后再重新进入程序,surfaceView的生命周期调用是这样的:surfaceDestroyed→ surfaceCreated → surfaceChanged。
由以上区别可知,当每次按下Back后再返回程序时,SurfaceView都会被重新加载。
因为这个原因,我们为了避免线程重复创建而出现线程状态异常。最完美的做法就是,线程的初始化和线程的启动都放在视图创建的surfaceCreated中来完成,并且在surfaceDestroyed 中将线程标示符设置为false。这样既可以避免线程已启动异常,同样也可避免线程无线创建的问题。
2.控制帧频
由于不同手机不同的性能,处理逻辑和绘图的时间不同,为了尽量使游戏的用户体验一直,我们就要控制帧频,以避免设备性能好游戏就能运行飞快的问题。性能较差的设备,能够做到不丢帧的运行即可。当设备处理完绘图和逻辑之后,如果处理所用时间小于一帧的时间,那么就让它休眠够剩下的时间。