dev #25
					 11 changed files with 59 additions and 44 deletions
				
			
		|  | @ -11,35 +11,37 @@ import RPGEngine.Render.Core ( Renderer ) | |||
| 
 | ||||
| -- A game is the base data container. | ||||
| data Game = Game { | ||||
|     state  :: State, | ||||
|     levels :: [Level], | ||||
|     player :: Player | ||||
|     state  :: State | ||||
| } | ||||
| 
 | ||||
| ------------------------------- State -------------------------------- | ||||
| 
 | ||||
| -- Code reusability | ||||
| data StateBase = StateBase { | ||||
|     renderer     :: Renderer Game, | ||||
|     renderer     :: Renderer State, | ||||
|     inputHandler :: InputHandler Game | ||||
| } | ||||
| 
 | ||||
|            -- Main menu | ||||
| data State = Menu           { base :: StateBase        } | ||||
| data State = Menu           { base      :: StateBase    } | ||||
|            -- Select the level you want to play | ||||
|            | LevelSelection { base :: StateBase,  | ||||
|                               levelList :: [FilePath],  | ||||
|                               selector :: ListSelector } | ||||
|            | LevelSelection { base      :: StateBase, | ||||
|                               levelList :: [FilePath], | ||||
|                               selector  :: ListSelector } | ||||
|            -- Playing a level | ||||
|            | Playing        { base  :: StateBase,  | ||||
|                               level :: Level           } | ||||
|            | Playing        { base      :: StateBase, | ||||
|                               levels    :: [Level], | ||||
|                               level     :: Level, | ||||
|                               player    :: Player, | ||||
|                               restart   :: State        } | ||||
|            -- Paused while playing a level | ||||
|            | Paused         { base  :: StateBase,  | ||||
|                               level :: Level           } | ||||
|            | Paused         { base      :: StateBase,  | ||||
|                               continue  :: State        } | ||||
|            -- Won a level | ||||
|            | Win            { base :: StateBase        } | ||||
|            | Win            { base      :: StateBase    } | ||||
|            -- Lost a level | ||||
|            | Lose           { base :: StateBase        } | ||||
|            | Lose           { base      :: StateBase, | ||||
|                               restart   :: State        } | ||||
| 
 | ||||
| ------------------------------- Level -------------------------------- | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,15 +6,15 @@ import RPGEngine.Data | |||
|     ( Player(Player, position), | ||||
|       Direction, | ||||
|       Physical(Exit, Walkable, Entrance), | ||||
|       State(Playing, level), | ||||
|       Game(Game, state, player) ) | ||||
|       State(..), | ||||
|       Game(..) ) | ||||
| import RPGEngine.Data.Level (findAt, directionOffsets) | ||||
| 
 | ||||
| ------------------------------ Exported ------------------------------ | ||||
| 
 | ||||
| -- Check if a move is legal by checking what is located at the new position. | ||||
| isLegalMove :: Direction -> Game -> Bool | ||||
| isLegalMove dir g@Game{ state = Playing { level = lvl }, player = p@Player{ position = (x, y) }} = legality | ||||
| isLegalMove dir g@Game{ state = Playing { level = lvl, player = p@Player{ position = (x, y) }}} = legality | ||||
|     where legality = physical `elem` [Walkable, Entrance, Exit] | ||||
|           physical = findAt newPos lvl | ||||
|           newPos   = (x + xD, y + yD) | ||||
|  |  | |||
|  | @ -2,11 +2,16 @@ module RPGEngine.Input.Paused | |||
| ( handleInputPaused | ||||
| ) where | ||||
| 
 | ||||
| import RPGEngine.Input.Core ( InputHandler ) | ||||
| import RPGEngine.Input.Core ( InputHandler, handleAnyKey ) | ||||
| 
 | ||||
| import RPGEngine.Data ( Game ) | ||||
| import RPGEngine.Data ( Game (..), State (..) ) | ||||
| 
 | ||||
| ------------------------------ Exported ------------------------------ | ||||
| 
 | ||||
| handleInputPaused :: InputHandler Game | ||||
| handleInputPaused = undefined | ||||
| handleInputPaused = handleAnyKey continueGame | ||||
| 
 | ||||
