我将使用 netwire 和 OpenGL 在 Haskell 中编写一个实时游戏。基本思想是每个对象都由一根线表示,它会获取一些数据作为输入并输出其状态,然后我会将它们全部连接到一根大线中,以获取 GUI 的状态作为输入并输出世界状态,然后我可以将其传递给渲染器以及一些“全局”逻辑,如碰撞检测。
我不确定的一件事是:我想如何输入电线?并非所有实体都有相同的输入;玩家是唯一可以访问键输入状态的实体,寻找导弹需要目标的位置等。
我应该怎么办?
最佳答案
抑制幺半群e
是抑制异常的类型。这不是电线产生的东西,但与e
的作用大致相同。在 Either e a
.换句话说,如果您通过 <|>
组合电线,则输出类型必须相等。
假设您的 GUI 事件通过输入传递到线路,并且您有一个连续的按键事件。一种建模方法是最直接的:
keyDown :: (Monad m, Monoid e) => Key -> Wire e m GameState ()
此连线将当前游戏状态作为输入并生成
()
如果键被按住。当键没有被按下时,它只是禁止。大多数应用程序并不真正关心为什么线路禁止,因此大多数线路禁止使用 mempty
.表达此事件的更方便的方法是使用 reader monad:
keyDown :: (Monoid e) => Key -> Wire e (Reader GameState) a a
这个变体真正有用的是,现在您不必将游戏状态作为输入传递。相反,当事件发生时,这条线就像身份线一样,当它没有发生时,它会被禁止:
quitScreen . keyDown Escape <|> mainGame
这个想法是,当按下转义键时,事件线
keyDown Escape
暂时消失,因为它就像身份线一样。所以整条线就像 quitScreen
假设它不会抑制自己。一旦键被释放,事件线被禁止,所以与 quitScreen
的组合抑制,也是。因此,整根电线的作用类似于 mainGame
.如果你想限制一条线可以看到的游戏状态,你可以很容易地为此编写一个线组合器:
trans :: (forall a. m' a -> m a) -> Wire e m' a b -> Wire e m a b
这允许您申请
withReaderT
:trans (withReaderT fullGameStateToPartialGameState)
关于haskell - 使用 netwire 进行游戏实体建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14668075/