簡體   English   中英

使用cocos2d-python和pyglet進行鍵輪詢

[英]Key polling with cocos2d-python and pyglet

我正在嘗試在按下鍵的同時移動精靈。 我可以使用on_key_press()和on_key_release()來做到這一點,但是通過這些我遇到了在向左移動的同時向右移動的問題,反之亦然。 我想使用鍵輪詢,並從pyglet文檔中找到了它。

from pyglet.window import key

window = pyglet.window.Window()
keys = key.KeyStateHandler()
window.push_handlers(keys)

# Check if the spacebar is currently pressed:
if keys[key.SPACE]:
    pass    

我似乎無法在cocos2d中實現此功能。 下面是一個簡單的示例。 打印“按鍵!” 很好,但是如果我能打印“太空!” 反復按空格鍵可以解決我的問題。

from cocos.director import director
from cocos.layer import *
from cocos.scene import Scene
from pyglet.window import key
from pyglet.window.key import KeyStateHandler

class MyLayer(Layer):
    is_event_handler = True

    def __init__(self):
        super(MyLayer, self).__init__()
        self.keys = KeyStateHandler()
        director.window.push_handlers(self.keys)

    def on_key_press(self, symbol, modifiers):
        print('Key press!')
        if self.keys[key.SPACE]:
            print('Space!')

def main():
    director.init(resizable=False, width=1024, height=786)
    title_scene = Scene(MyLayer())
    director.run(title_scene)

if __name__ == '__main__':
    main()

為了完整起見,這里是我的on_key_press()和on_key_release()代碼。 問題是,如果我按向右,按向左,釋放左,由於on_key_release()將x速度設置為零,我的Sprite將停止。 但是,我仍要按向右,因此我想在按住並釋放向左后繼續沿該方向移動。

def on_key_press(self, symbol, modifiers):
    if symbol == key.LEFT:
        self.player1.velocity = (-self.player1.speed, self.player1.velocity[1])
    if symbol == key.RIGHT:
        self.player1.velocity = (self.player1.speed, self.player1.velocity[1])

def on_key_release(self, symbol, modifiers):
    if symbol == key.LEFT:
        self.player1.velocity = (0, self.player1.velocity[1])
    if symbol == key.RIGHT:
        self.player1.velocity = (0, self.player1.velocity[1])

來自pyglet指南

當分別按下或釋放鍵盤上的任何鍵時,將觸發Window.on_key_press和Window.on_key_release事件。 這些事件不受“鍵重復”的影響-按下某個鍵后,在釋放該鍵之前不會再有其他事件。

這意味着,如果您按向右,按向左,向左釋放,但不向右釋放,那么在釋放並再次按它之前,將不會調度新的on_key_press事件。

如果保留現有結構,我認為您必須檢查self.keys內部的on_key_release是否設置了on_key_release 但是,僅此一項是行不通的。 使用當前代碼,您將始終獲得keys[key.RIGHT]False 接下來,我將解釋為什么。

調用director.window.push_handlers(self.keys) ,會將KeyStateHandler自己的on_key_presson_key_release處理程序注冊到注冊MyLayer相應處理程序的同一隊列中。 KeyStateHandler的處理程序所做的是,它們在keys dict中設置和取消設置鍵,以便您可以例如查詢keys[key.SPACE]以查看是否按住了空格鍵。

該代碼的問題是,您在MyLayer的處理程序之前注冊了KeyStateHandler的處理程序,這導致MyLayer的處理程序在KeyStateHandler的處理程序之前被調用。 因此,當您按空格keys[key.SPACE]並檢查MyLayer.on_key_press keys[key.SPACE]是否為True ,則不是,因為KeyStateHandler尚未設置keys[key.SPACE]

要在MyLayer的那些函數之前調用KeyStateHandler的處理函數,您不應在MyLayer的構造函數中注冊(=推動)它們,而應在MyLayer的on_enter函數中進行如下注冊:

def on_enter(self):
    super(MyLayer, self).on_enter()
    director.window.push_handlers(self.keys)

如果這樣做,您可能還應該在MyLayer的on_exit函數中刪除/注銷那些處理程序。

如果您對代碼段進行了更改,則應打印“按鍵!”。 和“太空!” 每次您按空格鍵時,但不會重復,因為on_key_press事件仍然每次按鍵僅調度一次。

您可能已經通過CocosNode.schedule安排了一些功能,或者定義了一些使用self.player1.velocity來移動Sprite的Action(繼承自Move動作將是一個很好的方法)。 獲得所需效果的一種方法是不定義自己的on_key_press和on_key_release處理函數,而是依賴KeyStateHandler。 你推KeyStateHandler的處理功能,如在您的代碼段,並在預定的功能或操作步驟開始您讀取keys快譯通,它正在按鍵,並更新基礎上的速度。

例如,要打印“ Space!” 重復使用時間表:

from cocos.director import director
from cocos.layer import *
from cocos.scene import Scene
from pyglet.window import key
from pyglet.window.key import KeyStateHandler

class MyLayer(Layer):

    def __init__(self):
        super(MyLayer, self).__init__()
        self.keys = KeyStateHandler()
        director.window.push_handlers(self.keys)
        self.schedule(self.act_on_input)

    def act_on_input(self, dt):
        if self.keys[key.SPACE]:
            print('Space!')

def main():
    director.init(resizable=False, width=1024, height=786)
    title_scene = Scene(MyLayer())
    director.run(title_scene)

if __name__ == '__main__':
    main()

請注意,此方法的工作方式是在KeyStateHandler的on_key_press處理程序self.keys[key.SPACE]設置為True ,每次按鍵僅調用一次。 釋放鍵時,dict條目在KeyStateHandler的on_key_release處理程序中設置為False

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM