diff --git a/assets/entities/player.png b/assets/entities/player.png new file mode 100644 index 0000000..512b550 Binary files /dev/null and b/assets/entities/player.png differ diff --git a/assets/unkown.png b/assets/unkown.png new file mode 100644 index 0000000..005de40 Binary files /dev/null and b/assets/unkown.png differ diff --git a/lib/RPGEngine/Data.hs b/lib/RPGEngine/Data.hs index 13be117..641f109 100644 --- a/lib/RPGEngine/Data.hs +++ b/lib/RPGEngine/Data.hs @@ -7,7 +7,8 @@ data Game = Game { -- Current state of the game state :: State, playing :: Level, - levels :: [Level] + levels :: [Level], + player :: Player } ------------------------------- Level -------------------------------- @@ -30,9 +31,13 @@ data Physical = Void ------------------------------- Player ------------------------------- +type X = Int +type Y = Int + data Player = Player { playerHp :: Maybe Int, - inventory :: [Item] + inventory :: [Item], + coord :: (X, Y) } deriving (Eq, Show) instance Living Player where diff --git a/lib/RPGEngine/Data/Defaults.hs b/lib/RPGEngine/Data/Defaults.hs index 2ef92f2..75965a4 100644 --- a/lib/RPGEngine/Data/Defaults.hs +++ b/lib/RPGEngine/Data/Defaults.hs @@ -18,9 +18,10 @@ defaultEntity = Entity { -- Initialize the game initGame :: Game initGame = Game { - state = defaultState, + state = defaultState, playing = defaultLevel, - levels = [defaultLevel] + levels = [defaultLevel], + player = defaultPlayer } defaultItem :: Item @@ -51,8 +52,9 @@ defaultLevel = Level { defaultPlayer :: Player defaultPlayer = Player { - playerHp = Prelude.Nothing, -- Compares to infinity - inventory = [] + playerHp = Prelude.Nothing, -- Compares to infinity + inventory = [], + coord = (0, 0) } -- Default state of the game, Menu diff --git a/lib/RPGEngine/Input.hs b/lib/RPGEngine/Input.hs index 04b6a6a..a737d05 100644 --- a/lib/RPGEngine/Input.hs +++ b/lib/RPGEngine/Input.hs @@ -7,6 +7,7 @@ module RPGEngine.Input import RPGEngine.Data import RPGEngine.Data.State import RPGEngine.Input.Core +import RPGEngine.Input.Player import Graphics.Gloss.Interface.IO.Game @@ -22,7 +23,19 @@ handleAllInput ev g = handleAnyKey setNextState ev g -- Input for 'Playing' state handlePlayInputs :: InputHandler Game handlePlayInputs = composeInputHandlers [ - handleKey (Char 'p') (\game -> game{ state = Pause }) + -- Pause the game + handleKey (Char 'p') (\game -> game{ state = Pause }), + + -- 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 ] -- Go to the next stage of the Game diff --git a/lib/RPGEngine/Input/Player.hs b/lib/RPGEngine/Input/Player.hs new file mode 100644 index 0000000..3b77917 --- /dev/null +++ b/lib/RPGEngine/Input/Player.hs @@ -0,0 +1,19 @@ +module RPGEngine.Input.Player +( movePlayer +) where + +import RPGEngine.Data (Game(..), Direction(..), Player(..), X, Y) + +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) diff --git a/lib/RPGEngine/Render.hs b/lib/RPGEngine/Render.hs index 03e7855..1468f77 100644 --- a/lib/RPGEngine/Render.hs +++ b/lib/RPGEngine/Render.hs @@ -8,7 +8,15 @@ module RPGEngine.Render ) where import RPGEngine.Data + ( State(..), + Game(..) ) +import RPGEngine.Render.Level + ( renderLevel ) + import Graphics.Gloss + ( white, pictures, text, Display(InWindow), Color, Picture ) +import RPGEngine.Render.Player (renderPlayer) +import RPGEngine.Render.GUI (renderGUI) ----------------------------- Constants ------------------------------ @@ -36,9 +44,12 @@ render g@Game{ state = Lose } = renderLose g renderMenu :: Game -> Picture renderMenu _ = text "[Press any key to start]" --- TODO renderPlaying :: Game -> Picture -renderPlaying _ = text "Playing" +renderPlaying g@Game{ playing = lvl, player = player } = pictures [ + renderLevel lvl, + renderPlayer player, + renderGUI g + ] -- TODO renderPause :: Game -> Picture diff --git a/lib/RPGEngine/Render/Core.hs b/lib/RPGEngine/Render/Core.hs new file mode 100644 index 0000000..0fe63ab --- /dev/null +++ b/lib/RPGEngine/Render/Core.hs @@ -0,0 +1,63 @@ +module RPGEngine.Render.Core where + +import Graphics.Gloss ( Picture, translate ) +import GHC.IO (unsafePerformIO) +import Graphics.Gloss.Juicy (loadJuicyPNG) +import Data.Maybe (fromJust) +import Graphics.Gloss.Data.Picture (scale) + +----------------------------- Constants ------------------------------ + +-- Default scale +zoom :: Float +zoom = 5.0 + +-- Resolution of the texture +resolution :: Float +resolution = 16 + +assetsFolder :: FilePath +assetsFolder = "assets/" + +unknownImage :: FilePath +unknownImage = "unkown.png" + +allEntities :: [(String, FilePath)] +allEntities = [ + ("player", "player.png"), + ("door", "door.png") + ] + +allItems :: [(String, FilePath)] +allItems = [ + ("dagger", "dagger.png"), + ("key", "key.png" ) + ] + +-- Map of all renders +library :: [(String, Picture)] +library = unknown:entities ++ environment ++ gui ++ items + where unknown = ("unkown", renderPNG (assetsFolder ++ unknownImage)) + entities = map (\(f, s) -> (f, renderPNG (assetsFolder ++ "entities/" ++ s))) allEntities + environment = [] + gui = [] + items = map (\(f, s) -> (f, renderPNG (assetsFolder ++ "items/" ++ s))) allItems + +---------------------------------------------------------------------- + +-- Turn a path to a .png file into a Picture. +renderPNG :: FilePath -> Picture +renderPNG path = scale zoom zoom $ fromJust $ unsafePerformIO $ loadJuicyPNG path + +-- Retrieve an image from the library. If the library does not contain +-- the requested image, a default is returned. +getRender :: String -> Picture +getRender id = get filtered + where filtered = filter ((== id) . fst) library + get [] = snd $ head library + get ((_, res):_) = res + +setRenderPos :: Int -> Int -> Picture -> Picture +setRenderPos x y = translate floatX floatY + where floatX = fromIntegral x * zoom * resolution + floatY = fromIntegral y * zoom * resolution \ No newline at end of file diff --git a/lib/RPGEngine/Render/GUI.hs b/lib/RPGEngine/Render/GUI.hs new file mode 100644 index 0000000..e29b012 --- /dev/null +++ b/lib/RPGEngine/Render/GUI.hs @@ -0,0 +1,10 @@ +module RPGEngine.Render.GUI +( renderGUI +) where + +import RPGEngine.Data (Game) +import Graphics.Gloss (Picture, blank) + +-- TODO +renderGUI :: Game -> Picture +renderGUI _ = blank diff --git a/lib/RPGEngine/Render/Level.hs b/lib/RPGEngine/Render/Level.hs new file mode 100644 index 0000000..267316c --- /dev/null +++ b/lib/RPGEngine/Render/Level.hs @@ -0,0 +1,10 @@ +module RPGEngine.Render.Level +( renderLevel +) where + +import Graphics.Gloss +import RPGEngine.Data + +-- TODO +renderLevel :: Level -> Picture +renderLevel _ = text "Level" \ No newline at end of file diff --git a/lib/RPGEngine/Render/Player.hs b/lib/RPGEngine/Render/Player.hs new file mode 100644 index 0000000..0d5f65c --- /dev/null +++ b/lib/RPGEngine/Render/Player.hs @@ -0,0 +1,11 @@ +module RPGEngine.Render.Player +( renderPlayer +) where + +import RPGEngine.Data (Player(..)) + +import Graphics.Gloss (Picture, text) +import RPGEngine.Render.Core (getRender, setRenderPos) + +renderPlayer :: Player -> Picture +renderPlayer Player{ coord = (x, y) } = setRenderPos x y $ getRender "player" diff --git a/rpg-engine.cabal b/rpg-engine.cabal index 0823b23..51f2809 100644 --- a/rpg-engine.cabal +++ b/rpg-engine.cabal @@ -19,6 +19,7 @@ library RPGEngine.Input RPGEngine.Input.Core + RPGEngine.Input.Player RPGEngine.Parse RPGEngine.Parse.Core @@ -26,6 +27,10 @@ library RPGEngine.Parse.StructElement RPGEngine.Render + RPGEngine.Render.Core + RPGEngine.Render.GUI + RPGEngine.Render.Level + RPGEngine.Render.Player executable rpg-engine main-is: Main.hs