我想在每按一次键时在Haskell Gloss中移动一个对象,而不仅仅是移动开始按一下键的一帧。 (例如:按下“ w”键时,每帧加速对象)
编辑:我尝试使用EventKey的第二个参数,但无济于事。
我的代码:
--TODO - Holding keys doesn't work yet
handleKeys :: Event -> AsteroidsGame -> AsteroidsGame
handleKeys (EventKey (Char char) _ _ _) game
| char == 'w' = move 0 1
| char == 'a' = move (-1) 0
| char == 's' = move 0 (-1)
| char == 'd' = move 1 0
where move x y = game {player = accelerateObject (player game) x y}
handleKeys _ game = game
accelerateObject :: Object -> Float -> Float -> Object
accelerateObject obj hor ver = obj {vel = (vx + hor, vy + ver)}
where (vx, vy) = vel obj
答案 0 :(得分:1)
正确推导出OP后,光泽度将为您提供输入事件(“按键刚刚按下”,“鼠标刚刚移动”),而不是输入状态(“当前按键按下”,“鼠标位于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