Search code examples
javaandroidsdkonkeydown

trying to create an own method for onKeyDown event (Android)


I have two classes:

MainPanel (where I define some methods) MainThread (where I do a loop with these methods to create a classic game structure)

In the MainPanel class I have this method to capture if a key was pressed

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

It works right, my question is if it's possible to create the onKeyDown as a proper method and use it in the loop to avoid the listener. The idea is to define a method like this in the MainPanel:

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

And then, call it into my loop on MainThread Class like this...

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

At the following line I don't know how to pass the parameter keyCode...

this.MainPanel.MyOwnOnKeyDown(keyCode, event); 

It's possible to that?

Thanks in advance


Solution

  • Looks like you're trying to author a game or some other similar type of program.

    In your main loop, where you're trying to call your own keydown method, you should instead call a method like "handleInput()", and then your implementation of the real Android keydown method should add the event information (keycode, etc.) to a Queue collection. The handleInput() method would then handle all keypresses that have occurred (are in the queue) since the last time around the loop.

    Here's an example main-loop of a game:

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

    The class with this loop also has a queue for holding all events coming in from the player:

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

    The "GameEvent" class has a timestamp memeber (for when the event occurred). Then there are sub-classes such as KeyGameEvent (for keyboard events) and TouchGameEvent (for screen touches), ScrollGameEvent, LongPressGameEvent (subclass of TouchGameEvent) etc.

    Here is an example:

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

    These GameEvent classes then get instantiated and placed on the queue in the standard Android event handler methods, such as this:

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

    Finally, the handleInput() method looks like this:

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

    The, obviously (I hope) within the methods such as processKeyGameEvent() that are called by handeInput(), you actually examine which keys were pressed/released, and have you game logic do whatever is appropriate for such a key press/release.

    If your game is only interested in Keyboard input events (not touch, etc.) then you could forgo creating the GameEvent class hierarchy, and simply place the KeyEvent received by onKeyDown() into the queue.