| continueGame :: Game -> Game | ||||
| continueGame g@Game{ state = Paused{ continue = state }} = newGame | ||||
|     where newGame = g{ state = state } | ||||
| continueGame g = g | ||||
|  | @ -15,7 +15,7 @@ import RPGEngine.Data | |||
|       Level(Level, layout), | ||||
|       State(..), | ||||
|       StateBase(StateBase, renderer, inputHandler), | ||||
|       Game(Game, state, player) ) | ||||
|       Game(..) ) | ||||
| import RPGEngine.Data.Level ( findFirstOf, directionOffsets ) | ||||
| import RPGEngine.Data.Game ( isLegalMove ) | ||||
| import RPGEngine.Input.Paused ( handleInputPaused ) | ||||
|  | @ -53,19 +53,22 @@ spawnPlayer l@Level{ layout = lay } p@Player{ position = prevPos } = p{ position | |||
| ---------------------------------------------------------------------- | ||||
| 
 | ||||
| pauseGame :: Game -> Game | ||||
| pauseGame g@Game{ state = Playing{ level = level } } = pausedGame | ||||
| pauseGame g@Game{ state = playing@Playing{} } = pausedGame | ||||
|     where pausedGame  = g{ state = pausedState } | ||||
|           pausedState = Paused{ base = newBase, level = level } | ||||
|           pausedState = Paused{ base = newBase, continue = playing } | ||||
|           newBase     = StateBase { renderer = renderPaused, inputHandler = handleInputPaused } | ||||
| pauseGame g = g | ||||
| 
 | ||||
| -- Move a player in a direction if possible. | ||||
| movePlayer :: Direction -> Game -> Game | ||||
| movePlayer dir g@Game{ player = p@Player{ position = (x, y) }} = newGame | ||||
|     where newGame   = g{ player   = newPlayer } | ||||
| movePlayer dir g@Game{ state = s@Playing{ player = p@Player{ position = (x, y) }}} = newGame | ||||
|     where newGame   = g{ state = newState } | ||||
|           newState  = s{ player   = newPlayer } | ||||
|           newPlayer = p{ position = newCoord  } | ||||
|           newCoord  | isLegalMove dir g = (x + xD, y + yD) | ||||
|                     | otherwise         = (x, y) | ||||
|           (xD, yD)  = directionOffsets dir | ||||
| movePlayer _ g = g | ||||
| 
 | ||||
| -- TODO | ||||
| goToNextLevel :: Game -> Game | ||||
|  |  | |||
|  | @ -26,13 +26,14 @@ initWindow = InWindow | |||
| -- Initialize the game | ||||
| initGame :: Game | ||||
| initGame = Game {  | ||||
|     state   = Menu{ base = StateBase{ renderer = renderMenu, inputHandler = handleInputMenu }}, | ||||
|     levels  = [defaultLevel], | ||||
|     player  = spawnPlayer defaultLevel defaultPlayer | ||||
|     state   = Menu{ base = StateBase{  | ||||
|         renderer = renderMenu,  | ||||
|         inputHandler = handleInputMenu | ||||
|     }} | ||||
| } | ||||
| 
 | ||||
| -- Render all different states | ||||
| render :: Game -> Picture | ||||
| render g@Game{ state = state } = renderFunc g | ||||
| render g@Game{ state = state } = renderFunc state | ||||
|     where stateBase  = base state | ||||
|           renderFunc = renderer stateBase | ||||
|  | @ -15,8 +15,8 @@ import Graphics.Gloss.Data.Color (red) | |||
| 
 | ||||
| ------------------------------ Exported ------------------------------ | ||||
| 
 | ||||
| renderLevelSelection :: Renderer Game | ||||
| renderLevelSelection Game{ state = state } = result | ||||
| renderLevelSelection :: Renderer State | ||||
| renderLevelSelection state = result | ||||
|     where result = renderLevelList state | ||||
| 
 | ||||
| ---------------------------------------------------------------------- | ||||
|  |  | |||
|  | @ -4,11 +4,11 @@ module RPGEngine.Render.Lose | |||
| 
 | ||||
| import RPGEngine.Render.Core ( Renderer ) | ||||
| 
 | ||||
| import RPGEngine.Data ( Game ) | ||||
| import RPGEngine.Data ( State ) | ||||
| import Graphics.Gloss ( text ) | ||||
| 
 | ||||
| ---------------------------------------------------------------------- | ||||
| 
 | ||||
| -- TODO | ||||
| renderLose :: Renderer Game | ||||
| renderLose :: Renderer State | ||||
| renderLose _ = text "Win" | ||||
|  | @ -4,11 +4,11 @@ module RPGEngine.Render.Menu | |||
| 
 | ||||
| import RPGEngine.Render.Core ( Renderer ) | ||||
| 
 | ||||
| import RPGEngine.Data ( Game ) | ||||
| import RPGEngine.Data ( State ) | ||||
| import Graphics.Gloss (text) | ||||
| 
 | ||||
| ---------------------------------------------------------------------- | ||||
| 
 | ||||
| -- TODO | ||||
| renderMenu :: Renderer Game | ||||
| renderMenu :: Renderer State | ||||
| renderMenu _ = text "[Press any key to start]" | ||||
|  | @ -4,7 +4,7 @@ module RPGEngine.Render.Paused | |||
| 
 | ||||
| import RPGEngine.Render.Core ( Renderer, overlay ) | ||||
| 
 | ||||
| import RPGEngine.Data ( Game ) | ||||
| import RPGEngine.Data ( State (..) ) | ||||
| import Graphics.Gloss ( pictures, scale, text ) | ||||
| import RPGEngine.Render.Playing ( renderPlaying ) | ||||
| import Graphics.Gloss.Data.Picture (color) | ||||
|  | @ -12,9 +12,10 @@ import Graphics.Gloss.Data.Color (white) | |||
| 
 | ||||
| ------------------------------ Exported ------------------------------ | ||||
| 
 | ||||
| renderPaused :: Renderer Game | ||||
| renderPaused g = pictures [renderPlaying g, pause] | ||||
|     where pause = pictures [ | ||||
| renderPaused :: Renderer State | ||||
| renderPaused state = pictures [playing, pause] | ||||
|     where playing = renderPlaying $ continue state | ||||
|           pause = pictures [ | ||||
|             overlay, | ||||
|             color white $ scale 0.5 0.5 $ text "[Press any key to continue]" | ||||
|             ] | ||||
|  | @ -16,14 +16,17 @@ import RPGEngine.Data | |||
| import Graphics.Gloss ( Picture, pictures ) | ||||
| import Graphics.Gloss.Data.Picture (translate) | ||||
| import RPGEngine.Config (resolution, zoom) | ||||
| import Graphics.Gloss (text) | ||||
| import Graphics.Gloss (blank) | ||||
| 
 | ||||
| ------------------------------ Exported ------------------------------ | ||||
| 
 | ||||
| renderPlaying :: Renderer Game | ||||
| renderPlaying g@Game{ state = Playing { level = lvl }, player = player } = pictures [ | ||||
| renderPlaying :: Renderer State | ||||
| renderPlaying Playing { level = lvl, player = player } = pictures [ | ||||
|     renderLevel lvl, | ||||
|     renderPlayer player | ||||
|     ] | ||||
| renderPlaying _ = blank | ||||
| 
 | ||||
| ------------------------------- Player ------------------------------- | ||||
| 
 | ||||
|  | @ -35,7 +38,7 @@ renderPlayer Player{ position = (x, y) } = move picture | |||
| -- Center the player in the middle of the screen. | ||||
| -- Not in use at the moment, might be useful later. | ||||
| focusPlayer :: Game -> Picture -> Picture | ||||
| focusPlayer Game{ player = Player{ position = (x, y)}} = move | ||||
| focusPlayer Game{ state = Playing{ player = Player{ position = (x, y) }}} = move | ||||
|     where move    = translate centerX centerY | ||||
|           centerX = resolution * zoom * fromIntegral (negate x) | ||||
|           centerY = resolution * zoom * fromIntegral (negate y) | ||||
|  |  | |||
|  | @ -4,11 +4,11 @@ module RPGEngine.Render.Win | |||
| 
 | ||||
| import RPGEngine.Render.Core ( Renderer ) | ||||
| 
 | ||||
| import RPGEngine.Data ( Game ) | ||||
| import RPGEngine.Data ( State ) | ||||
| import Graphics.Gloss (text) | ||||
| 
 | ||||
| ---------------------------------------------------------------------- | ||||
| 
 | ||||
| -- TODO | ||||
| renderWin :: Renderer Game | ||||
| renderWin :: Renderer State | ||||
| renderWin _ = text "Win" | ||||
		Reference in a new issue