Domanda

Ho due classi:

MainPanel (dove io definisco alcuni metodi) MainThread (dove faccio un ciclo con questi metodi per creare una struttura di gioco classica)

Nella classe MainPanel ho questo metodo per la cattura se un tasto è stato premuto

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

Funziona bene, la mia domanda è se è possibile creare l'onKeyDown come un metodo corretto e utilizzarlo nel ciclo per evitare l'ascoltatore. L'idea è di definire un metodo come questo nel MainPanel:

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

E poi, lo chiamano nel mio ciclo sulla MainThread classe come questo ...

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

Al seguente riga non so come passare il parametro keyCode ...

this.MainPanel.MyOwnOnKeyDown(keyCode, event); 

E 'possibile questo?

Grazie in anticipo

È stato utile?

Soluzione

sembra che si sta cercando di autore di un gioco o qualche altro tipo simile di programma.

Nel vostro ciclo principale, in cui si sta cercando di chiamare il proprio metodo di keydown, si dovrebbe invece chiamare un metodo come "handleInput ()", e quindi l'implementazione del vero metodo di keydown Android dovrebbe aggiungere le informazioni sugli eventi (keycode , ecc) per una collezione coda. Il metodo handleInput () sarebbe quindi gestire tutti i tasti premuti che si sono verificati (sono in coda) dopo l'ultima volta intorno al ciclo.

Ecco un esempio principale anello di un gioco:

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

La classe con questo ciclo ha anche una coda per lo svolgimento di tutti gli eventi provenienti dal giocatore:

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

La classe "GameEvent" ha un memeber timestamp (per cui si è verificato l'evento). Poi vi sono sottoclassi come KeyGameEvent (per eventi di tastiera) e TouchGameEvent (per tocchi schermo), ScrollGameEvent, LongPressGameEvent (sottoclasse di TouchGameEvent) ecc

Ecco un esempio:

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;
  }

}

Queste classi GameEvent quindi ottenere un'istanza e immessi sul coda nei metodi del gestore di eventi standard di Android, come questa:

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

Infine, il handleInput () metodo assomiglia a questo:

  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.
    }
  }

Il, ovviamente (spero) nei metodi come processKeyGameEvent () che vengono chiamati da handeInput (), si esamina in realtà che sono stati premuti / rilasciati i tasti, e hai logica di gioco fai tutto ciò che è appropriato per una pressa tale chiave / release.

Se il gioco è interessato solo a eventi di input della tastiera (non toccare, ecc) allora si potrebbe rinunciare creazione della gerarchia delle classi GameEvent, ed è sufficiente posizionare il KeyEvent ricevuto dal onKeyDown () nella coda.

Altri suggerimenti

Credo che ciò che si vuole fare è impostare una variabile per se una chiave è attivo e in riferimento ciclo principale che.

es: Negli MainPanel avere alcuni settori come ad esempio:

// 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;

Allora il vostro onKeyDown sarebbe simile a:

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

e onKeyUp sarebbe simile a:

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

e il vostro aspetto ciclo principale qualcosa del tipo:

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

probabilmente avrete bisogno di una logica più sofisticata per il monitoraggio delle pressioni dei tasti, ma questo pulsante si separa gli eventi di aggiornamenti in modo da poter avere un movimento continuo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top