пытается создать собственный метод для события onKeyDown (Android) - PullRequest
0 голосов
/ 29 января 2011

У меня есть два класса:

MainPanel (где я определяю некоторые методы) MainThread (где я делаю цикл с этими методами для создания классической игровой структуры)

В классе MainPanel Iиметь этот метод для захвата, если клавиша была нажата

 @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); 

Это возможно?

Заранее спасибо

Ответы [ 2 ]

3 голосов
/ 29 января 2011

Похоже, вы пытаетесь создать игру или программу подобного типа.

В вашем основном цикле, где вы пытаетесь вызвать свой собственный метод keydown, вам следует вместо этого вызвать методкак "handleInput ()", и тогда ваша реализация реального метода Android keydown должна добавить информацию о событии (код ключа и т. д.) в коллекцию очередей.Затем метод 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.
    }
  }

Очевидно (я надеюсь) в методах, таких как processKeyGameEvent (), которые вызываются функцией handeInput (), вы фактически проверяете, какие клавиши были нажаты / отпущены, и позволяете ли игровой логике делать то, что подходит для такой клавишинажмите / отпустите.

Если ваша игра заинтересована только событиями ввода с клавиатуры (не касанием и т. д.), то вы можете отказаться от создания иерархии классов GameEvent и просто поместить KeyEvent, полученный onKeyDown (), в очередь.

1 голос
/ 29 января 2011

Я думаю, что вы хотите установить переменную, если ключ активен, и в ссылке на основной цикл это.

Например: в 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); 
}

Возможно, вам понадобится более сложная логика для отслеживания нажатий клавиш, но это отделяет события кнопок от обновлений, чтобы вы могли непрерывно перемещаться.

...