2013-04-22 43 views
1

所以我正在努力開發一個平臺風格的遊戲,用C編寫,並使用GTK作爲我的圖形工具包。現在我有一個程序,在屏幕上放置三個塊。其中兩個是平臺,第三個可以通過按左/右箭頭鍵橫向移動。 (我還沒有畫出任何精靈,所以現在我的遊戲中的英雄是一個藍色的矩形)。我也通過按'z'鍵實現了跳躍,並且您可以跳躍並登陸平臺。GDK/GTK可以同時按下兩個按鍵嗎?

然而,橫向移動而跳躍是相當困難的。我相信這是因爲我的程序無法識別兩個按鍵同時按下,因此您必須釋放左側或右側箭頭,按z,然後釋放z並再次按右側或左側箭頭以在空中橫向移動。我想能夠左手或右手並同時按z鍵讓英雄橫向跳躍。

GDK reference manual將GDK密鑰代碼列表中的'gdk/gdkkeysyms.h'(在我的系統上位於/usr/include/gtk-3.0/gdk/gdkkeysyms.h)中,但不包含給出有關同時使用兩個鍵的任何指導。 GTK/GDK能認出其中兩個鍵同時按下事件(GDK,GTK爲準,我得到其中兩個之間的界限是模糊的,但我想這是一個話題另一個問題)?你會如何運用它? (對於單個密鑰,您可以通過執行類似

key = event->keyval; 

但我真的不知道這對於兩個密鑰會是什麼樣子)。

感謝您的幫助!

回答

1

有兩種情況,以做到心中有數。

一些特殊的鍵被稱爲修改鍵和這些導致修改位在event->state進行設置,以便您可以檢查if (event->state & GDK_CONTROL_MASK)例如。

只有少數幾個常見的修飾根據這樣設置的標誌。對於其他按鍵,您需要自己跟蹤單獨的按下和釋放事件,這將允許您確定在另一個按鍵到達時是否仍然按下一個按鍵。小部件信號是按鍵事件和按鍵釋放事件。

有可能是造成你麻煩等因素的影響,一個好的方法是創建一個小單文件獨立編譯的測試案例顯示問題。你可以通過製作測試用例來解決問題,但如果不能,測試用例將幫助其他人幫助你。 (因爲他們可以用它來重現問題)

+0

感謝。我會嘗試設置一個測試用例,看看能否識別出兩個按鍵。這聽起來像你說的是,如果一個按鍵被按住,然後按下另一個按鍵,則會爲第二按鍵生成另一個按鍵事件信號,我認爲這是真的,但我沒有真正想過。所以,也許我可以嘗試通過使用單獨的變量跟蹤每個鍵的按下/釋放狀態來使其工作。在我剛喂入程序之前,使用一個名爲'key'的變量按下每個按鍵事件的下一個按鍵。所以也許我需要'keyleft','keyright'和'keyz'變量... – user2281387 2013-04-22 05:22:17

+0

更新:是的,就是這樣。我創建了變量來分別跟蹤每個鍵,現在它工作得很好。謝謝! – user2281387 2013-04-22 06:00:06

2

鍵盤不工作的方式:每個鍵生成一個獨立的中斷,這將產生一個獨立的窗口系統事件,所以你必須對自己保持狀態。

有些鍵實際上是特殊的,並且充當其他鍵的修飾符:Control,Shift,Alt,是修飾符,因此被區別對待 - 即如果按下它們,它們的狀態將分別記錄到事件數據結構中從被按下的實際按鍵開始。不過,它們也會產生單獨的關鍵事件。

你可以簡單地保持一個按鍵的記錄,並檢查以後,如果保持該狀態,例如:

static gboolean is_a_pressed = FALSE; 
static gboolean is_b_pressed = FALSE; 

static gboolean on_key_press (GtkWidget *w, GdkEvent *e) 
{ 
    /* acquire key A */ 
    if (e->key.symbol == GDK_KEY_a) 
    is_a_pressed = TRUE; 

    /* acquire key B */ 
    if (e->key.symbol == GDK_KEY_b) 
    is_b_pressed = TRUE; 

    /* both keys have been pressed */ 
    if (is_a_pressed && is_b_pressed) 
    do_something_amazing(); 

    /* let the event propagate further */ 
    return GDK_EVENT_PROPAGATE; 
} 

static gboolean on_key_release (GtkWidget *w, GdkEvent *e) 
{ 
    /* release key A */ 
    if (e->key.symbol == GDK_KEY_a) 
    is_a_pressed = FALSE; 

    /* release key B */ 
    if (e->key.symbol == GDK_KEY_b) 
    is_b_pressed = FALSE; 

    return GDK_EVENT_PROPAGATE; 
} 
相關問題