diff --git a/lib/RPGEngine/Data.hs b/lib/RPGEngine/Data.hs index 641f109..3a701a2 100644 --- a/lib/RPGEngine/Data.hs +++ b/lib/RPGEngine/Data.hs @@ -14,9 +14,10 @@ data Game = Game { ------------------------------- Level -------------------------------- data Level = Level { - layout :: Layout, - items :: [Item], - entities :: [Entity] + layout :: Layout, + coordlayout :: [(X, Y, Physical)], + items :: [Item], + entities :: [Entity] } deriving (Eq, Show) type Layout = [Strip] @@ -37,7 +38,7 @@ type Y = Int data Player = Player { playerHp :: Maybe Int, inventory :: [Item], - coord :: (X, Y) + position :: (X, Y) } deriving (Eq, Show) instance Living Player where diff --git a/lib/RPGEngine/Data/Defaults.hs b/lib/RPGEngine/Data/Defaults.hs index 75965a4..e3414eb 100644 --- a/lib/RPGEngine/Data/Defaults.hs +++ b/lib/RPGEngine/Data/Defaults.hs @@ -1,6 +1,8 @@ module RPGEngine.Data.Defaults where import RPGEngine.Data +import RPGEngine.Input.Player (spawnPlayer) +import RPGEngine.Input.Level (putCoords) defaultEntity :: Entity defaultEntity = Entity { @@ -21,7 +23,7 @@ initGame = Game { state = defaultState, playing = defaultLevel, levels = [defaultLevel], - player = defaultPlayer + player = spawnPlayer defaultLevel defaultPlayer } defaultItem :: Item @@ -46,6 +48,7 @@ defaultLayout = [ defaultLevel :: Level defaultLevel = Level { layout = defaultLayout, + coordlayout = putCoords defaultLevel, -- TODO This should go items = [], entities = [] } @@ -54,7 +57,7 @@ defaultPlayer :: Player defaultPlayer = Player { playerHp = Prelude.Nothing, -- Compares to infinity inventory = [], - coord = (0, 0) + position = (0, 0) } -- Default state of the game, Menu diff --git a/lib/RPGEngine/Input/Level.hs b/lib/RPGEngine/Input/Level.hs new file mode 100644 index 0000000..63391c9 --- /dev/null +++ b/lib/RPGEngine/Input/Level.hs @@ -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 diff --git a/lib/RPGEngine/Input/Player.hs b/lib/RPGEngine/Input/Player.hs index 3b77917..be56f27 100644 --- a/lib/RPGEngine/Input/Player.hs +++ b/lib/RPGEngine/Input/Player.hs @@ -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 \ No newline at end of file diff --git a/lib/RPGEngine/Render/Player.hs b/lib/RPGEngine/Render/Player.hs index 0d5f65c..7adb8b0 100644 --- a/lib/RPGEngine/Render/Player.hs +++ b/lib/RPGEngine/Render/Player.hs @@ -8,4 +8,4 @@ import Graphics.Gloss (Picture, text) import RPGEngine.Render.Core (getRender, setRenderPos) renderPlayer :: Player -> Picture -renderPlayer Player{ coord = (x, y) } = setRenderPos x y $ getRender "player" +renderPlayer Player{ position = (x, y) } = setRenderPos x y $ getRender "player" \ No newline at end of file diff --git a/rpg-engine.cabal b/rpg-engine.cabal index 51f2809..d7c3090 100644 --- a/rpg-engine.cabal +++ b/rpg-engine.cabal @@ -19,6 +19,7 @@ library RPGEngine.Input RPGEngine.Input.Core + RPGEngine.Input.Level RPGEngine.Input.Player RPGEngine.Parse