#3 Restrict player going places

This commit is contained in:
Tibo De Peuter 2022-12-21 14:49:42 +01:00
parent 5c8cee8104
commit 0786a41006
6 changed files with 78 additions and 21 deletions

View file

@ -0,0 +1,27 @@
module RPGEngine.Input.Level
( putCoords
, findFirst
, whatIsAt
) where
import RPGEngine.Data (Level (..), Y, X, Physical(..))
-- 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
-- Find first position of a Physical
-- Graceful exit by giving Nothing if there is nothing found.
findFirst :: Level -> Physical -> Maybe (X, Y)
findFirst l@Level{ coordlayout = lay } physical = try
where matches = filter (\(x, y, v) -> v == physical) lay
try | not (null matches) = Just $ (\(x, y, _) -> (x, y)) $ head matches
| otherwise = Nothing
-- What is located at a given position in the level?
whatIsAt :: (X, Y) -> Level -> Physical
whatIsAt pos lvl@Level{ coordlayout = lay } = try
where matches = map (\(_, _, v) -> v) $ filter (\(x, y, v) -> (x, y) == pos) lay
try | not (null matches) = head matches
| otherwise = Void

View file

@ -1,19 +1,44 @@
module RPGEngine.Input.Player
( movePlayer
module RPGEngine.Input.Player
( spawnPlayer
, movePlayer
) where
import RPGEngine.Data (Game(..), Direction(..), Player(..), X, Y)
import RPGEngine.Data (Game(..), Direction(..), Player(..), X, Y, Physical (..), Level(..))
import RPGEngine.Input.Level (whatIsAt, findFirst)
import Data.Maybe (fromJust, isNothing)
----------------------------- Constants ------------------------------
movePlayer :: Direction -> Game -> Game
movePlayer dir g@Game{ player = p@Player{ coord = (x, y) }} = newGame
where newGame = g{ player = newPlayer }
newPlayer = p{ coord = newCoord }
newCoord = (x + xD, y + yD)
(xD, yD) = diffs dir
diffs :: Direction -> (X, Y)
diffs North = (0, 1)
diffs East = (1, 0)
diffs South = (0, -1)
diffs West = (-1, 0)
diffs Center = (0, 0)
diffs North = ( 0, 1)
diffs East = ( 1, 0)
diffs South = ( 0, -1)
diffs West = (-1, 0)
diffs Center = ( 0, 0)
----------------------------------------------------------------------
-- 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 = findFirst l Entrance
newPos | isNothing try = prevPos
| otherwise = fromJust try
-- 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 }
newPlayer = p{ position = newCoord }
newCoord | isLegalMove dir g = (x + xD, y + yD)
| otherwise = (x, y)
(xD, yD) = diffs dir
-- Check if a move is legal by checking what is located at the new position.
isLegalMove :: Direction -> Game -> Bool
isLegalMove dir g@Game{ playing = lvl, player = p@Player{ position = (x, y) }} = legality
where legality = physical `elem` [Walkable, Entrance, Exit]
physical = whatIsAt newPos lvl
newPos = (x + xD, y + yD)
(xD, yD) = diffs dir