我在WPF中編寫了一個Tetris克隆。如果我按住右箭頭鍵,則當前片段向右移動。爲了可玩性,我想讓用戶按下另一個鍵(即F鍵)並旋轉移動件,而不必先鬆開右箭頭鍵。目前,當我這樣做時,這件作品停止轉移。來自鍵盤的多個輸入C#WPF
在此我的第一基本試圖鉤住
Window_PreviewKeyDown(object sender, KeyEventArgs e)
,然後將消息發送到控制器層。
如何構建我的輸入偵聽代碼以允許這樣做?
我當前的代碼Here
我在WPF中編寫了一個Tetris克隆。如果我按住右箭頭鍵,則當前片段向右移動。爲了可玩性,我想讓用戶按下另一個鍵(即F鍵)並旋轉移動件,而不必先鬆開右箭頭鍵。目前,當我這樣做時,這件作品停止轉移。來自鍵盤的多個輸入C#WPF
在此我的第一基本試圖鉤住
Window_PreviewKeyDown(object sender, KeyEventArgs e)
,然後將消息發送到控制器層。
如何構建我的輸入偵聽代碼以允許這樣做?
我當前的代碼Here
應該存在一個KeyUp事件,並且通過使用KeyDown和KeyUp可以達到您要查找的效果。這可以通過幾種方法來完成。
一個是讓你的KeyDown事件啓動一個重複的動作,讓KeyUp取消它。
另一種方法是存儲某些按鍵是否被按住。保存一個鍵列表並在KeyDown和KeyUp上關閉時打開它們。在遊戲主循環中,您將觸發與當前所有按鍵相對應的事件。
一個例子:
bool[] heldDown = new bool[256]; // One index for the keycode of each key
void Window_PreviewKeyDown(object sender, KeyEventArgs e) {
heldDown[e.KeyCode] = true;
}
void Window_PreviewKeyUp(object sender, KeyEventArgs e) {
heldDown[e.KeyCode] = false;
}
然後你通過「heldDown」去你的主迴路和火災事件針對要按住每一個有意義的鍵:
if (heldDown[Key.F])
MainController.TriggerPieceEvent(Constants.PieceEvents.RotateClockwise);
if (heldDown[Key.Left])
MainController.TriggerPieceEvent(Constants.PieceEvents.ShiftLeft);
// etc...
Windows將只重複事件您按下最後一個鍵。另外,鍵重複之前的延遲以及重複的速率取決於通常針對打字而不針對遊戲優化的設置。因此,對於遊戲,最好完全忽略它們,並有自己的方式來實現「重複」鍵。
基本上,您將不得不保持您感興趣的鍵的狀態(按下或釋放),並在您收到KeyDown或KeyUp事件時更改它們。然後,在某種計時器中,您將必須檢查當時每個關閉的鍵的狀態和觸發事件。如果該定時器發生在控制器層或用戶界面中,取決於您的體系結構:-)
您可能會添加額外的檢查,例如當左右鍵同時忽略這兩個鍵時,否則該塊會反覆左右跳動。
所需要的狀態。創建一些像'RightArrowPressed'和'RotateButtonPressed'這樣的變量,在Key_Down中檢查鍵是否被按下,如果是,則將相應的變量設置爲true。
在key_up中,執行相同的操作,但將其設置爲false。
現在你可以在任何時候查看這兩個變量,看看哪個鍵被按下了。
您正在依靠自動重複鍵來保持棋子的移動。這是不恰當的,用戶的鍵盤重複延遲是可變的,並且會影響遊戲的可玩性。正如你發現的那樣,當另一個鍵被按下時,它會停止自動重複。
通過給予每個遊戲對象作爲運動狀態來解決這個問題。使用KeyDown事件來改變它。如果運動狀態值仍與鍵匹配,則KeyUp事件將其重置。在你的遊戲循環中,根據他們的動作狀態更新遊戲對象的位置。你會以固定的速度這樣做,由計時器觸發。
運動狀態還應該表明「跌倒」。您現在可以簡單地讓遊戲變得更加困難,因爲通過降低計時器速度來降低等級。碎片墜落更快。鍵盤變得更加靈敏,讓用戶有機會贏得一個關卡。
C++風格的數組:P – Alex 2010-04-06 16:21:32
哦,對:)一旦C,總是C我想。 – Jakob 2010-04-06 16:43:39