尝试为 onKeyDown 事件创建自己的方法(Android)

发布于 2024-10-14 22:03:49 字数 1256 浏览 5 评论 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); 

可以那?

提前致谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

第七度阳光i 2024-10-21 22:03:49

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

在你的主循环中,当你尝试调用你自己的 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.
    }
  }

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

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

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.

彼岸花似海 2024-10-21 22:03:49

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

例如:在 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); 
}

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

I think what you want to do is set a variable for if a key is active and in your main loop reference that.

eg: In the MainPanel have some class fields such as:

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

Then your onKeyDown would look similar to:

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

and onKeyUp would look similar to:

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

and your main loop looks something like:

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

You'll probably need more sophisticated logic for tracking key presses but this separates button events from updates so you can have continuous movement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文