我正在尝试按下按键时移动精灵。我可以使用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速度设置为零。但是,我仍然按下右键,所以我想在按下并释放左后继续移动那些方向。
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])
答案 0 :(得分:2)
来自pyglet guide:
分别按下或释放键盘上的任何键时会触发Window.on_key_press和Window.on_key_release事件。 这些事件不受“密钥重复”的影响 - 一旦按下某个键,该密钥在被释放之前就不会再发生任何事件。
这意味着如果向右按,向左按,向左释放,但不向右释放,则在释放右键并再次按下之前不会发送新的on_key_press事件。
如果你保留了你的结构,我认为你必须检查self.keys
内on_key_release
是否设置了key.RIGHT。但仅此一点是行不通的。使用当前代码,您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的处理程序,这导致在KeyStateHandler的处理程序之前调用MyLayer的处理程序。因此,当您按空格并检查MyLayer.on_key_press
keys[key.SPACE]
是否为True
时,它不是,因为KeyStateHandler尚未设置keys[key.SPACE]
。
要在MyLayer之前调用KeyStateHandler的处理函数,你不应该在MyLayer的构造函数中注册(= push)它们,而是在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
移动你的精灵的动作(继承Move动作将是一个很好的方法) 。获得所需效果的一种方法是不定义自己的on_key_press和on_key_release处理函数,而是依赖KeyStateHandler。您可以像在代码片段中一样按下KeyStateHandler的处理函数,并在计划函数或操作步骤的开头读取keys
dict,按下哪些键,并根据该值更新速度。
例如,打印'太空!'反复使用时间表:
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的self.keys[key.SPACE]
处理程序中将True
设置为on_key_press
,每次按键时只调用一次。释放密钥时,dict条目在KeyStateHandler的False
处理程序中设置为on_key_release
。