packages feed

free-game 1.1.9 → 1.1.78

raw patch · 15 files changed

+73/−268 lines, 15 filesdep −StateVardep ~JuicyPixels-utildep ~OpenGLdep ~OpenGLRaw

Dependencies removed: StateVar

Dependency ranges changed: JuicyPixels-util, OpenGL, OpenGLRaw, colors, mtl, reflection

Files

CHANGELOG.md view
@@ -1,25 +1,13 @@-1.1.80
----------------------------------------------------------------------
-* Added `mouseScroll`
-* Fixed the malfunction of FPS management
-
-1.1.79
----------------------------------------------------------------------
-* Exported `clipBitmap`
-
-1.1.78
-* Added `mouseInWindow`
-
 1.1
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 * Use Box instead of drab BoundingBox
 
 1.0.5
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 * No fundamental changes
 
 1.0.4
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 
 * Fixed some potential bugs that appeared on 7.8.1 RC2
 * Added `getBoundingBox` and `setBoundingBox` which accesses the window size and the region to draw.
@@ -27,7 +15,7 @@ * Demoted the precedence of `thickness` and `blendMode` according to other APIs.
 
 1.0.3
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 * Added `runGameDefault` as an alternative of classic `runGame def`.
 * Removed the duplicate instance of `MonadIO`.
 * `free-game` no longer depends on ominous `repa`.
@@ -38,18 +26,18 @@ * Make the window size solid.
 
 1.0.2
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 * Supported changing a blend function. `blendMode mode m` changes the blend mode while `m` is running.
 * Fixed fatal 'keyPress'-related bugs.
 * Special thanks: [@myuon_myon](https://twitter.com/myuon_myon)
 * Re-added `keyChar` and `keySpecial`.
 
 1.0.1
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 * Demoted the precedence of `Affine` APIs to 5.
 
 1.0
--------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------
 * Supported free-4.4.
 * Supported GLFW-b-1.3.
 * Use `Double` instead of `Float`.
FreeGame.hs view
@@ -35,14 +35,12 @@     globalize,
     localize,
     -- * Pictures
-    Drawable,
     Picture2D(..),
     BlendMode(..),
     Bitmap,
     bitmapSize,
     readBitmap,
     cropBitmap,
-    clipBitmap,
     loadBitmaps,
     loadBitmapsWith,
     writeBitmap,
@@ -59,7 +57,6 @@     keyDown,
     -- * Mouse
     Mouse(),
-    mouseScroll,
     mouseInWindow,
     mousePositionMay,
     mousePosition,
FreeGame/Backend/GLFW.hs view
@@ -67,17 +67,15 @@     keyBuffer <- newIORef initialKeyBuffer
     mouseBuffer <- newIORef initialMouseBuffer
     mouseIn <- newIORef True
-    scroll <- newIORef (V2 0 0)
     GLFW.setKeyCallback (G.theWindow sys) $ Just $ keyCallback keyBuffer
     GLFW.setMouseButtonCallback (G.theWindow sys) $ Just $ mouseButtonCallback mouseBuffer
     GLFW.setCursorEnterCallback (G.theWindow sys) $ Just $ mouseEnterCallback mouseIn
-    GLFW.setScrollCallback (G.theWindow sys) $ Just $ \_ x y -> modifyIORef scroll (+V2 x y)
+
     execFinalizerT
         $ give (RefKeyStates keyBuffer)
         $ give (RefMouseButtonStates mouseBuffer)
         $ give (RefMouseInWindow mouseIn)
         $ give (TextureStorage texs)
-        $ give scroll
         $ give sys
         $ gameLoop m
 
@@ -87,7 +85,6 @@     , Given KeyStates
     , Given MouseButtonStates
     , Given MouseInWindow
-    , Given (IORef (V2 Double))
     ) => IterT (F UI) a -> FinalizerT IO (Maybe a)
 gameLoop m = do
     liftIO $ G.beginFrame given
@@ -99,7 +96,6 @@     b <- liftIO $ do
         modifyIORef' (getKeyStates given) (Map.map buttonStay)
         modifyIORef' (getMouseButtonStates given) (Map.map buttonStay)
-        writeIORef given (V2 0 0 :: V2 Double)
         G.endFrame given
     liftIO (readIORef fs) >>= finalizer . sequence_
 
