正如 OP 正确推断的那样,gloss 为您提供输入事件(“刚刚按下键”,“刚刚移动鼠标”),而不是输入状态(“当前按下键”,“鼠标位于 x,y”)。似乎没有内置的方式来查看每一帧的输入状态,所以我们必须自己解决。谢天谢地,这并不难!
对于一个简单的工作示例,我们将制作一个非常有趣的“游戏”,您可以在按下空格键时观看计数器向上计数。铆。这种方法适用于处理任何按键,因此很容易扩展到您的案例。
我们需要的第一件事是我们的游戏状态:
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