Haskell Gloss,在动画功能中从控制台读取不会更新绘图

Posted

技术标签:

【中文标题】Haskell Gloss,在动画功能中从控制台读取不会更新绘图【英文标题】:Haskell Gloss, reading from console within animate function does not update drawing 【发布时间】:2022-01-13 21:19:39 【问题描述】:

我正在使用 haskell 进行 LOGO 的简单实现。

对于图形部分,我使用 Gloss,特别是模块 Graphics.Gloss.Interface.IO.Simulate 中的函数 simulateIO

我用它来制作一个窗口并保存我的程序的状态。问题在于更新,它使用ViewPort -> Float -> model -> IO model 类型的函数,其中模型是状态的类型。我不使用 Viweport 和 Float 参数。我从控制台读取了一行,对其进行解析并评估它以获得我在函数末尾返回的新状态。

显示第一次执行和更新后,不再更新。 当我打印状态时,我可以看到它正在更新,但显示没有。 放置一个常量值而不是获取输入可以解决问题,但这也不是很有用:)。

这是我的代码的简短部分:

runProgram :: Display -> IO ()
runProgram d = simulateIO d white 10 defaultEnv env2Pic step

env2Pic :: Env -> IO Picture
env2Pic e =
   ...
   in return $ pictures piccc

step :: ViewPort -> Float -> Env -> IO Env
step v f e = do
  minput <- getLine
  case minput of
    "" -> step v f e
    _ -> case parserComm minput of
      Nothing -> print "no parse" >> step v f e
      Just cms -> evalPrint e cms

evalPrint 返回IO Env

有没有办法强制重绘?

编辑 看来我的功能运行良好,状态确实正在修改。我认为问题在于函数env2Pic 没有被simulateIO 函数调用,只是在开始时调用了几次。

我还是不明白为什么。

【问题讨论】:

您是否确认evalPrint 确实返回了更新后的Env 是的,我在step 的开头添加了一个print e,并且每次通话都会发生变化 【参考方案1】:

显然 step 函数不应该阻塞,所以你不应该在那个函数中运行像 getLine 这样的阻塞操作。您可以通过在后台线程中运行 getLine 来解决它。这是一个最小的工作示例:

import Control.Concurrent (forkIO)
import Control.Monad (forever)
import Data.IORef (IORef, atomicWriteIORef, newIORef, readIORef)
import Graphics.Gloss (Display (InWindow), Picture (Text), white)
import Graphics.Gloss.Interface.IO.Simulate
  ( ViewPort,
    simulateIO,
  )

runProgram :: IORef String -> Display -> IO ()
runProgram r d = simulateIO d white 10 "" env2Pic (step r)

type Env = String

env2Pic :: Applicative f => Env -> f Picture
env2Pic e = pure (Text e)

step :: IORef String -> ViewPort -> Float -> Env -> IO Env
step r _ _ _ = readIORef r

background :: IORef String -> IO b
background r = forever $ do
  x <- getLine
  atomicWriteIORef r x

main :: IO ()
main = do
  r <- newIORef ""
  forkIO $ background r
  runProgram r (InWindow "test" (500, 500) (100, 100))

【讨论】:

试一试,IORef 会像“管道”一样工作吗?没有输入时它的行为如何?我对 Haskell 中的多线程没有太多经验

以上是关于Haskell Gloss,在动画功能中从控制台读取不会更新绘图的主要内容,如果未能解决你的问题,请参考以下文章

如何在现有的 Haskell 代码中从 String 转到 Data.ByteString.Lazy?

Haskell趣学指南

在jQuery中从下到上动画div而不是从上到下[重复]

读 Learn You a Haskell for Great Good!

如何在 Android 中从 JPEG 创建动画 GIF(开发)

如何在 android 中从 url 播放动画 GIF 图像?