Android游戏开发:Player类中OnTouch事件无法生效问题求助
问题分析与解决方案
首先,你的触摸事件没生效的核心原因很明确:你的Player类虽然实现了View.OnTouchListener,但从来没有任何View把它设置为触摸监听器。触摸事件是由当前显示的GameView(SurfaceView)接收的,而你没有把Player和GameView的触摸事件关联起来,所以Player的onTouch方法永远不会被调用。
快速修复方案
最简单的修复方式是在GameView的构造函数里,把自己的触摸监听器设置为Player实例:
public GameView (Context context){ super(context); simpleTurret = SimpleTurret.getInstance(context); player = Player.getInstance(context); // 添加这一行,把Player设置为GameView的触摸监听器 this.setOnTouchListener(player); thread.start(); }
这样,当用户触摸GameView时,触摸事件就会传递到Player的onTouch方法里,你的移动逻辑就能正常工作了。
游戏开发最佳实践建议
不过从架构设计的角度来说,让Player类直接处理触摸事件并不是最优的做法,原因如下:
Player的核心职责应该是管理角色的状态(位置、生命值、移动逻辑等),而输入处理属于外部交互逻辑,应该和角色逻辑分离。- 如果后续需要添加更多输入方式(比如键盘、手柄),或者多个角色共享输入逻辑,这种耦合的设计会让代码变得难以维护。
更合理的做法是:
- 让
GameView(或者专门的输入管理类)负责接收所有输入事件。 GameView根据输入事件的类型,调用Player提供的状态修改方法(比如startMovingRight()、stopMovingRight())。
修改后的Player类(专注角色逻辑)
public class Player { private static Player instance = null; int x, y; boolean moveRight = false; Bitmap sprite; public Player (Context context){ sprite = BitmapFactory.decodeResource(context.getResources(), R.drawable.test_sprite); x = 300; y = 0; } public void Update(){ if (moveRight){ x += 3; } else { x -= 3; } } public static Player getInstance(Context context) { if (instance == null){ instance = new Player(context); } return instance; } // 对外暴露状态修改方法 public void startMovingRight() { moveRight = true; } public void stopMovingRight() { moveRight = false; } // 补充必要的getter方法 public Bitmap getSprite() { return sprite; } public int getX() { return x; } public int getY() { return y; } }
修改后的GameView类(处理输入并通知Player)
public class GameView extends SurfaceView implements Runnable, View.OnTouchListener { private boolean running = true; SurfaceHolder surfaceHolder = getHolder(); SimpleTurret simpleTurret; Player player; private Thread thread = new Thread(this); public GameView (Context context){ super(context); simpleTurret = SimpleTurret.getInstance(context); player = Player.getInstance(context); // 设置自身为触摸监听器 this.setOnTouchListener(this); thread.start(); } @Override public void run() { while (running){ player.Update(); // 补充调用Player的更新逻辑 DrawCanvas(); Control(); } } public void DrawCanvas(){ Canvas canvas = surfaceHolder.lockCanvas(); if (surfaceHolder.getSurface().isValid()){ canvas.drawColor(Color.RED); canvas.drawBitmap(simpleTurret.getSprite(), simpleTurret.getX(), simpleTurret.getY(), null); canvas.drawBitmap(player.getSprite(), player.getX(), player.getY(), null); surfaceHolder.unlockCanvasAndPost(canvas); } } public void Control(){ try{ thread.sleep(17); } catch(InterruptedException e){ e.printStackTrace(); } } // 实现触摸事件处理,通知Player更新状态 @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.getActionMasked()){ case MotionEvent.ACTION_DOWN: player.startMovingRight(); break; case MotionEvent.ACTION_UP: player.stopMovingRight(); break; } return true; } }
另外注意:原代码的GameView.run()方法里没有调用player.Update(),这会导致Player的位置永远不会更新,即使触摸事件生效了也看不到移动,我在上面的代码里补充了这一点。
内容的提问来源于stack exchange,提问作者Frenchie
相关产品推荐
相关产品推荐

