2016-10-31 22:47:16 +00:00
|
|
|
{-# LANGUAGE RecordWildCards #-}
|
2017-02-23 23:18:29 +00:00
|
|
|
{-# LANGUAGE BangPatterns #-}
|
2020-05-03 23:36:12 +00:00
|
|
|
{-# LANGUAGE ExplicitForAll #-}
|
|
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
|
|
{-# LANGUAGE RankNTypes #-}
|
2020-05-04 03:17:44 +00:00
|
|
|
{-# LANGUAGE TypeApplications #-}
|
2016-03-25 08:41:22 +00:00
|
|
|
module Affection
|
2016-10-31 22:47:16 +00:00
|
|
|
( withAffection
|
2017-09-09 14:47:24 +00:00
|
|
|
, get
|
2017-11-04 17:35:09 +00:00
|
|
|
, put
|
2018-01-12 21:08:23 +00:00
|
|
|
, liftIO
|
2016-12-08 17:22:29 +00:00
|
|
|
, module A
|
2016-03-25 08:41:22 +00:00
|
|
|
) where
|
|
|
|
|
2017-10-03 10:47:18 +00:00
|
|
|
import SDL (($=))
|
2016-10-31 22:47:16 +00:00
|
|
|
import qualified SDL
|
2018-06-16 17:34:42 +00:00
|
|
|
import qualified SDL.Raw.Video as SDL (glSetAttribute)
|
|
|
|
import qualified SDL.Raw.Enum as SDL
|
2016-10-31 22:47:16 +00:00
|
|
|
|
2016-11-02 00:14:53 +00:00
|
|
|
import System.Clock
|
2016-10-31 22:47:16 +00:00
|
|
|
|
|
|
|
import Control.Monad.Loops
|
2018-06-03 00:41:49 +00:00
|
|
|
import Control.Monad.State.Strict
|
2018-01-12 21:08:23 +00:00
|
|
|
import Control.Monad.IO.Class (liftIO)
|
2016-03-25 10:43:31 +00:00
|
|
|
|
2016-12-11 16:38:03 +00:00
|
|
|
import Foreign.C.Types (CInt(..))
|
|
|
|
|
2016-12-08 17:22:29 +00:00
|
|
|
import Affection.Types as A
|
2020-05-03 23:36:12 +00:00
|
|
|
import Affection.Class as A
|
2017-03-05 15:39:37 +00:00
|
|
|
import Affection.StateMachine as A
|
2017-09-07 04:23:01 +00:00
|
|
|
import Affection.Util as A
|
2017-11-27 01:18:23 +00:00
|
|
|
import Affection.MessageBus as A
|
2017-12-13 14:19:53 +00:00
|
|
|
import Affection.Subsystems as A
|
|
|
|
|
|
|
|
import Affection.Logging as A
|
2016-03-25 15:58:46 +00:00
|
|
|
|
2018-03-27 21:23:13 +00:00
|
|
|
import qualified Graphics.Rendering.OpenGL as GL (clear, flush, ClearBuffer(..))
|
2017-09-09 14:47:24 +00:00
|
|
|
|
2016-12-11 16:38:03 +00:00
|
|
|
|
2016-11-06 04:02:06 +00:00
|
|
|
-- | Main function which bootstraps everything else.
|
|
|
|
withAffection
|
2020-05-04 03:17:44 +00:00
|
|
|
:: forall us. (Affectionate us)
|
2020-05-03 23:36:12 +00:00
|
|
|
=> AffectionConfig us -- ^ Configuration of the Game and its engine.
|
2016-11-06 04:02:06 +00:00
|
|
|
-> IO ()
|
2016-11-08 04:15:44 +00:00
|
|
|
withAffection AffectionConfig{..} = do
|
2017-12-19 20:53:47 +00:00
|
|
|
liftIO $ logIO Debug "Affection starting"
|
|
|
|
liftIO $ logIO Debug "Initializing SDL"
|
2017-02-23 21:54:26 +00:00
|
|
|
-- intialiaze SDL
|
2016-10-31 22:47:16 +00:00
|
|
|
case initComponents of
|
|
|
|
All ->
|
|
|
|
SDL.initializeAll
|
|
|
|
Only is ->
|
|
|
|
SDL.initialize is
|
2017-02-23 21:54:26 +00:00
|
|
|
-- give SDL render quality
|
|
|
|
SDL.HintRenderScaleQuality SDL.$= SDL.ScaleLinear
|
|
|
|
-- just checking…
|
|
|
|
do
|
|
|
|
renderQuality <- SDL.get SDL.HintRenderScaleQuality
|
|
|
|
when (renderQuality /= SDL.ScaleLinear) $
|
2017-12-13 14:19:53 +00:00
|
|
|
logIO Warn "Linear texture filtering not enabled!"
|
2017-02-23 21:54:26 +00:00
|
|
|
-- construct window
|
2019-01-30 11:00:28 +00:00
|
|
|
liftIO $ logIO Debug "Creating Window(s)"
|
2020-05-03 23:36:12 +00:00
|
|
|
windows <- zip3 (map (\(x,_,_) -> x) windowConfigs) <$>
|
2019-01-30 11:00:28 +00:00
|
|
|
mapM
|
2020-05-03 23:36:12 +00:00
|
|
|
(\wc -> SDL.createWindow windowTitle ((\(_,y,_) -> y) wc))
|
|
|
|
windowConfigs <*>
|
|
|
|
pure (map (\(_,_,z) -> z) windowConfigs)
|
|
|
|
|
|
|
|
mapM_ (SDL.showWindow . (\(_,y,_) -> y)) windows
|
2018-06-16 17:34:42 +00:00
|
|
|
_ <- SDL.glSetAttribute SDL.SDL_GL_SHARE_WITH_CURRENT_CONTEXT 1
|
2020-05-03 23:36:12 +00:00
|
|
|
contexts <- zip (map (\(x,_,_) -> x) windows) <$>
|
|
|
|
mapM (SDL.glCreateContext . (\(_,y,_) -> y)) windows
|
2019-01-30 11:00:28 +00:00
|
|
|
-- let SDL.V2 (CInt rw) (CInt rh) = SDL.windowInitialSize windowConfigs
|
|
|
|
-- (w, h) = case canvasSize of
|
|
|
|
-- Just (cw, ch) -> (cw, ch)
|
|
|
|
-- Nothing -> (fromIntegral rw, fromIntegral rh)
|
2020-05-03 23:36:12 +00:00
|
|
|
mapM_ (\w -> flip SDL.setWindowMode ((\(_,_,z) -> z) w) ((\(_,y,_) -> y) w)) windows
|
2018-09-25 05:02:33 +00:00
|
|
|
-- SDL.swapInterval $= SDL.SynchronizedUpdates -- <- causes Problems with windows
|
2017-12-19 20:53:47 +00:00
|
|
|
liftIO $ logIO Debug "Getting Time"
|
2017-11-27 01:18:23 +00:00
|
|
|
-- get current time
|
2017-07-29 00:40:41 +00:00
|
|
|
execTime <- getTime Monotonic
|
2017-12-19 20:53:47 +00:00
|
|
|
liftIO $ logIO Debug "Loading initial data container"
|
2020-05-04 03:26:49 +00:00
|
|
|
-- construct game data object from provided Affectionate instance
|
2020-05-04 03:17:44 +00:00
|
|
|
gameData <- loadState @us
|
2020-05-04 03:26:49 +00:00
|
|
|
-- build state container
|
2020-05-03 23:36:12 +00:00
|
|
|
let initContainer = AffectionData
|
|
|
|
{ drawWindows = windows
|
|
|
|
, glContext = contexts
|
|
|
|
, elapsedTime = 0
|
|
|
|
, deltaTime = 0
|
|
|
|
, sysTime = execTime
|
|
|
|
, pausedTime = False
|
|
|
|
}
|
2020-05-04 03:26:49 +00:00
|
|
|
-- initialize and run state
|
|
|
|
(_, nState) <- runStateT
|
|
|
|
(A.runState
|
2016-11-04 15:06:16 +00:00
|
|
|
(do
|
2020-05-04 03:26:49 +00:00
|
|
|
liftIO $ logIO Debug "Starting Loop"
|
|
|
|
-- run preLoop function from Affectionate
|
|
|
|
preLoop gameData
|
|
|
|
whileM_ (hasNextStep gameData)
|
|
|
|
(do
|
|
|
|
-- get state
|
|
|
|
ad <- get
|
|
|
|
-- Measure time difference form last run
|
|
|
|
now <- liftIO $ getTime Monotonic
|
|
|
|
let lastTime = sysTime ad
|
|
|
|
-- compute dt and update elapsedTime
|
|
|
|
let !dt = fromIntegral
|
|
|
|
(toNanoSecs $ diffTimeSpec lastTime now) / (10 ^ (9 :: Int))
|
|
|
|
!ne = elapsedTime ad + dt
|
|
|
|
-- update state data object with new time values
|
|
|
|
put $ ad
|
|
|
|
{ elapsedTime = ne
|
|
|
|
, deltaTime = dt
|
|
|
|
}
|
|
|
|
-- poll events
|
|
|
|
evs <- preHandleEvents =<< liftIO SDL.pollEvents
|
|
|
|
-- handle events
|
|
|
|
handleEvents gameData evs
|
|
|
|
-- execute user defined update loop
|
|
|
|
unless (pausedTime ad) (update gameData dt)
|
|
|
|
-- clear GL buffer >> execute user defined draw loop >> flush GL buffer
|
|
|
|
liftIO $ GL.clear [GL.ColorBuffer, GL.DepthBuffer, GL.StencilBuffer]
|
|
|
|
draw gameData
|
|
|
|
liftIO GL.flush
|
|
|
|
-- actual displaying of newly drawn frame
|
|
|
|
mapM_ (SDL.glSwapWindow . (\(_,y,_) -> y)) windows
|
|
|
|
-- -- save new time
|
|
|
|
-- ad3 <- get
|
|
|
|
-- when (sysTime ad == sysTime ad3) (
|
|
|
|
-- put ad3
|
|
|
|
-- { sysTime = now
|
|
|
|
-- }
|
|
|
|
-- )
|
|
|
|
)
|
|
|
|
)
|
|
|
|
) initContainer
|
2017-12-19 20:53:47 +00:00
|
|
|
liftIO $ logIO Debug "Loop ended. Cleaning"
|
2020-05-03 23:36:12 +00:00
|
|
|
cleanUp gameData
|
2017-12-19 20:53:47 +00:00
|
|
|
liftIO $ logIO Debug "Destroying Window"
|
2019-01-30 11:00:28 +00:00
|
|
|
mapM_ (SDL.glDeleteContext . snd) contexts
|
2020-05-03 23:36:12 +00:00
|
|
|
mapM_ (SDL.destroyWindow . (\(_,y,_) -> y)) windows
|
2018-09-25 05:02:33 +00:00
|
|
|
-- SDL.quit -- <- This causes segfaults depending on hardware
|
2017-12-19 20:53:47 +00:00
|
|
|
liftIO $ logIO Debug "This is the end"
|