Ключ опроса с cocos2d-python и 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. Простой пример ниже. Он печатает "Нажатие клавиши!" очень хорошо, но если бы я мог заставить его напечатать "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):
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(). Проблема в том, что если я нажму Right, нажму Left, отпусти Left, мой Sprite будет остановлен, так как 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])
1 ответ
События Window.on_key_press и Window.on_key_release генерируются при нажатии или отпускании любой клавиши на клавиатуре соответственно. На эти события не влияет "повторение клавиши" - после нажатия клавиши для этой клавиши больше нет событий, пока она не будет отпущена.
Это означает, что если вы нажмете вправо, нажмете влево, отпустите влево, но не отпустите вправо, то новые события on_key_press не будут отправлены, пока вы не отпустите правую и не нажмете ее снова.
Если вы сохраняете структуру, которая у вас есть, я думаю, что вы должны проверить, установлен ли key.RIGHT в self.keys
внутри on_key_release
, Но это само по себе не сработает. С текущим кодом вы всегда получите это keys[key.RIGHT]
является False
, Далее я объясню, почему это так.
Когда вы звоните director.window.push_handlers(self.keys)
, вы регистрируете KeyStateHandler собственный on_key_press
а также on_key_release
обработчики в той же очереди вы регистрируете соответствующие обработчики MyLayer. Обработчики KeyStateHandler делают то, что они устанавливают и сбрасывают ключи в keys
диктовать, чтобы вы могли, например, запрос keys[key.SPACE]
чтобы увидеть, удерживается ли клавиша пробела.
Проблема с кодом заключается в том, что вы регистрируете обработчики KeyStateHandler перед обработчиками MyLayer, что вызывает вызов обработчиков MyLayer перед обработчиками KeyStateHandler. Поэтому, когда вы нажимаете пробел и регистрируетесь MyLayer.on_key_press
будь то keys[key.SPACE]
является True
это не так, поскольку KeyStateHandler не установил keys[key.SPACE]
еще.
Чтобы вызывать функции-обработчики KeyStateHandler перед функциями MyLayer, вы не должны регистрировать (=push) их в конструкторе 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
переместить свой спрайт (хороший способ сделать это - наследование от действия Move). Один из способов получить желаемый эффект - не определять свои собственные функции-обработчики on_key_press и on_key_release, а полагаться на KeyStateHandler. Вы нажимаете на функции-обработчики KeyStateHandler как в своем фрагменте кода, так и в начале запланированной функции или шага действия, из которого вы читаете keys
dict, какие клавиши нажимаются, и обновлять скорость на основании этого.
Например, чтобы напечатать "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()
Обратите внимание, что способ работает так: self.keys[key.SPACE]
установлен в True
в KeyStateHandler's on_key_press
обработчик, который вызывается только один раз за нажатие клавиши. Когда вы отпускаете ключ, запись dict устанавливается на False
в KeyStateHandler's on_key_release
обработчик.