推箱子游戏开发(二) 键盘事件监听 角色在屏幕下移动
推箱子游戏开发(二) 键盘事件监听 角色在屏幕上移动先看一下效果图。我们的目标是:通过键盘按键,控制人物在
推箱子游戏开发(二) 键盘事件监听 角色在屏幕上移动
先看一下效果图。
我们的目标是:通过键盘按键,控制人物在屏幕上自由移动。要实现这个目标,只要完成下面三件事就行:1. 监听键盘,获取按键值 2. 根据按键值,修改人物在屏幕上的坐标 3. 在新的坐标位置显示人物
下面是程序的基本框图。
如上图所示:主Activity依次:创建人物、创建键盘监听线程、启动键盘监听线程、显示游戏界面。在游戏界面启动后,游戏界面绘图线程随之启动。绘图线程每隔固定时间对屏幕进行一次刷新。键盘监听线程启动后,会捕获按键值,然后根据按键值来修改人物显示坐标。人物显示坐标改变后,下次绘图线程就可以新的地方把人物画出来。
package com.mapAndSprit;import android.app.Activity;import android.os.Bundle;import android.view.KeyEvent;public class MapAndSpritActivity extends Activity {//游戏界面GameView gameView;//人物MySprite mySprite;//键盘监听线程KeyThread kt;//键盘动作int action = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);gameView = new GameView( this );mySprite = new MySprite( this );kt = new KeyThread( this );kt.start();//显示游戏界面setContentView( gameView );}//按键按下@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){// TODO Auto-generated method stubif(keyCode == 19){//上 action = action | 0x08; } if(keyCode == 20){//下 action = action | 0x04; } if(keyCode == 21){//左 action = action | 0x02; } if(keyCode == 22){//右 action = action | 0x01; }return false;}//按键抬起@Overridepublic boolean onKeyUp(int keyCode, KeyEvent event){// TODO Auto-generated method stubif(keyCode == 19){//上 action = action & 0x37; } if(keyCode == 20){//下 action = action & 0x3B; } if(keyCode == 21){//左 action = action & 0x3D; } if(keyCode == 22){//右 action = action & 0x3E; }return false;}}
package com.mapAndSprit;public class KeyThread extends Thread {MapAndSpritActivity mapAndSpritActivity;boolean flag = true;int sleepSpan = 50;int action;boolean KEY_UP = false;boolean KEY_DOWN = false;boolean KEY_LEFT = false;boolean KEY_RIGHT = false;public KeyThread( MapAndSpritActivity mapAndSpritActivity ){this.mapAndSpritActivity = mapAndSpritActivity;}public void run(){while( flag ){action = mapAndSpritActivity.action;if((action & 0x08) != 0){//上KEY_UP = true;}else{KEY_UP = false;}if((action & 0x04) != 0){//下KEY_DOWN = true;}else{KEY_DOWN = false;}if((action & 0x02) != 0){//左KEY_LEFT = true;}else{KEY_LEFT = false;}if((action & 0x01) != 0){//右KEY_RIGHT = true;}else{KEY_RIGHT = false;} if( KEY_UP ){if( !( mapAndSpritActivity.mySprite.curJ < 1 ) ){mapAndSpritActivity.mySprite.curJ -= 1;}}if( KEY_DOWN ){if( !( mapAndSpritActivity.mySprite.curJ >15 ) ){mapAndSpritActivity.mySprite.curJ += 1;}}if( KEY_LEFT ){if( !( mapAndSpritActivity.mySprite.curI < 1 ) ){mapAndSpritActivity.mySprite.curI -= 1;}}if( KEY_RIGHT ){if( !( mapAndSpritActivity.mySprite.curI > 10 ) ){mapAndSpritActivity.mySprite.curI += 1;}}try{//睡眠sleepSpan毫秒Thread.sleep( sleepSpan );}catch(Exception e){e.printStackTrace();}}}}
package com.mapAndSprit;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;public class MySprite {MapAndSpritActivity mapAndSpritActivity;Bitmap man;//人物在地图显示的位置int curI = 0;int curJ = 0;int curX = 0;int curY = 0;public MySprite( MapAndSpritActivity mapAndSpritActivity ){this.mapAndSpritActivity = mapAndSpritActivity;man = BitmapFactory.decodeResource( mapAndSpritActivity.getResources(), R.drawable.a1 );}public void drawSelf( Canvas c, Paint paint ){//把屏幕分成虚拟的10 * 15的网格,每个格子大小 20 * 20//每次走动一个格子curX = this.mapAndSpritActivity.gameView.initX + curI * 20;curY = this.mapAndSpritActivity.gameView.initX + curJ * 20;c.drawBitmap( man, curX, curY, paint );}}
package com.mapAndSprit;import android.graphics.Canvas;import android.graphics.Color;import android.view.SurfaceHolder;import android.view.SurfaceView;public class GameView extends SurfaceView implements SurfaceHolder.Callback{MapAndSpritActivity mapAndSpritActivity;GameViewDrawThread gameViewDrawThread;SurfaceHolder holder;//人物能在屏幕上显示的最左上角的位置int initX = 20;int initY = 20;public GameView( MapAndSpritActivity mapAndSpritActivity ){super( mapAndSpritActivity );this.mapAndSpritActivity = mapAndSpritActivity;holder = getHolder();holder.addCallback( this );gameViewDrawThread = new GameViewDrawThread( this, holder );}public void onDraw( Canvas c ){c.drawColor( Color.BLUE );mapAndSpritActivity.mySprite.drawSelf( c, null );}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {// TODO Auto-generated method stub}@Overridepublic void surfaceCreated(SurfaceHolder arg0) {// TODO Auto-generated method stubgameViewDrawThread.setFlag( true );gameViewDrawThread.start();}@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {// TODO Auto-generated method stubboolean retry = true;//停止刷帧线程gameViewDrawThread.setFlag(false);//不断地循环,直到等待的线程结束 while (retry) { try { //等待刷帧线程结束 gameViewDrawThread.join(); retry = false; } catch (InterruptedException e) { } }}}
[java] view plaincopyprint?
- package com.mapAndSprit;
- import android.graphics.Canvas; import android.view.SurfaceHolder;
- public class GameViewDrawThreadextends Thread {
- private GameView gameView; private SurfaceHolder holder;
- boolean isRun; int sleepSpan = 200;
- public GameViewDrawThread( GameView gameView, SurfaceHolder holder )
- { this.gameView = gameView;
- this.holder = holder; isRun = true;
- }
- public void setFlag(boolean flag ) {
- isRun = flag; }
- @Override
- public void run() { // TODO Auto-generated method stub
- while( isRun ) {
- Canvas c = null; try
- { c = holder.lockCanvas();
- synchronized( holder ) {
- //调用绘图函数 gameView.onDraw( c );
- } }finally
- { if( c != null )
- { holder.unlockCanvasAndPost( c );
- } }
- try{
- //睡眠200毫秒 Thread.sleep( sleepSpan );
- } catch(Exception e){
- e.printStackTrace(); }
- } }
- }