推箱子游戏开发(二) 键盘事件监听 角色在屏幕下移动
推箱子游戏开发(二) 键盘事件监听 角色在屏幕上移动
先看一下效果图。
先看一下效果图。
我们的目标是:通过键盘按键,控制人物在屏幕上自由移动。要实现这个目标,只要完成下面三件事就行: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;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- gameView = new GameView( this );
- mySprite = new MySprite( this );
- kt = new KeyThread( this );
- kt.start();
- //显示游戏界面
- setContentView( gameView );
- }
- //按键按下
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event)
- {
- // TODO Auto-generated method stub
- if(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;
- }
- //按键抬起
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event)
- {
- // TODO Auto-generated method stub
- if(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 );
- }
- @Override
- public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
- // TODO Auto-generated method stub
- }
- @Override
- public void surfaceCreated(SurfaceHolder arg0) {
- // TODO Auto-generated method stub
- gameViewDrawThread.setFlag( true );
- gameViewDrawThread.start();
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder arg0) {
- // TODO Auto-generated method stub
- boolean retry = true;
- //停止刷帧线程
- gameViewDrawThread.setFlag(false);
- //不断地循环,直到等待的线程结束
- while (retry) {
- try {
- //等待刷帧线程结束
- gameViewDrawThread.join();
- retry = false;
- }
- catch (InterruptedException e) {
- }
- }
- }
- }
- package com.mapAndSprit;
- import android.graphics.Canvas;
- import android.view.SurfaceHolder;
- public class GameViewDrawThread extends 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();
- }
- }
- }
- }