Nik*_*gyu 8 user-interface haskell sdl
我正在Haskell中编写一个小型RTS游戏,现在是时候为它创建一些GUI(按钮,菜单等).但是,我没有任何GUI工具包创建经验,所以我要感谢有关如何选择正确的数据类型,事件处理例程等的想法.
所需功能:菜单屏幕(主要,加载/保存,设置,网络游戏),文本输入,游戏界面(主屏幕(C&C)),按钮,选择和复选框.
我当前的方法是将整个GUI表示为一个状态机,它在它们之间有许多状态和转换,当事件到达时触发它们:
-- Local client state. Actual game state is stored on the server
-- and is updated/synced separately.
data ClientState = […]
-- Keyboard state, mouse state, quadtree of clickables, list of
-- widgets.
data UIState = […]
uiCycle :: UIState -> ClientState -> IO ()
uiCycle uiState clientState = do
event <- waitEvent
let widget = findWidget uiState event
let (uiState', clientStateAction, ioAction) =
uiTransition widget event uiState clientState
-- Update game state (execute game logic).
let clientState' = clientStateAction clientState
-- Redraw appropriate surfaces etc.
ioAction
uiCycle uiState' clientState'
Run Code Online (Sandbox Code Playgroud)
小工具就像
data Widget =
Widget { wtType :: WidgetType
, wtParent :: Maybe Widget
--, wtRelated :: [Widget] -- Feels hacky.
, wtBox :: Rect
, wtPosition :: WidgetPosition
, wtAnchors :: [WidgetAnchor]
, wtEventHandlers :: Map Event EventHandler
, wtDisabled :: Bool
}
Run Code Online (Sandbox Code Playgroud)
哪里
type EventHandler = (Event -> (UIState, ClientState) ->
(UIState, ClientState, IO ()))
Run Code Online (Sandbox Code Playgroud)
当一个事件到来并找到适当的小部件时,我的程序会wtEventHandlers为这个小部件查找此类事件的处理程序,并在找到此类处理程序时执行操作.
创建窗口小部件时,会将其rect添加到a QuadTree,查询该窗口findWidget.创建或删除窗口小部件时会更新树.
但是,以这种方式编程是非常困难的,因为UI状态已经很多(即使对于具有几个按钮且没有菜单的简单UI).
我考虑将每个小部件实现为状态机并组合这些机器,以便减少状态和转换的数量.也许将它包装成monad会很好(就像在XMonad中完成的那样).
我看过的事情:
我的问题是:
Monad个好主意吗?E. g.
mkGameScreenButtons = runGuiDef $ do
panicExitButton /// MouseDown ==> liftM exitGameNow
panicExitButton /// MouseIn ==> do hideGameScreen
muteSounds
muteMusic
panicExitButton /// MouseOut ==> do unhideGameScreen
unmuteSounds
unmuteMusic
gameSpeedSlider /// MouseUp ==> changeSpeed (wtValue gameSpeedSlider)
[...]
where panicExitButton = mkButton (5, 5) [AnchorTop, AnchorRight] "BOSS BUTTON"
[...]
Run Code Online (Sandbox Code Playgroud)