@@ -123,7 +119,6 @@     , Given MouseButtonStates
     , Given MouseInWindow
     , Given (IORef [IO ()])
-    , Given (IORef (V2 Double))
     ) => UI (FinalizerT IO a) -> FinalizerT IO a
 runUI (Draw m) = do
     (cont, xs) <- liftIO $ do
@@ -145,10 +140,10 @@     cont
 runUI (KeyStates cont) = liftIO (readIORef $ getKeyStates given) >>= cont
 runUI (MouseButtons cont) = liftIO (readIORef $ getMouseButtonStates given) >>= cont
+-- runUI _ _ (MouseWheel cont) = GLFW.getMouseWheel >>= cont
 runUI (MousePosition cont) = do
     (x, y) <- liftIO $ GLFW.getCursorPos (G.theWindow given)
     cont $ V2 x y
-runUI (MouseScroll cont) = liftIO (readIORef given) >>= cont
 runUI (MouseInWindow cont) = liftIO (readIORef $ getMouseInWindow given) >>= cont
 runUI (Bracket m) = join $ iterM runUI m
 runUI (TakeScreenshot cont) = liftIO (G.screenshot given >>= liftBitmapIO) >>= cont
FreeGame/Class.hs view
@@ -8,14 +8,12 @@ -- Maintainer  :  Fumiaki Kinoshita <fumiexcel@gmail.com>
 -- Stability   :  provisional
 -- Portability :  non-portable
---
+-- 
 ----------------------------------------------------------------------------
 module FreeGame.Class where
 
 import Linear
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 import Unsafe.Coerce
 import FreeGame.Types
 import FreeGame.Data.Bitmap
@@ -56,7 +54,7 @@     circle :: Double -> p ()
     circleOutline :: Double -> p ()
     thickness :: Float -> p a -> p a
-    color :: Color Float -> p a -> p a
+    color :: Color -> p a -> p a
     blendMode :: BlendMode -> p a -> p a
 
 class Affine p => Local p where
@@ -146,7 +144,6 @@     globalMousePosition :: f Vec2
     mouseButtons_ :: f (Map.Map Int ButtonState)
     mouseInWindow :: f Bool
-    mouseScroll :: f Vec2
 
 -- | Returns the relative coordinate of the cursor.
 mousePosition :: (Applicative f, Mouse f, Local f) => f Vec2
FreeGame/Data/Bitmap.hs view
@@ -22,9 +22,9 @@ 
     -- * Bitmap operations
     ,cropBitmap
-    ,clipBitmap
     -- * V2
     ,sizeBitmap
+    ,clipBitmap
     ) where
 
 import qualified Codec.Picture as C
@@ -33,12 +33,10 @@ import Data.BoundingBox
 import Linear.V2
 import System.Random
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 import Data.Hashable
 
-data Bitmap = Bitmap { bitmapImage :: C.Image C.PixelRGBA8, bitmapHash :: Int }
+data Bitmap = Bitmap (C.Image C.PixelRGBA8) Int
 
 -- | Get the size of the 'Bitmap'.
 bitmapSize :: Bitmap -> (Int, Int)
FreeGame/Data/Font.hs view
@@ -10,7 +10,7 @@ --
 -- Rendering characters
 ----------------------------------------------------------------------------
-module FreeGame.Data.Font
+module FreeGame.Data.Font 
   ( Font
   , loadFontFromFile
   , loadFont
@@ -21,9 +21,7 @@   , RenderedChar(..)
   ) where
 
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 import Control.Monad.IO.Class
 import Control.Monad
 import Data.IORef
@@ -121,7 +119,7 @@     let dpi = fromIntegral resolutionDPI
 
     runFreeType $ ft_Set_Char_Size face 0 (floor $ siz * 64) dpi dpi
-
+    
     ix <- ft_Get_Char_Index face (fromIntegral $ fromEnum ch)
     runFreeType $ ft_Load_Glyph face ix ft_LOAD_DEFAULT
 
@@ -134,7 +132,7 @@ 
     let h = fromIntegral $ B.rows bmp
         w = fromIntegral $ B.width bmp
-
+    
     fptr <- newForeignPtr_ $ castPtr $ buffer bmp
 
     adv <- peek $ GS.advance slot
FreeGame/Instances.hs view
@@ -9,11 +9,7 @@ import Control.Monad.Trans.Cont
 import Control.Monad.Trans.Maybe
 import Control.Monad.Trans.List
