module Gamgine.Engine where
import Graphics.UI.GLFW (getTime)
import Control.Monad.State (MonadIO, liftIO)
import Control.Applicative ((<$>))
import Data.Maybe (fromMaybe)


mkUpdateLoop :: (MonadIO m) => Int -> Int -> m a -> (Double -> m (Double, Double))
mkUpdateLoop :: forall (m :: * -> *) a.
MonadIO m =>
Int -> Int -> m a -> Double -> m (Double, Double)
mkUpdateLoop Int
ticksPerSecond Int
maxFrameSkip m a
update = \Double
nextFrame -> Double -> Int -> m (Double, Double)
loop Double
nextFrame Int
0
   where
      loop :: Double -> Int -> m (Double, Double)
loop Double
nextFrame Int
skippedFrames = do
         Double
time <- IO Double -> m Double
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
nextFrame (Maybe Double -> Double) -> IO (Maybe Double) -> IO Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO (Maybe Double)
getTime)
         if Double
time Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
nextFrame Bool -> Bool -> Bool
&& Int
skippedFrames Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
maxFrameSkip
            then do
               m a
update
               Double -> Int -> m (Double, Double)
loop (Double
nextFrame Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
skipTicks) (Int
skippedFrames Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
            else do
               let interpol :: Double
interpol = Double -> Double -> Double -> Double
forall {a}. Fractional a => a -> a -> a -> a
interpolation Double
time Double
nextFrame Double
skipTicks
               (Double, Double) -> m (Double, Double)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
nextFrame, Double
interpol)

      interpolation :: a -> a -> a -> a
interpolation a
time a
nextFrame a
skipTicks =
         (a
time a -> a -> a
forall a. Num a => a -> a -> a
- a
skipTicks a -> a -> a
forall a. Num a => a -> a -> a
- a
nextFrame) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
skipTicks

      skipTicks :: Double
skipTicks = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ticksPerSecond :: Double)