spice (empty) → 0.1.0.0
raw patch · 12 files changed
+383/−0 lines, 12 filesdep +GLFWdep +OpenGLdep +basesetup-changed
Dependencies added: GLFW, OpenGL, base, containers, data-default, elerea
Files
- LICENSE +20/−0
- Setup.hs +2/−0
- spice.cabal +35/−0
- src/FRP/Spice.hs +8/−0
- src/FRP/Spice/Config.hs +31/−0
- src/FRP/Spice/Engine.hs +54/−0
- src/FRP/Spice/Game.hs +13/−0
- src/FRP/Spice/Input.hs +90/−0
- src/FRP/Spice/Input/Keyboard.hs +28/−0
- src/FRP/Spice/Input/Mouse.hs +43/−0
- src/FRP/Spice/Input/MousePosition.hs +24/−0
- src/FRP/Spice/Math/Vector.hs +35/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2014 Cerek Hillen++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ spice.cabal view
@@ -0,0 +1,35 @@+name: spice+version: 0.1.0.0+synopsis: An FRP-based game engine written in Haskell.+description: An FRP-based game engine written in Haskell. - See the homepage for more information.+homepage: http://github.com/crockeo/spice+license: MIT+license-file: LICENSE+author: Cerek Hillen+maintainer: Cerek Hillen <cerekh@gmail.com>+copyright: (c) 2014, Cerek Hillen+category: FRP+build-type: Simple+cabal-version: >=1.10++library+ exposed-modules: FRP.Spice+ FRP.Spice.Config+ FRP.Spice.Engine+ FRP.Spice.Game+ FRP.Spice.Input+ FRP.Spice.Input.Keyboard+ FRP.Spice.Input.Mouse+ FRP.Spice.Input.MousePosition+ FRP.Spice.Math.Vector++ hs-source-dirs: src/++ build-depends: base == 4.7.*+ , elerea == 2.7.*+ , GLFW == 0.5.*+ , containers == 0.5.*+ , data-default == 0.5.*+ , OpenGL++ default-language: Haskell2010
+ src/FRP/Spice.hs view
@@ -0,0 +1,8 @@+module FRP.Spice (module Rexport) where++-----------------------+-- Rexported Imports --+import FRP.Spice.Config as Rexport+import FRP.Spice.Engine as Rexport+import FRP.Spice.Input as Rexport+import FRP.Spice.Game as Rexport
+ src/FRP/Spice/Config.hs view
@@ -0,0 +1,31 @@+module FRP.Spice.Config where++--------------------+-- Global Imports --+import Data.Default++----------+-- Code --++-- The window config+data WindowConfig = WindowConfig { getWindowWidth :: Int+ , getWindowHeight :: Int+ , getWindowFullscreen :: Bool+ , getWindowResizable :: Bool+ , getWindowTitle :: String+ }+ deriving (Eq, Show, Read)++-- The default window config+defaultWindowConfig :: WindowConfig+defaultWindowConfig = WindowConfig { getWindowWidth = 640+ , getWindowHeight = 480+ , getWindowFullscreen = False+ , getWindowResizable = False+ , getWindowTitle = "Spice Application"+ }++-- A default instance for the window+-- config+instance Default WindowConfig where+ def = defaultWindowConfig
+ src/FRP/Spice/Engine.hs view
@@ -0,0 +1,54 @@+module FRP.Spice.Engine where++--------------------+-- Global Imports --+import Graphics.Rendering.OpenGL+import Graphics.UI.GLFW as GLFW+import FRP.Elerea.Param+import Data.IORef++-------------------+-- Local Imports --+import FRP.Spice.Engine.RunInput+import FRP.Spice.Engine.Network+import FRP.Spice.Engine.Driver+import FRP.Spice.Config+import FRP.Spice.Input+import FRP.Spice.Game++----------+-- Code --++-- Starting the engine+startEngine :: Game a => WindowConfig -> a -> IO ()+startEngine wc game = do+ -- Opening the window+ initialize+ openWindow (Size 640 480) [DisplayRGBBits 8 8 8, DisplayAlphaBits 8, DisplayDepthBits 24] Window++ -- Checking for the window being closed+ closed <- newIORef False+ windowCloseCallback $= do+ writeIORef closed True+ return True++ -- Getting an external of the game+ (gameSignal, gameSink) <- external game++ -- Getting the input container+ ic <- makeInputContainer++ -- Updating the input+ mousePosCallback $= makeMousePositionCallback ic+ keyCallback $= makeKeyboardCallback ic+ mouseButtonCallback $= makeMouseCallback ic++ -- Creating the network+ network <- makeNetwork (getInput ic) gameSignal gameSink++ -- Driving the network+ GLFW.time $= 0+ driveNetwork network $ runInput closed++ -- Closing the window, after all is said and done+ closeWindow
+ src/FRP/Spice/Game.hs view
@@ -0,0 +1,13 @@+module FRP.Spice.Game where++-------------------+-- Local Imports --+import FRP.Spice.Input++----------+-- Code --++-- The game instance, to be used with updating and rendering+class Game a where+ update :: Float -> Input -> a -> a+ render :: a -> IO ()
+ src/FRP/Spice/Input.hs view
@@ -0,0 +1,90 @@+module FRP.Spice.Input ( module Rexport+ , Sinks (..)+ , Input (..)+ , InputContainer (..)+ , makeInputContainer+ , makeMousePositionCallback+ , makeKeyboardCallback+ , makeMouseCallback+ ) where++--------------------+-- Global Imports --+import Data.Map.Strict hiding (keys, map)+import Graphics.Rendering.OpenGL+import Graphics.UI.GLFW as GLFW+import Control.Applicative+import FRP.Elerea.Param++-------------------+-- Local Imports --+import qualified FRP.Spice.Input.MousePosition as MousePosition+import qualified FRP.Spice.Input.Keyboard as Keyboard+import qualified FRP.Spice.Input.Mouse as Mouse+import FRP.Spice.Math.Vector++-----------------------+-- Rexported Imports --+import Data.Map.Strict as Rexport ((!))+import Graphics.UI.GLFW as Rexport (Key (..), SpecialKey (..), MouseButton (..))++----------+-- Code --++-- The sinks+data Sinks = Sinks { mousePositionSinks :: Vector Float -> IO ()+ , keyboardSinks :: Map Key (Bool -> IO ())+ , mouseSinks :: Map MouseButton (Bool -> IO ())+ }++data Input = Input { mousePosition :: Vector Float+ , keyboard :: Map Key Bool+ , mouse :: Map MouseButton Bool+ }++-- The container to go around the+data InputContainer = InputContainer { getSinks :: Sinks+ , getInput :: Signal Input+ }++-- Creating the input container for use in the program+makeInputContainer :: IO InputContainer+makeInputContainer = do+ mousePositionExternals <- MousePosition.externals+ keyboardExternals <- Keyboard.externals+ mouseExternals <- Mouse.externals++ let sinks = Sinks { mousePositionSinks = MousePosition.sinks mousePositionExternals+ , keyboardSinks = Keyboard.sinks keyboardExternals+ , mouseSinks = Mouse.sinks mouseExternals+ }++ let input = do mps <- fst mousePositionExternals+ kbs <- Keyboard.signals keyboardExternals+ ms <- Mouse.signals mouseExternals++ return Input { mousePosition = mps+ , keyboard = kbs+ , mouse = ms+ }++ return InputContainer { getSinks = sinks+ , getInput = input+ }++-- Creating callbacks for each type+makeMousePositionCallback :: InputContainer -> MousePosCallback+makeMousePositionCallback ic (Position x y) =+ mousePositionSinks (getSinks ic) $ Vector (fromIntegral x / 320 - 1) ((-fromIntegral y) / 240 - 1)++makeKeyboardCallback :: InputContainer -> KeyCallback+makeKeyboardCallback ic key state =+ keyboardSinks (getSinks ic) ! key $ case state of+ Press -> True+ Release -> False++makeMouseCallback :: InputContainer -> MouseButtonCallback+makeMouseCallback ic button state =+ mouseSinks (getSinks ic) ! button $ case state of+ Press -> True+ Release -> False
+ src/FRP/Spice/Input/Keyboard.hs view
@@ -0,0 +1,28 @@+module FRP.Spice.Input.Keyboard where++--------------------+-- Global Imports --+import qualified Data.Traversable as T+import Data.Map.Strict hiding (keys, map)+import Graphics.UI.GLFW as GLFW+import FRP.Elerea.Param+import Control.Monad++----------+-- Code --++-- A set of all keys available via GLFW+keys :: [Key]+keys = map toEnum [0 .. 318]++-- Getting the externals for all of the keys+externals :: IO (Map Key (Signal Bool, Bool -> IO ()))+externals = liftM fromList $ mapM (\k -> liftM ((,) k) $ external False) keys++-- Getting the signals from the externals+signals :: Map Key (Signal Bool, Bool -> IO ()) -> Signal (Map Key Bool)+signals = T.sequence . fmap fst++-- Getting the sinks from the externals+sinks :: Map Key (Signal Bool, Bool -> IO ()) -> Map Key (Bool -> IO ())+sinks = fmap snd
+ src/FRP/Spice/Input/Mouse.hs view
@@ -0,0 +1,43 @@+module FRP.Spice.Input.Mouse where++--------------------+-- Global Imports --+import qualified Data.Traversable as T (sequence)+import Data.Map.Strict hiding (keys, map)+import Graphics.Rendering.OpenGL+import Graphics.UI.GLFW as GLFW+import FRP.Elerea.Param+import Control.Monad+import Data.Default++-------------------+-- Local Imports --+import FRP.Spice.Math.Vector++----------+-- Code --++-- Adding an instance of Ord to MouseButton so it can be used with the map+instance Ord MouseButton where+ mb1 <= mb2 = fromEnum mb1 < fromEnum mb2++-- A set of all mouse buttons available via GLFW+buttons :: [MouseButton]+buttons = [ ButtonLeft+ , ButtonRight+ , ButtonMiddle+ ]+ +++ map ButtonNo [0 .. 7]++-- Getting externals for all of the buttons+externals :: IO (Map MouseButton (Signal Bool, Bool -> IO ()))+externals = liftM fromList $ mapM (\b -> liftM ((,) b) $ external False) buttons++-- Getting the signals from the externals+signals :: Map MouseButton (Signal Bool, Bool -> IO ()) -> Signal (Map MouseButton Bool)+signals = T.sequence . fmap fst++-- Getting the sinks from the externals+sinks :: Map MouseButton (Signal Bool, Bool -> IO ()) -> Map MouseButton (Bool -> IO ())+sinks = fmap snd
+ src/FRP/Spice/Input/MousePosition.hs view
@@ -0,0 +1,24 @@+module FRP.Spice.Input.MousePosition where++--------------------+-- Global Imports --+import Graphics.Rendering.OpenGL+import Graphics.UI.GLFW as GLFW+import FRP.Elerea.Param+import Data.Default++-------------------+-- Local Imports --+import FRP.Spice.Math.Vector++-- Getting the external for the mouse position+externals :: IO (Signal (Vector Float), Vector Float -> IO ())+externals = external def++-- Getting the signal from the external+signals :: (Signal (Vector Float), Vector Float -> IO ()) -> Signal (Vector Float)+signals = fst++-- Getting the signal from the external+sinks :: (Signal (Vector Float), Vector Float -> IO ()) -> Vector Float -> IO ()+sinks = snd
+ src/FRP/Spice/Math/Vector.hs view
@@ -0,0 +1,35 @@+module FRP.Spice.Math.Vector where++--------------------+-- Global Imports --+import Data.Default+import Data.Monoid++----------+-- Code --++-- The vector datatype+data Vector a = Vector a a++-- Default instance+instance Default a => Default (Vector a) where+ def = Vector def def++-- Show instance+instance Show a => Show (Vector a) where+ show (Vector x y) = mconcat ["Vector ", show x, " ", show y]++-- Num instance+instance Num a => Num (Vector a) where+ (Vector x1 y1) + (Vector x2 y2) = Vector (x1 + x2) (y1 + y2)+ (Vector x1 y1) * (Vector x2 y2) = Vector (x1 * x2) (y1 * y2)++ fromInteger n = Vector (fromInteger n) (fromInteger n)++ abs (Vector x y) = Vector (abs x) (abs y)+ signum (Vector x y) = Vector (signum x) (signum y)+ negate (Vector x y) = Vector (negate x) (negate y)++-- Functor instance+instance Functor Vector where+ fmap fn (Vector x y) = Vector (fn x) (fn y)