[英]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_press
和on_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.