如何让你的游戏角色相应地移动



我目前正试图在haskell中使用终端中的hscurses创建一个类似蛇的游戏,但在实现游戏的输入功能时遇到了一些问题。我的问题是,每当我按下其中一个移动键,例如"a"时,角色就会向左移动控制台注册的字符数。这导致当我想切换方向时,例如按下"s"向下,角色继续向左移动,向下移动会延迟。

res :: Int -> IO a -> IO (Maybe a)
res n f = concurrently (System.Timeout.timeout n f) (threadDelay n) >>= (result, _) -> return 
result
getInput :: IO Char
getInput = hSetEcho stdin False 
>> hSetBuffering stdin NoBuffering
>> getChar

以及主游戏循环功能中处理输入的部分:

loop :: Window -> State -> Player -> IO State
loop window state player = do
threadDelay 1000000
k <- res 100 getInput
newState <- updateState player state
newPlayer <- movePlayer player k
render newState newPlayer window

和movePlayer功能:

movePlayer :: Player -> Maybe Char -> IO Player
movePlayer Player {xy=xy1, direction = d} k =
case k of
Just 'w' -> return Player {xy = (fst xy1, snd xy1-1), direction = Up}
Just 's' -> return Player {xy = (fst xy1, snd xy1+1), direction = Downie}
Just 'd' -> return Player {xy = (fst xy1+1, snd xy1), direction = Rightie}
Just 'a' -> return Player {xy = (fst xy1-1, snd xy1), direction = Leftie}
Nothing -> return Player {xy = addVecs xy1 (dirToVec d), direction = d}
_ -> return Player {xy = xy1, direction = d}

我不知道问题出在哪里,所以我们很感激任何帮助,或者是否有其他方法可以实现这个输入功能

当前您的输入循环和状态更新循环是绑定在一起的:每次更新最多只能接受一个输入。你将需要取消它们的同步。

低技术的替代方案是将当前具有res 100 getInput的点更改为在循环中实际运行getInput,并且只保留阻塞前接收到的最后一个Char。中等技术的替代方案是有两个线程,一个用于读取输入,另一个用于进行状态更新,共享MVar或类似的线程用于说明最后按下了什么键。高科技的替代方案是使用类似库的砖块来处理所有的输入和输出。

最新更新