qle*_*nec 12 haskell sdl frp conways-game-of-life elerea
我正在努力在Haskell开发一个小小的Conway的生命游戏.我写了一个库,生命游戏,它可以管理细胞网格并计算它们的代数(参见github.com/qleguennec/lifegame.git).世代是一个无限的列表.到目前为止,图书馆工作得很好,但缺乏文档.这是一个小型图书馆,它不应该如此难以进入.
现在,我在这里的,我试图用lifegame加上掌舵实际显示世代到屏幕上.这是我写的:
import FRP.Helm
import FRP.Helm.Graphics (Element(..))
import qualified FRP.Helm.Window as Window
import FRP.Helm.Animation (Frame, AnimationStatus(..), animate, absolute)
import FRP.Helm.Time (second, running, delta)
import FRP.Elerea.Simple
import Cell.Display (allGenFrames)
import LifeGame.Data.CellGrid (CellGrid(..), randCellGrid)
render :: Form -> (Int, Int) -> Element
render form (x, y) = collage x y $ [form]
main :: IO ()
main = do
cg <- randCellGrid 50 50
anim <- return . absolute $ allGenFrames cg (1 * second) 10
engine <- startup defaultConfig
run engine $ render <~ (animate anim running status) ~~ Window.dimensions engine
where
config = defaultConfig { windowTitle = "bats"
, windowDimensions = (500, 500)}
status = effectful $ getLine >>= \i -> return $
case i of
"Pause" -> Pause
"Stop" -> Stop
"Cycle" -> Cycle
Run Code Online (Sandbox Code Playgroud)
(来自:github.com/qleguennec/bats.git)
计算的艰苦工作生活在animate running status",第20行.我真的不明白动画的第二个论点是什么.此外,我不确定提供无限的框架列表是合法的.
当我启动代码时,游戏冻结并在5分钟后停止.它似乎消耗所有内存和崩溃.现在,我明白所有这些都缺乏文档.我在做这个工作.但是,作为婴儿Haskeller和婴儿FRP/SDL开发人员,我需要知道我是否采取了错误的方式(我可能会这样做).任何评论被接受和推荐.谢谢.
我不知道我是否可以在 FRP 方面为您提供帮助 - 有这么多的库,而我自己并没有经常使用它 - 但就其价值而言(因为您说您对 Haskell 还很陌生),Conway's Life 可以无需 FRP 即可轻松编写,并且使用 SDL 渲染也很简单。
我发现最好将游戏表示为一组坐标对,而不是一个数组 - 这样,您就不会遇到边界条件或世界包裹问题。(您可以从hashmap和unordered-containers包中获得高效的严格或惰性集合。
CA 逻辑如下所示:
next cs = [i | (i,n) <- M.toList neighbors,
n == 3 || (n == 2 && S.member i cs')]
where
cs' = S.fromList cs
moore (x,y) = tail $ liftM2 (,) [x, x+1, x-1] [y, y+1, y-1]
neighbors = M.fromListWith (+) $ map (,1) $ moore =<< cs
Run Code Online (Sandbox Code Playgroud)
主程序循环如下所示:
run w cs = do
drawCells w cs
e <- pollEvent
case e of
KeyUp (Keysym SDLK_ESCAPE _ _) -> return ()
KeyUp (Keysym SDLK_SPACE _ _) -> pause w cs
_ -> run w $ next cs
drawCells w cs = do
fillRect w (Just $ Rect 0 0 xres yres) (Pixel 0)
c <- createRGBSurface [SWSurface] cellSz cellSz 32 0 0 0 0
mapM_ (draw c . scale) cs
SDL.flip w
where
rect (x,y) = Just $ Rect x y cellSz cellSz
scale = join (***) (* cellSz)
draw c p = do fillRect c Nothing $ Pixel 0xFFFFFF
blitSurface c Nothing w $ rect p
Run Code Online (Sandbox Code Playgroud)
要查看完整的实现,以及 FRP 所能提供的大部分功能(通过鼠标编辑网格)等,请查看此内容。