При правильном выводе OP, глянец отображает события ввода («клавиша только что нажата», «мышь только что перемещена»), а не состояние ввода («клавиша в данный момент нажата», «мышь находится в точке х, у»),Кажется, не существует встроенного способа просмотра состояния ввода в каждом кадре, поэтому нам придется сделать наш обходной путь.К счастью, это не так уж сложно!
Для простого рабочего примера мы сделаем невероятно забавную «игру», в которой вы можете наблюдать за счетчиком вверх, пока нажата клавиша пробела.Клепка.Этот подход обобщает обработку любых нажатий клавиш, поэтому его будет легко распространить на ваш случай.
Первое, что нам нужно, это состояние нашей игры:
import qualified Data.Set as S
data World = World
{ keys :: S.Set Key
, counter :: Int }
Мы отслеживаемнаше конкретное состояние игры (в данном случае просто счетчик), а также состояние нашего обходного пути (набор нажатых клавиш).
Обработка событий ввода просто включает либо добавление ключа к нашему набору нажатых в данный момент клавишили удаляя его:
handleInput :: Event -> World -> World
handleInput (EventKey k Down _ _) world = world { keys = S.insert k (keys world)}
handleInput (EventKey k Up _ _) world = world { keys = S.delete k (keys world)}
handleInput _ world = world -- Ignore non-keypresses for simplicity
Это можно легко расширить, например, для обработки.движение мыши, изменив наш тип World
, чтобы отслеживать последние известные координаты курсора, и установив его в этой функции всякий раз, когда мы видим событие EventMotion
.
Наш мир от кадра к кадруЗатем функция обновления использует состояние ввода для обновления определенного игрового состояния:
update :: Float -> World -> World
update _ world
| S.member (SpecialKey KeySpace) (keys world) = world { counter = 1 + counter world }
| otherwise = world { counter = 0 }
Если в данный момент нажата пробел (S.member (SpecialKey KeySpace) (keys world)
), увеличить счетчик - в противном случае сбросить его на 0. Мы не делаемзаботьтесь о том, сколько времени прошло между кадрами, поэтому мы игнорируем аргумент float.
Наконец, мы можем отрендерить нашу игру и сыграть в нее:
render :: World -> Picture
render = color white . text . show . counter
main :: IO ()
main = play display black 30 initWorld render handleInput update
where
display = InWindow "test" (800, 600) (0, 0)
initWorld = World S.empty 0