2011-01-29 58 views
0

一個自己的方法,我有兩個類:試圖創建onKeyDown事件(安卓)

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

這是可能的呢?

在此先感謝

+0

我真的質疑你的設計方法在這裏。我敢打賭,無論你想要解決什麼問題,都有一個更優雅的解決方案。 – user432209 2011-01-29 17:40:32

回答

3

看起來像你正在嘗試編寫遊戲或其他類似的程序。

在你想要調用自己的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放入隊列中。

+0

感謝回覆,我也會試試這個! – karse23 2011-01-29 18:08:55

+0

你能舉個例子嗎? – karse23 2011-01-29 19:21:55

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

您可能需要更復雜的邏輯來跟蹤按鍵,但這會將按鈕事件與更新分離,以便您可以持續移動。