This repository has been archived on 2023-06-24. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
2022FuncProg-project3-RPGEn.../lib/RPGEngine/Input/Playing.hs

83 lines
No EOL
3 KiB
Haskell

module RPGEngine.Input.Playing
( handleInputPlaying
, spawnPlayer
) where
import RPGEngine.Input.Core
( composeInputHandlers, handleKey, InputHandler )
import RPGEngine.Data
( Player(Player, position),
Direction(West, North, East, South),
Physical(Entrance),
Y,
X,
Level(Level, layout),
State(..),
StateBase(StateBase, renderer, inputHandler),
Game(..) )
import RPGEngine.Data.Level ( findFirstOf, directionOffsets )
import RPGEngine.Data.Game ( isLegalMove )
import RPGEngine.Input.Paused ( handleInputPaused )
import RPGEngine.Render.Paused ( renderPaused )
import Graphics.Gloss.Interface.IO.Game (Key(..))
import Graphics.Gloss.Interface.IO.Interact (SpecialKey(..))
import Data.Maybe (isNothing, fromJust)
------------------------------ Exported ------------------------------
handleInputPlaying :: InputHandler Game
handleInputPlaying = composeInputHandlers [
-- Pause the game
handleKey (Char 'p') pauseGame,
-- Player movement
handleKey (SpecialKey KeyUp) $ movePlayer North,
handleKey (SpecialKey KeyRight) $ movePlayer East,
handleKey (SpecialKey KeyDown) $ movePlayer South,
handleKey (SpecialKey KeyLeft) $ movePlayer West,
handleKey (Char 'w') $ movePlayer North,
handleKey (Char 'd') $ movePlayer East,
handleKey (Char 's') $ movePlayer South,
handleKey (Char 'a') $ movePlayer West
]
-- Set the initial position of the player in a given level.
spawnPlayer :: Level -> Player -> Player
spawnPlayer l@Level{ layout = lay } p@Player{ position = prevPos } = p{ position = newPos }
where try = findFirstOf l Entrance
newPos | isNothing try = prevPos
| otherwise = fromJust try
----------------------------------------------------------------------
pauseGame :: Game -> Game
pauseGame g@Game{ state = playing@Playing{} } = pausedGame
where pausedGame = g{ state = pausedState }
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{ 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
goToNextLevel = undefined
----------------------------------------------------------------------
-- Map all Physicals onto coordinates
putCoords :: Level -> [(X, Y, Physical)]
putCoords l@Level{ layout = lay } = concatMap (\(a, bs) -> map (\(b, c) -> (b, a, c)) bs) numberedList
where numberedStrips = zip [0::Int .. ] lay
numberedList = map (\(x, strip) -> (x, zip [0::Int ..] strip)) numberedStrips