推箱子游戏开发(二) 键盘事件监听 角色在屏幕上移动
2013-01-15 15:32
645 查看
先看一下效果图。
我们的目标是:通过键盘按键,控制人物在屏幕上自由移动。要实现这个目标,只要完成下面三件事就行:1. 监听键盘,获取按键值 2. 根据按键值,修改人物在屏幕上的坐标 3. 在新的坐标位置显示人物
下面是程序的基本框图。
如上图所示:主Activity依次:创建人物、创建键盘监听线程、启动键盘监听线程、显示游戏界面。在游戏界面启动后,游戏界面绘图线程随之启动。绘图线程每隔固定时间对屏幕进行一次刷新。键盘监听线程启动后,会捕获按键值,然后根据按键值来修改人物显示坐标。人物显示坐标改变后,下次绘图线程就可以新的地方把人物画出来。
[java]
view plaincopyprint?
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;
}
}
[java]
view plaincopyprint?
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();
}
}
}
}
[java]
view plaincopyprint?
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 );
}
}
[java]
view plaincopyprint?
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) {
}
}
}
}
[java]
view plaincopyprint?
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();
}
}
}
}
我们的目标是:通过键盘按键,控制人物在屏幕上自由移动。要实现这个目标,只要完成下面三件事就行:1. 监听键盘,获取按键值 2. 根据按键值,修改人物在屏幕上的坐标 3. 在新的坐标位置显示人物
下面是程序的基本框图。
如上图所示:主Activity依次:创建人物、创建键盘监听线程、启动键盘监听线程、显示游戏界面。在游戏界面启动后,游戏界面绘图线程随之启动。绘图线程每隔固定时间对屏幕进行一次刷新。键盘监听线程启动后,会捕获按键值,然后根据按键值来修改人物显示坐标。人物显示坐标改变后,下次绘图线程就可以新的地方把人物画出来。
[java]
view plaincopyprint?
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; 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; } }
[java]
view plaincopyprint?
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; 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(); } } } }
[java]
view plaincopyprint?
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.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 ); } }
[java]
view plaincopyprint?
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.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) { } } } }
[java]
view plaincopyprint?
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();
}
}
}
}
相关文章推荐
- Android应用程序入门 推箱子游戏开发(二) 键盘事件监听 角色在屏幕上移动
- iOS移动开发中监听键盘移动的事件,自动调整view-(1)-UIKeyboardFrameEndUserInfoKey
- 求助帮忙 MFC游戏上人物移动代码 响应键盘多个事件一起发生
- android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动
- SDL游戏开发教程03(消息循环和键盘事件响应)
- Cocos2d-x游戏开发——屏幕触摸事件
- Swift游戏开发之俄罗斯方块:No.9 添加点击和移动事件
- Cocos2d-x游戏开发之2.x后弹出键盘后无法响应除键盘外的触摸事件解决
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(九) 2D游戏角色在地图上的移动
- Android游戏开发教程之十九:屏幕双击事件的捕获
- 【Android游戏开发之四】Android 游戏框架(一个游戏角色在屏幕行走的demo)
- android游戏开发框架libgdx的使用(十三)—TiledMap中的角色和角色移动
- 【Android游戏开发之四】Android 游戏框架(一个游戏角色在屏幕行走的demo)
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(九) 2D游戏角色在地图上的移动
- 从零开始学AS3游戏开发【一】 响应键盘移动的方块
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(九) 2D游戏角色在地图上的移动
- 【Android游戏开发之四】Android 游戏框架(一个游戏角色在屏幕行走的demo)
- Cocos2d-x 3.x游戏开发之旅---<把角色放在屏幕中间>
- 【Android游戏开发之四】Android 游戏框架(一个游戏角色在屏幕行走的demo)
- 【Cocos2d游戏开发之五】多触点与触屏事件详解(单一监听、事件分发)