目录
6、 设计一个GameLoop类别
7、 只诞生一次GameLoop对象编辑
6、 设计一个GameLoop类别
- 刚才的小线程,其实就扮演了游戏线程(Game thread)的角色,它负责控制游戏的循环。
// myView.java
//……
public class myView extends View {//……….@Override protected void onDraw(Canvas canvas) {//…………..myThread t = new myThread();t.start();}class myThread extends Thread{public void run() {postInvalidateDelayed(1000);}};
}
- 于是,我们将刚才的小线程部分独立出来,成为一个独立的类别,通称为游戏线程(Game Thread) 或游戏循环(Game Loop)。
// GameLoop.java
// ………
public class GameLoop extends Thread {myView mView;GameLoop(myView v){mView = v;}public void run() {mView.onUpdate();mView.postInvalidateDelayed(1000);}
}// myView.java
// ………..
public class myView extends View {private Paint paint= new Paint();private int x, y;private int line_x = 100;private int line_y = 100;private float count = 0;myView(Context ctx) {super(ctx);}public void onUpdate(){if( count > 12) count = 0;x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));count++;}@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.WHITE);paint.setColor(Color.BLUE);paint.setStrokeWidth(3);canvas.drawLine(line_x, line_y, line_x+x, line_y+y, paint);paint.setStrokeWidth(2);paint.setColor(Color.RED);canvas.drawRect(line_x-5, line_y - 5, line_x+5, line_y + 5, paint);paint.setColor(Color.CYAN);canvas.drawRect(line_x-3, line_y - 3, line_x+3, line_y + 3, paint);//--------------------------------GameLoop loop = new GameLoop(this);;loop.start();}
}
- 首先由myActivity来诞生myView对象,然后由Android框架調用myView的onDraw()函数来绘图和显示。绘图完毕,立即诞生一个GameLoop对象,并調用start()函数去启动一个小线程去調用postInvalidate()函数。就触发UI线程重新調用myView的onDraw()函数。
7、 只诞生一次GameLoop对象
- 每次执行onDraw()时,都会重新诞生一次GameThread对象,也诞生一次游戏线程去調用postInvalidate()函数。似乎是UI线程控制着游戏线程,这样游戏线程就不能扮演主控者的角色了。
- 于是,可换一个方式:一开始先诞生一个游戏线程,并且使用while(true)来创造一个无限循环(Endless Loop),让游戏线程持续绕回圈,而不会停止。
- 在诞生myView时,就诞生GameLoop对象,且調用其start()函数来启动游戏线程。此时游戏线程处于<暂停>状态,虽然继续绕回圈,但是并不会調用postInvalidate()函数。接着,由Android框架調用myView的onDraw()函数来绘图和显示。
- 绘图完毕,立即調用GameLoop的loopResume()函数,让GameLoop从<暂停>状态转移到<执行>状态。此时,这游戏线程就去調用postInvalidate()函数,触发UI线程重新調用myView的onDraw()函数。如下图:
// GameLoop.java
// ……..
public class GameLoop extends Thread {private myView mView;private boolean bRunning;GameLoop(myView v){mView = v; bRunning = false; }public void run() {while(true){if(bRunning){mView.onUpdate();mView.postInvalidateDelayed(1000);loopPause();} }}public void loopPause(){ bRunning = false; }public void loopResme(){ bRunning = true; }
}
- 其中, loopPause()函数将bRunning设定为false,游戏线程就处于<暂停>状态。loopResume()函数将bRunning设定为true,游戏线程就处于<执行>状态,就会調用myView的onUpdate()函数,去更新绘图的设定。
- 然后調用postInvalidate()函数,触发UI线程去重新調用onDraw()函数。
// myView.java // ……… public class myView extends View {private Paint paint= new Paint();private int x, y;private int line_x = 100, line_y = 100;private float count;private GameLoop loop;myView(Context ctx) {super(ctx);init();loop = new GameLoop(this);loop.start();}public void init(){count = 0;x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));}public void onUpdate(){ // 游戏线程执行的if( count > 12) count = 0;x = (int) (75.0 * Math.cos(2*Math.PI * count/12.0));y = (int) (75.0 * Math.sin(2*Math.PI * count/12.0));count++;}@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.WHITE);paint.setColor(Color.BLUE);paint.setStrokeWidth(3);canvas.drawLine(line_x, line_y, line_x+x, line_y+y, paint);paint.setStrokeWidth(2);paint.setColor(Color.RED);canvas.drawRect(line_x-5, line_y - 5, line_x+5,line_y + 5, paint);paint.setColor(Color.CYAN);canvas.drawRect(line_x-3, line_y - 3, line_x+3,line_y + 3, paint);//--------------------------------loop.loopResme();} }
• 请留意: onUpdate()函数是由游戏线程所执行的;而onDraw()则是由UI线程所执行的。