-#if MIN_VERSION_transformers(0,4,0)
-import Control.Monad.Trans.Except
-#else
 import Control.Monad.Trans.Error
-#endif
 import Control.Monad.Trans.Identity
 import qualified Control.Monad.State.Lazy as Lazy
 import qualified Control.Monad.State.Strict as Strict
@@ -21,9 +17,7 @@ import qualified Control.Monad.Writer.Strict as Strict
 import qualified Control.Monad.Trans.RWS.Strict as Strict
 import qualified Control.Monad.Trans.RWS.Lazy as Lazy
-#if !MIN_VERSION_base(4,8,0)
 import Data.Monoid
-#endif
 import Control.Monad.Free.Church as Church
 import Control.Monad.Free as Free
 import FreeGame.Class
@@ -69,7 +63,6 @@     globalMousePosition = (l) globalMousePosition; \
     mouseButtons_ = (l) mouseButtons_; \
     mouseInWindow = (l) mouseInWindow; \
-    mouseScroll = (l) mouseScroll; \
     }
 
 #define MK_FROM_FINALIZER(cxt, ty, l) instance (FromFinalizer m cxt) => FromFinalizer (ty) where { \
@@ -91,25 +84,21 @@     setBoundingBox b = (l) (setBoundingBox b); \
     }
 
-MK_AFFINE(, F m, hoistF)
-MK_AFFINE(, Free.Free m, Free.hoistFree)
+MK_AFFINE(_COMMA_ Functor m, F m, hoistF)
+MK_AFFINE(_COMMA_ Functor m, Free.Free m, Free.hoistFree)
 MK_AFFINE(_COMMA_ Monad m, IterT m, hoistIterT)
-MK_AFFINE(, ReaderT r m, mapReaderT)
-MK_AFFINE(, Lazy.StateT s m, Lazy.mapStateT)
-MK_AFFINE(, Strict.StateT s m, Strict.mapStateT)
-MK_AFFINE(, Lazy.WriterT w m, Lazy.mapWriterT)
-MK_AFFINE(, Strict.WriterT w m, Strict.mapWriterT)
-MK_AFFINE(, Lazy.RWST r w s m, Lazy.mapRWST)
-MK_AFFINE(, Strict.RWST r w s m, Strict.mapRWST)
-MK_AFFINE(, IdentityT m, mapIdentityT)
-MK_AFFINE(, MaybeT m, mapMaybeT)
-MK_AFFINE(, ListT m, mapListT)
-#if MIN_VERSION_transformers(0,4,0)
-MK_AFFINE(, ExceptT e m, mapExceptT)
-#else
-MK_AFFINE(_COMMA_ Error e, ErrorT e m, mapErrorT)
-#endif
-MK_AFFINE(, ContT r m, mapContT)
+MK_AFFINE(_COMMA_ Monad m, ReaderT r m, mapReaderT)
+MK_AFFINE(_COMMA_ Monad m, Lazy.StateT s m, Lazy.mapStateT)
+MK_AFFINE(_COMMA_ Monad m, Strict.StateT s m, Strict.mapStateT)
+MK_AFFINE(_COMMA_ Monad m _COMMA_ Monoid w, Lazy.WriterT w m, Lazy.mapWriterT)
+MK_AFFINE(_COMMA_ Monad m _COMMA_ Monoid w, Strict.WriterT w m, Strict.mapWriterT)
+MK_AFFINE(_COMMA_ Monad m _COMMA_ Monoid w, Lazy.RWST r w s m, Lazy.mapRWST)
+MK_AFFINE(_COMMA_ Monad m _COMMA_ Monoid w, Strict.RWST r w s m, Strict.mapRWST)
+MK_AFFINE(_COMMA_ Monad m, IdentityT m, mapIdentityT)
+MK_AFFINE(_COMMA_ Monad m, MaybeT m, mapMaybeT)
+MK_AFFINE(_COMMA_ Monad m, ListT m, mapListT)
+MK_AFFINE(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, mapErrorT)
+MK_AFFINE(_COMMA_ Monad m, ContT r m, mapContT)
 
 MK_PICTURE_2D(_COMMA_ Functor m, F m, Church.liftF, hoistF)
 MK_PICTURE_2D(_COMMA_ Functor m, Free.Free m, Free.liftF, Free.hoistFree)
