0

私は2つのクラスを持っています:

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

ゲームまたは他の同様の種類のプログラムを作成しようとしているようです。

独自のキーダウン メソッドを呼び出そうとしているメイン ループでは、代わりに「handleInput()」などのメソッドを呼び出す必要があります。次に、実際の Android キーダウン メソッドの実装でイベント情報 (キーコードなど) を追加する必要があります。 ) キュー コレクションに。次に、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 に答える