Files
loop/src/Dodge/Menu.hs
T

216 lines
7.2 KiB
Haskell

module Dodge.Menu
( scodeToChar
, popScreen
, pushScreen
, pauseMenu
, gameOverMenu
)
where
import Dodge.Data
import Dodge.Save
import Dodge.Config.Update
import SDL
import SDL.Internal.Numbered
import Preload.Update
import Dodge.Base.Window
import Dodge.SoundLogic
import Dodge.LevelGen
import Control.Lens
import System.Random
optionMenu :: ScreenLayer
optionMenu = OptionScreen
{ _scTitle = const "OPTIONS"
, _scOptions = optionsOptions
, _scDefaultEff = popScreen
, _scOptionFlag = NormalOptions
}
optionsOptions :: [MenuOption]
optionsOptions =
[ anOption ScancodeV soundMenu "VOLUME"
, anOption ScancodeG graphicsMenu "GRAPHICS"
, anOption ScancodeP gameplayMenu "GAMEPLAY"
, anOption ScancodeD debugMenu "DEBUG OPTIONS"
]
where
anOption scode submenu t = Toggle scode (pushScreen submenu) (const t)
debugMenu :: ScreenLayer
debugMenu = OptionScreen
{ _scTitle = const "OPTIONS:GAMEPLAY"
, _scOptions = debugMenuOptions
, _scDefaultEff = popScreen . writeConfig
, _scOptionFlag = NormalOptions
}
debugMenuOptions :: [MenuOption]
debugMenuOptions =
[ doption ScancodeF debug_seconds_frame "SHOW SECONDS/FRAME" _debug_seconds_frame
, doption ScancodeC debug_noclip "NOCLIP" _debug_noclip
, doption ScancodeS debug_cr_status "SHOW CREATURE STATUS" _debug_cr_status
, doption ScancodeV debug_view_boundaries "SHOW VIEW BOUNDARIES" _debug_view_boundaries
, doption ScancodeP debug_pathing "SHOW PATHING" _debug_pathing
]
where
doption scode l t rec
= Toggle scode (Just . (config . l %~ not)) (\w -> t ++ ":" ++ show (rec $ _config w))
gameplayMenu :: ScreenLayer
gameplayMenu = OptionScreen
{ _scTitle = const "OPTIONS:GAMEPLAY"
, _scOptions = gameplayMenuOptions
, _scDefaultEff = popScreen . writeConfig
, _scOptionFlag = NormalOptions
}
gameplayMenuOptions :: [MenuOption]
gameplayMenuOptions =
[ option ScancodeR rotate_to_wall "ROTATE TO WALL" _rotate_to_wall
, option ScancodeS show_sound "SHOW VISUAL SOUNDS" _show_sound
]
where
option scode l t rec = Toggle scode (Just . (config . l %~ not))
(\w -> t ++ ":" ++ show (rec $ _config w))
soundMenu :: ScreenLayer
soundMenu = OptionScreen
{ _scTitle = const "OPTIONS:VOLUME"
, _scOptions = soundMenuOptions
, _scDefaultEff = popScreen . writeConfig
, _scOptionFlag = NormalOptions
}
soundMenuOptions :: [MenuOption]
soundMenuOptions =
[ Toggle2 ScancodeY (master dec . sw)
ScancodeU (master inc . sw) (\w -> "MASTER VOLUME:" ++ mavol w)
, Toggle2 ScancodeH (soundEffs dec . sw)
ScancodeJ (soundEffs inc . sw) (\w -> "EFFECTS VOLUME:" ++ snvol w)
, Toggle2 ScancodeN (music dec . sw)
ScancodeM (music inc . sw) (\w -> "MUSIC VOLUME:" ++ muvol w)
]
where
dec x = max 0 (x - 0.1)
inc x = min 1 (x + 0.1)
--sw w = w & sideEffects %~ (setVol (_config w) : )
sw w = w & sideEffects %~ setVolThen (_config w)
master g = Just . (config . volume_master %~ g)
soundEffs g = Just . (config . volume_sound %~ g)
music g = Just . (config . volume_music %~ g)
cfig w = _config w
mavol w = f $ _volume_master $ cfig w
snvol w = f $ _volume_sound $ cfig w
muvol w = f $ _volume_music $ cfig w
f x = show (round $ 10 * x :: Int)
pushScreen :: ScreenLayer -> World -> Maybe World
pushScreen ml w = Just $ w & menuLayers %~ (ml :)
popScreen :: World -> Maybe World
popScreen = Just . (menuLayers %~ tail)
writeConfig :: World -> World
writeConfig w = w & sideEffects %~ saveConfig (_config w)
graphicsMenu :: ScreenLayer
graphicsMenu = OptionScreen
{ _scTitle = const "OPTIONS:GRAPHICS"
, _scOptions = graphicsMenuOptions
, _scDefaultEff = popScreen . writeConfig
, _scOptionFlag = NormalOptions
}
graphicsMenuOptions :: [MenuOption]
graphicsMenuOptions =
[ Toggle ScancodeW (Just . (config . wall_textured %~ not)) wtextstring
, Toggle ScancodeS upf resostring
, Toggle ScancodeD (Just . (config . cloud_shadows %~ not)) cshadstring
]
where
wtextstring w = "WALL TEXTURES:" ++ show (_wall_textured $ _config w)
resostring w = "RESOLUTION: 1/" ++ show (_resolution_factor $ _config w)
upf w = Just $ updateFramebufferSize $ w & config . resolution_factor %~ cycleResolution
cshadstring w = "CLOUD SHADOWS:" ++ show (_cloud_shadows $ _config w)
cycleResolution :: (Eq a, Num a, Num p) => a -> p
cycleResolution 1 = 2
cycleResolution 2 = 4
cycleResolution 4 = 1
cycleResolution _ = 1
gameOverMenu :: ScreenLayer
gameOverMenu = OptionScreen
{ _scTitle = const "GAME OVER"
, _scOptions = pauseMenuOptions
, _scDefaultEff = Just
, _scOptionFlag = GameOverOptions
}
pauseMenu :: ScreenLayer
pauseMenu = OptionScreen
{ _scTitle = const "PAUSED"
, _scOptions = pauseMenuOptions
, _scDefaultEff = unpause
, _scOptionFlag = NormalOptions
}
pauseMenuOptions :: [MenuOption]
pauseMenuOptions =
[ Toggle ScancodeN startNewGame (const "NEW LEVEL")
, Toggle ScancodeR (Just . loadSaveSlot LevelStartSlot) (const "RESTART")
, Toggle ScancodeO (pushScreen optionMenu ) (const "OPTIONS")
, Toggle ScancodeC (pushScreen displayControls) (const "CONTROLS")
, InvisibleToggle ScancodeEscape (const Nothing)
]
startNewGame :: World -> Maybe World
startNewGame w = Just $ w
& menuLayers .~ [WaitScreen (const "GENERATING...") 1]
& sideEffects .~ uvWorld (uvWorldSideEffects i w)
where
i = fst $ random (_randGen w)
uvWorldSideEffects :: Int -> World -> b -> IO World
uvWorldSideEffects i w = const (generateWorldFromSeed i <&> keyConfig .~ _keyConfig w <&> config .~ _config w
<&> preloadData .~ _preloadData w)
-- this kills save games etc...
-- | hacky
scodeToChar :: Scancode -> Char
scodeToChar = toEnum . (+ 61) . fromIntegral . toNumber
--charToScode :: Char -> Scancode
--charToScode = Scancode . fromIntegral . (\x -> x - 61) . fromEnum
updateFramebufferSize :: World -> World
updateFramebufferSize w = w & sideEffects %~ up
where
(x,y) = (round $ getWindowX w, round $ getWindowY w)
divRes = w ^. config . resolution_factor
up :: (Universe -> IO Universe) -> Universe -> IO Universe
up f w' = do
pdata <- pdataResizeUpdate (x `div` divRes) (y `div` divRes) x y (_preloadData (_uvWorld w'))
f $ w' & uvWorld . preloadData .~ pdata
--levelMenu :: Int -> ScreenLayer
--levelMenu x = OptionScreen
-- { _scTitle = const $ "LEVEL "++ show x
-- , _scOptions = levelMenuOptions
-- , _scDefaultEff = unpause . storeLevel
-- , _scOptionFlag = NormalOptions
-- }
unpause :: World -> Maybe World
unpause w = Just . resumeSound $ w {_menuLayers = []}
displayControls :: ScreenLayer
displayControls = ColumnsScreen "CONTROLS" listControls
listControls :: [(String,String)]
listControls =
[("wasd", "MOVEMENT")
,("[rmb]", "AIM")
,("[rmb+lmb]", "SHOOT OR USE ITEM")
,("[wheelscroll]" , "SELECT ITEM" )
,("[space]" , "PICKUP ITEM" )
,("m" , "DISPLAY MAP" )
,("f" , "DROP ITEM" )
,("c[esc]" , "PAUSE" )
,("qe" , "ROTATE CAMERA")
,("F5" , "QUICKSAVE")
,("F9" , "QUICKLOAD")
]