@@ -124,11 +113,7 @@ MK_PICTURE_2D(_COMMA_ Monad m, IdentityT m, lift, mapIdentityT)
 MK_PICTURE_2D(_COMMA_ Monad m, MaybeT m, lift, mapMaybeT)
 MK_PICTURE_2D(_COMMA_ Monad m, ListT m, lift, mapListT)
-#if MIN_VERSION_transformers(0,4,0)
-MK_PICTURE_2D(_COMMA_ Monad m, ExceptT e m, lift, mapExceptT)
-#else
 MK_PICTURE_2D(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, lift, mapErrorT)
-#endif
 MK_PICTURE_2D(_COMMA_ Monad m, ContT r m, lift, mapContT)
 
 MK_LOCAL(_COMMA_ Functor m, F m, Church.liftF)
@@ -144,11 +129,7 @@ MK_LOCAL(_COMMA_ Monad m, IdentityT m, lift)
 MK_LOCAL(_COMMA_ Monad m, MaybeT m, lift)
 MK_LOCAL(_COMMA_ Monad m, ListT m, lift)
-#if MIN_VERSION_transformers(0,4,0)
-MK_LOCAL(_COMMA_ Monad m, ExceptT e m, lift)
-#else
 MK_LOCAL(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, lift)
-#endif
 MK_LOCAL(_COMMA_ Monad m, ContT r m, lift)
 
 MK_KEYBOARD(_COMMA_ Functor m, F m, Church.liftF)
@@ -164,11 +145,7 @@ MK_KEYBOARD(_COMMA_ Monad m, IdentityT m, lift)
 MK_KEYBOARD(_COMMA_ Monad m, MaybeT m, lift)
 MK_KEYBOARD(_COMMA_ Monad m, ListT m, lift)
-#if MIN_VERSION_transformers(0,4,0)
-MK_KEYBOARD(_COMMA_ Monad m, ExceptT e m, lift)
-#else
 MK_KEYBOARD(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, lift)
-#endif
 MK_KEYBOARD(_COMMA_ Monad m, ContT r m, lift)
 
 MK_MOUSE(_COMMA_ Functor m, F m, liftF)
@@ -184,11 +161,7 @@ MK_MOUSE(_COMMA_ Monad m, IdentityT m, lift)
 MK_MOUSE(_COMMA_ Monad m, MaybeT m, lift)
 MK_MOUSE(_COMMA_ Monad m, ListT m, lift)
-#if MIN_VERSION_transformers(0,4,0)
-MK_MOUSE(_COMMA_ Monad m, ExceptT e m, lift)
-#else
 MK_MOUSE(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, lift)
-#endif
 MK_MOUSE(_COMMA_ Monad m, ContT r m, lift)
 
 MK_FROM_FINALIZER(_COMMA_ Functor m, F m, liftF)
@@ -203,11 +176,7 @@ MK_FROM_FINALIZER(_COMMA_ Monad m, IdentityT m, lift)
 MK_FROM_FINALIZER(_COMMA_ Monad m, MaybeT m, lift)
 MK_FROM_FINALIZER(_COMMA_ Monad m, ListT m, lift)
-#if MIN_VERSION_transformers(0,4,0)
-MK_FROM_FINALIZER(_COMMA_ Monad m, ExceptT e m, lift)
-#else
 MK_FROM_FINALIZER(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, lift)
-#endif
 MK_FROM_FINALIZER(_COMMA_ Monad m, ContT r m, lift)
 
 MK_FREE_GAME(_COMMA_ Functor m, F m, liftF)
@@ -222,9 +191,5 @@ MK_FREE_GAME(_COMMA_ Monad m, IdentityT m, lift)
 MK_FREE_GAME(_COMMA_ Monad m, MaybeT m, lift)
 MK_FREE_GAME(_COMMA_ Monad m, ListT m, lift)
-#if MIN_VERSION_transformers(0,4,0)
-MK_FREE_GAME(_COMMA_ Monad m, ExceptT e m, lift)
-#else
 MK_FREE_GAME(_COMMA_ Monad m _COMMA_ Error e, ErrorT e m, lift)
-#endif
-MK_FREE_GAME(_COMMA_ Monad m, ContT r m, lift)
+MK_FREE_GAME(_COMMA_ Monad m, ContT r m, lift)
FreeGame/Internal/Finalizer.hs view
@@ -3,9 +3,7 @@ 
 import Control.Monad.IO.Class
 import Control.Monad.Trans
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 
 -- | An action with explicit releasing action.
 newtype FinalizerT m a = FinalizerT
