0

我有两节课:

MainPanel(我定义了一些方法) MainThread(我用这些方法循环来创建一个经典的游戏结构)

在 MainPanel 类中,我有这个方法来捕获是否按下了一个键

 @Override 
 public boolean onKeyDown(int keyCode, KeyEvent event) { 
         switch(keyCode) { 
                 case KeyEvent.KEYCODE_DPAD_UP: 
                         Log.i(TAG,"key up was pressed"); 
                         return true; 
         } 
         return false; 
}

它工作正常,我的问题是是否可以将 onKeyDown 创建为正确的方法并在循环中使用它来避免监听器。这个想法是在 MainPanel 中定义一个这样的方法:

public void myOwnOnKeyDown(int keyCode, KeyEvent event) { 
     switch(keyCode) { 
             case KeyEvent.KEYCODE_DPAD_UP: 
                     Log.i(TAG,"key up was pressed");
     }
}

然后,像这样将它调用到我在 MainThread 类上的循环中......

public class MainThread extends Thread {
//...

public void loop() { 
    Canvas canvas; 
    KeyEvent event; Log.d(TAG, "Starting game loop");

    while (running) {

        this.MainPanel.MyOwnOnKeyDown(keyCode, event); 
        this.MainPanel.moveElements(); 
        this.MailPanel.drawElements(canvas); 
    } 
}

在以下行中,我不知道如何传递参数 keyCode ...

this.MainPanel.MyOwnOnKeyDown(keyCode, event); 

有可能吗?

提前致谢

4

2 回答 2

3

看起来您正在尝试创作游戏或其他类似类型的程序。

在您尝试调用自己的 keydown 方法的主循环中,您应该调用类似“handleInput()”的方法,然后您的真正 Android keydown 方法的实现应该添加事件信息(keycode 等)。 ) 到队列集合。然后,handleInput() 方法将处理自上次循环以来发生的所有按键(在队列中)。

这是一个游戏的主循环示例:

  public void run() {

    initializeState();

    while (stillRunning) { // stillRunning is a flag that signals the user wants to exit

      while(isPaused() && stillRunning) { // isPaused is a flag that is set in the if the user selects pause
        try {
          sleep(100);
        } catch (InterruptedException e) {
        }
      }
      if(!stillRunning)
        break;

      Canvas c = null;
      try {
        c = surfaceHolder.lockCanvas(null); // the game uses a Surface view for drawing
        synchronized (surfaceHolder) {
          updateState();  // update game entities - such as remove explosions that are finished, etc.
          handleInput(); // handle user input (key presses, screen touches, etc.)
          updatePhysics(); // collision detection, speed changes due to gravity, etc.
          updateAnimations(); // update which frames need to draw for animating entities
          updateSound(); // start/stop any sounds required by new game state/events
          updateVideo(c); // draw the next frame of video
        }
      } finally {
        // do this in a finally so that if an exception is thrown
        // during the above, we don't leave the Surface in an
        // inconsistent state
        if (c != null) {
          surfaceHolder.unlockCanvasAndPost(c);
        }
      }
    }
  }

具有此循环的类还有一个队列,用于保存来自播放器的所有事件:

private ConcurrentLinkedQueue<GameEvent> eventQueue = new ConcurrentLinkedQueue<GameEvent>();

“GameEvent”类有一个时间戳成员(事件发生的时间)。然后是KeyGameEvent(用于键盘事件)和TouchGameEvent(用于屏幕触摸)、ScrollGameEvent、LongPressGameEvent(TouchGameEvent的子类)等子类。

这是一个例子:

public class KeyGameEvent extends GameEvent {

  public int keyCode;
  public KeyEvent keyEvt;
  public boolean up;

  public KeyGameEvent(int keyCode, boolean keyUp, KeyEvent evt) {
    this.keyCode = keyCode;
    this.up = keyUp;
    this.keyEvt = evt;
  }

}

然后这些 GameEvent 类被实例化并放置在标准 Android 事件处理程序方法中的队列中,例如:

  public boolean onKeyDown(int keyCode, KeyEvent event) {
    KeyGameEvent kge = new KeyGameEvent(keyCode, false, evt);
    eventQueue.add(kge);
    return true;
  }

  public boolean onKeyUp(int keyCode, KeyEvent event) {
    KeyGameEvent kge = new KeyGameEvent(keyCode, true, evt);
    eventQueue.add(kge);
    return true;
  }

  public void onLongPress(MotionEvent evt) {
    LongPressGestureGameEvent lpe = new LongPressGestureGameEvent(evt);
    eventQueue.add(lpe);
  }

最后,handleInput() 方法如下所示:

  private void handleInput() {

    while(true) {
      GameEvent evt = eventQueue.poll();
      if(evt == null)
        break;

      if(evt instanceof KeyGameEvent) {
        processKeyGameEvent((KeyGameEvent)evt);
      }
      else if(evt instanceof TouchGameEvent) {
        processTouchGameEvent((TouchGameEvent)evt);
      }
      // ... etc. for the different types of events.
    }
  }

显然(我希望)在由 handeInput() 调用的 processKeyGameEvent() 等方法中,您实际上检查了哪些键被按下/释放,并让您的游戏逻辑执行任何适合此类键按下/释放的操作。

如果您的游戏只对键盘输入事件(而不是触摸等)感兴趣,那么您可以放弃创建 GameEvent 类层次结构,而只需将 onKeyDown() 接收到的 KeyEvent 放入队列中。

于 2011-01-29T17:58:27.010 回答
1

我认为你想要做的是为一个键是否处于活动状态并在你的主循环中引用它设置一个变量。

例如:在 MainPanel 中有一些类字段,例如:

// some constants
static int NONE = 0;
static int UP = 1;
static int DOWN = 2;
static int LEFT = 3;
static int RIGHT = 4;
// state fields
private volatile int movement = NONE;
private volatile boolean jumping = false;

然后您的 onKeyDown 将类似于:

@Override 
 public boolean onKeyDown(int keyCode, KeyEvent event) { 
         switch(keyCode) { 
                 case KeyEvent.KEYCODE_DPAD_UP: 
                         Log.i(TAG,"key up was pressed");
                         movement = UP;
                         return true; 
         } 
         return false; 
}

和 onKeyUp 看起来类似于:

@Override 
 public boolean onKeyDown(int keyCode, KeyEvent event) { 
         switch(keyCode) { 
                 case KeyEvent.KEYCODE_DPAD_UP: 
                         Log.i(TAG,"key up was pressed");
                         movement = NONE;
                         return true; 
         } 
         return false; 
}

你的主循环看起来像:

while (running) {
    if (this.movement == UP) {
         // update stuff
    } else if (this.movement == DOWN) {
         // update other stuff
    } // etc ...
    this.MainPanel.moveElements(); 
    this.MailPanel.drawElements(canvas); 
}

您可能需要更复杂的逻辑来跟踪按键,但这会将按钮事件与更新分开,以便您可以连续移动。

于 2011-01-29T18:01:47.247 回答