FreeGame/Internal/GLFW.hs view
@@ -2,17 +2,15 @@ module FreeGame.Internal.GLFW where
 import Control.Concurrent
 import Control.Bool
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 import Control.Monad.IO.Class
 import Control.Lens
 import Data.Color
 import Data.IORef
 import FreeGame.Types
 import Data.BoundingBox
-import Data.StateVar
-import Graphics.GL.Compatibility30
+import Graphics.Rendering.OpenGL.GL.StateVar
+import Graphics.Rendering.OpenGL.Raw.ARB.Compatibility
 import Linear
 import qualified Graphics.Rendering.OpenGL.GL as GL
 import qualified Graphics.UI.GLFW as GLFW
@@ -22,26 +20,16 @@ import Codec.Picture
 import Codec.Picture.RGBA8
 import qualified GHC.IO.Encoding as Encoding
-import qualified Data.Sequence as S
-import qualified Data.Foldable as F
+
 data System = System
     { refFrameCounter :: IORef Int
-    , theFPS :: IORef Double
-    , frameTimes :: IORef (S.Seq Double)
+    , refFPS :: IORef Int
+    , theFPS :: IORef Int
     , currentFPS :: IORef Int
-    , startTime :: IORef Double
     , refRegion :: IORef BoundingBox2
     , theWindow :: GLFW.Window
     }
 
-trim1 :: S.Seq Double -> S.Seq Double
-trim1 s0 = go zs s0 (sum zs) where
-    go (x:xs) s a
-        | a < 1 = s
-        | otherwise = go xs (S.drop 1 s) (a - x)
-    go [] s _ = s
-    zs = F.toList s0
-
 type Texture = (GL.TextureObject, Double, Double)
 
 runVertices :: MonadIO m => [V2 Double] -> m ()
@@ -111,7 +99,7 @@     let s = 2 * pi / 64
     GL.renderPrimitive GL.LineLoop $ runVertices [V2 (cos t * r) (sin t * r) | t <- [0,s..2 * pi]]
 
-color :: Color Float -> IO a -> IO a
+color :: Color -> IO a -> IO a
 color col m = do
     oldColor <- liftIO $ get GL.currentColor
     liftIO $ GL.currentColor $= unsafeCoerce col
@@ -158,8 +146,6 @@     GL.ortho wl wr wb wt 0 (-100)
     GL.matrixMode $= GL.Modelview 0
     GL.clear [GL.ColorBuffer]
-    Just t <- GLFW.getTime
-    writeIORef (startTime sys) t
 
 endFrame :: System -> IO Bool
 endFrame sys = do
@@ -168,14 +154,10 @@     Just t <- GLFW.getTime
     n <- readIORef (refFrameCounter sys)
     fps <- readIORef (theFPS sys)
-    threadDelay $ max 0 $ floor $ (1000000 *) $ fromIntegral n / fps - t
-    writeIORef (refFrameCounter sys) (succ n)
-    t0 <- readIORef (startTime sys)
-    fs <- readIORef (frameTimes sys)
-    Just t1 <- GLFW.getTime
-    let !fs' = trim1 $ fs S.|> (t1 - t0)
-    writeIORef (currentFPS sys) (S.length fs')
-    writeIORef (frameTimes sys) fs'
+    threadDelay $ max 0 $ floor $ (1000000 *) $ fromIntegral n / fromIntegral fps - t
+    if t > 1
+        then GLFW.setTime 0 >> writeIORef (currentFPS sys) n >> writeIORef (refFrameCounter sys) 0
+        else writeIORef (refFrameCounter sys) (succ n)
     GLFW.windowShouldClose (theWindow sys)
 
 withGLFW :: WindowMode -> BoundingBox2 -> (System -> IO a) -> IO a
@@ -209,10 +191,9 @@ 
     sys <- System
         <$> newIORef 0
+        <*> newIORef 0
         <*> newIORef 60
-        <*> newIORef S.empty
         <*> newIORef 60
-        <*> newIORef 0
         <*> pure rbox
         <*> pure win
 
@@ -249,4 +230,4 @@     GL.blendFunc $= blendMode2BlendingFactors mode
     a <- m
     GL.blendFunc $= oldFunc
-    return a
+    return a
FreeGame/UI.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DeriveFunctor, ExistentialQuantification, Rank2Types, UndecidableInstances #-}
+{-# LANGUAGE DeriveFunctor, ExistentialQuantification, Rank2Types #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  FreeGame.UI
@@ -12,7 +12,6 @@ ----------------------------------------------------------------------------
 module FreeGame.UI (
     UI(..)
-    , Drawable
     , reUI
     , reFrame
     , reGame
@@ -24,36 +23,30 @@ import FreeGame.Class
 import FreeGame.Internal.Finalizer
 import FreeGame.Types
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 import qualified Data.Map as Map
 import FreeGame.Data.Bitmap (Bitmap)
 import Data.Color
+import Data.BoundingBox
 import Control.Monad.Free.Church (F, iterM)
 import Control.Monad.Trans.Iter (IterT, foldM)
 import Control.Monad (join)
 
-class (Applicative f, Monad f, Picture2D f, Local f) => Drawable f where { }
-
-instance (Applicative f, Monad f, Picture2D f, Local f) => Drawable f where { }
-
 data UI a =
-    Draw (forall m. Drawable m => m a)
+    Draw (forall m. (Applicative m, Monad m, Picture2D m, Local m) => m a)
     | PreloadBitmap Bitmap a
     | FromFinalizer (FinalizerT IO a)
     | KeyStates (Map.Map Key ButtonState -> a)
     | MouseButtons (Map.Map Int ButtonState -> a)
     | MousePosition (Vec2 -> a)
     | MouseInWindow (Bool -> a)
-    | MouseScroll (Vec2 -> a)
     | TakeScreenshot (Bitmap -> a)
     | Bracket (Frame a)
-    | SetFPS Double a
+    | SetFPS Int a
     | SetTitle String a
     | ShowCursor a
     | HideCursor a
-    | ClearColor (Color Float) a
+    | ClearColor Color a
     | GetFPS (Int -> a)
     | ForkFrame (Frame ()) a
     | GetBoundingBox (BoundingBox2 -> a)
@@ -84,7 +77,6 @@ reUI (MouseButtons cont) = cont <$> mouseButtons_
 reUI (MousePosition cont) = cont <$> globalMousePosition
 reUI (MouseInWindow cont) = cont <$> mouseInWindow
-reUI (MouseScroll cont) = cont <$> mouseScroll
 reUI (TakeScreenshot cont) = cont <$> takeScreenshot
 reUI (Bracket m) = bracket m
 reUI (SetFPS i cont) = cont <$ setFPS i
@@ -101,7 +93,7 @@ 
 class (Picture2D m, Local m, Keyboard m, Mouse m, FromFinalizer m) => FreeGame m where
     -- | Draw an action that consist of 'Picture2D''s methods.
-    draw :: (forall f. Drawable f => f a) -> m a
+    draw :: (forall f. (Applicative f, Monad f, Picture2D f, Local f) => f a) -> m a
     -- | Load a 'Bitmap' to avoid the cost of the first invocation of 'bitmap'.
     preloadBitmap :: Bitmap -> m ()
     -- | Run a 'Frame', and release all the matter happened.
@@ -111,22 +103,22 @@     -- | Generate a 'Bitmap' from the front buffer.
     takeScreenshot :: m Bitmap
     -- | Set the goal FPS.
-    setFPS :: Double -> m ()
+    setFPS :: Int -> m ()
     setTitle :: String -> m ()
     showCursor :: m ()
     hideCursor :: m ()
-    clearColor :: Color Float -> m ()
+    clearColor :: Color -> m ()
     -- | Get the actual FPS value.
     getFPS :: m Int
     getBoundingBox :: m BoundingBox2
     setBoundingBox :: BoundingBox2 -> m ()
-
+    
 instance FreeGame UI where
     draw = Draw
     {-# INLINE draw #-}
     preloadBitmap bmp = PreloadBitmap bmp ()
     {-# INLINE preloadBitmap #-}
-
+    
     bracket = Bracket
     {-# INLINE bracket #-}
     forkFrame m = ForkFrame m ()
@@ -140,7 +132,7 @@     getBoundingBox = GetBoundingBox id
     setBoundingBox s = SetBoundingBox s ()
 
-overDraw :: (forall m. Drawable m => m a -> m a) -> UI a -> UI a
+overDraw :: (forall m. (Applicative m, Monad m, Picture2D m, Local m) => m a -> m a) -> UI a -> UI a
 overDraw f (Draw m) = Draw (f m)
 overDraw _ x = x
 {-# INLINE overDraw #-}
@@ -186,5 +178,4 @@     globalMousePosition = MousePosition id
     -- mouseWheel = MouseWheel id
     mouseButtons_ = MouseButtons id
-    mouseInWindow = MouseInWindow id
-    mouseScroll = MouseScroll id
+    mouseInWindow = MouseInWindow id
FreeGame/Util.hs view
@@ -35,9 +35,7 @@     keySpecial
     ) where
 
-#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative
-#endif
 import Control.Monad
 import Control.Monad.Free.Class
 import Control.Monad.Trans.Iter
@@ -64,6 +62,7 @@ -- | An infinite loop that run 'tick' every frame after the given action.
 foreverTick :: (Monad f, MonadFree f m) => m a -> m any
 foreverTick m = let m' = foreverTick m in m >> wrap (return m')
+{-# WARNING foreverTick "In most cases, foreverFrame is good enough and fast." #-}
 
 -- | @foreverFrame :: Frame a -> Game any@
 foreverFrame :: (Monad f, Monad m, MonadTrans t, MonadFree f (t m)) => m a -> t m any
@@ -110,7 +109,7 @@ loadBitmapsWith getFullPath path = do
     loc <- (</>path) <$> takeDirectory <$> loc_filename <$> location
     paths <- runIO $ getFileList loc
-
+    
     sequence $ do
         p <- paths
         let name = pathToName p
@@ -189,4 +188,4 @@ 
 {-# DEPRECATED keySpecial "use keyPress instead" #-}
 keySpecial :: Keyboard f => Key -> f Bool
-keySpecial = keyPress
+keySpecial = keyPress
examples/demo.hs view
@@ -40,15 +40,15 @@ bitmapTest :: Bitmap -> Frame ()
 bitmapTest bmp = blendMode Add $ do
     
-    color (fromRGB 1 0 0) $ do
+    color (Color 1 0 0 1) $ do
         translate (V2 300 346) $ bitmap bmp -- 'bitmap' creates an action from the bitmap.
-    color (fromRGB 0 1 0) $ do
+    color (Color 0 1 0 1) $ do
         translate (V2 310 350) $ bitmap bmp -- 'bitmap' creates an action from the bitmap.
-    color (fromRGB 0 0 1) $ do
+    color (Color 0 0 1 1) $ do
         translate (V2 293 359) $ bitmap bmp -- 'bitmap' creates an action from the bitmap.
     
-mouseTest :: Font -> Frame ()
-mouseTest font = whenM mouseInWindow $ do
+mouseTest :: Frame ()
+mouseTest = whenM mouseInWindow $ do
     p <- mousePosition
     l <- mouseButtonL
     r <- mouseButtonR
@@ -58,9 +58,6 @@             (False, True) -> blue
             (True, True) -> blend 0.5 red blue
     translate p $ color col $ thickness 4 $ circleOutline 16
-    translate p $ color white $ do
-        r <- mouseScroll
-        text font 48 $ show r
 
 main = runGame Windowed (Box (V2 0 0) (V2 640 480)) $ do
     bmp <- readBitmap "bird.png"
@@ -77,7 +74,7 @@ 
         fontTest font
         translate (V2 240 240) $ do
-            mouseTest font
+            mouseTest
 
             fps <- getFPS
 
− examples/demo_stateful.hs
@@ -1,23 +0,0 @@-import FreeGame
-
-data StateData = StateData { _counter :: Int
-                           , _font :: Font
-                           }
-    
-loop :: StateData -> Game ()
-loop state = do
-    let fnt = _font state
-        cnt = 1 + _counter state
-        state' = state{_counter = cnt}
-
-    translate (V2 100 240) . color green . text fnt 15 $ show cnt
-    translate (V2 340 240) . rotateD (fromIntegral cnt) . color red $ text fnt 70 "Test"
-
-    key <- keyPress KeyEscape
-    unless key $ tick >> loop state'
-
-main = runGame Windowed (Box (V2 0 0) (V2 640 480)) $ do
-    font <- loadFont "VL-PGothic-Regular.ttf"
-    clearColor black
-    let state = StateData{_counter=0, _font=font}
-    loop state
− examples/fib.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}
-import FreeGame
-import Control.Lens
-import Control.Monad.State
-import Control.Monad.Trans.Maybe
-
-data Mode = Scroll Double | Dist Double
-
-data World = World
-    { _seq0 :: [Int]
-    , _seq1 :: [Int]
-    , _offset :: Vec2
-    , _target :: Int
-    , _mode :: Mode
-    -- visual
-    , _font :: Font
-    }
-makeLenses ''World
-
-fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
-
-speed = 1
-
-update :: StateT World Game ()
-update = do
-    s0 <- use seq0
-    s1 <- use seq1
-    ofs <- use offset
-    t <- use target
-    font <- use font
-    
-    let v = s0 !! t + s1 !! t
-    color black $ do
-      translate (V2 24 240) $ text font 24 "fibs"
-      translate (V2 24 280) $ text font 24 "tail fibs"
-      forM_ (zip [0..] s0) $ \(i, v) -> translate (ofs + V2 (i * 36) 240) $ text font 24 (show v)
-      forM_ (zip [0..] s1) $ \(i, v) -> translate (ofs + V2 (i * 36) 280) $ text font 24 (show v)
-    color blue $ line [V2 400 480, V2 400 0]
-    ph <- use mode
-    case ph of
-      Scroll ph
-        | ph > 0 -> do
-          mode .= Scroll (ph - 1)
-          
-          color black $ translate (V2 390 320) $ text font 24 (show v)
-          offset .= ofs - V2 speed 0
-        | otherwise -> mode .= Dist 0
-      Dist ph
-        | ph >= 1 -> do
-          seq0 .= s0 ++ [v]
-          seq1 .= s1 ++ [v]
-          mode .= Scroll 36
-          target += 1
-        | otherwise -> color black $ do
-          translate (p0 ^* (1 - ph) + V2 (390+36) 240 ^* ph) $ text font 24 (show v)
-          translate (p0 ^* (1 - ph) + V2 (390) 280 ^* ph) $ text font 24 (show v)
-          mode .= Dist (ph + 1/30)
-    color red $ translate (V2 24 120) $ text font 24 "Press ESC to exit"
-  where
-    p0 = V2 390 320
-
-mainLoop :: World -> Game ()
-mainLoop s = do
-  s' <- execStateT update s
-  tick
-  unlessM (keyDown KeyEscape) $ mainLoop s'
-
-main = runGameDefault $ do
-    font <- loadFont "VL-PGothic-Regular.ttf"
-    runMaybeT $ forever $ do
-      color red $ translate (V2 24 240) $ text font 24 "Press SPACE to start"
-      tick
-      () <- whenM (keyDown KeySpace) mzero
-      return ()
-    mainLoop $ World [1,1] [1] (V2 400 0) 0 (Scroll 36) font
free-game.cabal view
@@ -1,5 +1,5 @@ name:                free-game
-version:             1.1.9
+version:             1.1.78
 synopsis:            Create games for free
 description:
     free-game defines a monad that integrates features to create 2D games.
@@ -46,11 +46,11 @@     FreeGame.Util
 
   ghc-options: -Wall -fexcess-precision -O2
-  default-extensions: FlexibleContexts, FlexibleInstances, CPP
+  default-extensions: FlexibleContexts, FlexibleInstances
   build-depends:
     array >= 0.4,
     base == 4.*,
-    colors == 0.3.*,
+    colors == 0.1.*,
     containers >= 0.4,
     control-bool,
     directory >= 1.0,
@@ -60,17 +60,16 @@     GLFW-b >= 1.3 && <2,
     hashable >= 1.2,
     JuicyPixels,
-    JuicyPixels-util >=0.1.1 && < 0.3,
+    JuicyPixels-util == 0.1.*,
     linear >= 1.0 && < 2,
-    mtl >= 2.2 && <4,
-    OpenGL >= 3 && <4,
-    OpenGLRaw,
+    mtl >= 2.1,
+    OpenGL == 2.9.*,
+    OpenGLRaw == 1.4.*,
     random == 1.*,
-    reflection,
-    StateVar,
+    reflection == 1.*,
     template-haskell,
     transformers >= 0.3,
     vector >= 0.9 && <0.12,
     void >= 0.5,
     boundingboxes >= 0.2 && < 0.4,
-    lens >= 3.8 && < 5
+    lens >= 3.8 && < 5