packages feed

free-game 1.1.79 → 1.1.80

raw patch · 10 files changed

+136/−27 lines, 10 filesdep ~JuicyPixels-utildep ~mtl

Dependency ranges changed: JuicyPixels-util, mtl

Files

CHANGELOG.md view
@@ -1,13 +1,25 @@+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.
@@ -15,7 +27,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`.
@@ -26,18 +38,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
@@ -58,6 +58,7 @@     keyDown,
     -- * Mouse
     Mouse(),
+    mouseScroll,
     mouseInWindow,
     mousePositionMay,
     mousePosition,
FreeGame/Backend/GLFW.hs view
@@ -67,15 +67,17 @@     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
 
@@ -85,6 +87,7 @@     , 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
@@ -96,6 +99,7 @@     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_
 
@@ -119,6 +123,7 @@     , 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
@@ -140,10 +145,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
@@ -144,6 +144,7 @@     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/Instances.hs view
@@ -67,6 +67,7 @@     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 { \
FreeGame/Internal/GLFW.hs view
@@ -20,16 +20,26 @@ 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
-    , refFPS :: IORef Int
-    , theFPS :: IORef Int
+    , theFPS :: IORef Double
+    , frameTimes :: IORef (S.Seq Double)
     , 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 ()
@@ -146,6 +156,8 @@     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
@@ -154,10 +166,14 @@     Just t <- GLFW.getTime
     n <- readIORef (refFrameCounter sys)
     fps <- readIORef (theFPS sys)
-    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)
+    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'
     GLFW.windowShouldClose (theWindow sys)
 
 withGLFW :: WindowMode -> BoundingBox2 -> (System -> IO a) -> IO a
@@ -191,9 +207,10 @@ 
     sys <- System
         <$> newIORef 0
-        <*> newIORef 0
         <*> newIORef 60
+        <*> newIORef S.empty
         <*> newIORef 60
+        <*> newIORef 0
         <*> pure rbox
         <*> pure win
 
FreeGame/UI.hs view
@@ -40,9 +40,10 @@     | MouseButtons (Map.Map Int ButtonState -> a)
     | MousePosition (Vec2 -> a)
     | MouseInWindow (Bool -> a)
+    | MouseScroll (Vec2 -> a)
     | TakeScreenshot (Bitmap -> a)
     | Bracket (Frame a)
-    | SetFPS Int a
+    | SetFPS Double a
     | SetTitle String a
     | ShowCursor a
     | HideCursor a
@@ -77,6 +78,7 @@ 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
@@ -103,7 +105,7 @@     -- | Generate a 'Bitmap' from the front buffer.
     takeScreenshot :: m Bitmap
     -- | Set the goal FPS.
-    setFPS :: Int -> m ()
+    setFPS :: Double -> m ()
     setTitle :: String -> m ()
     showCursor :: m ()
     hideCursor :: m ()
@@ -178,4 +180,5 @@     globalMousePosition = MousePosition id
     -- mouseWheel = MouseWheel id
     mouseButtons_ = MouseButtons id
-    mouseInWindow = MouseInWindow id+    mouseInWindow = MouseInWindow id
+    mouseScroll = MouseScroll id
examples/demo.hs view
@@ -47,8 +47,8 @@     color (Color 0 0 1 1) $ do
         translate (V2 293 359) $ bitmap bmp -- 'bitmap' creates an action from the bitmap.
     
-mouseTest :: Frame ()
-mouseTest = whenM mouseInWindow $ do
+mouseTest :: Font -> Frame ()
+mouseTest font = whenM mouseInWindow $ do
     p <- mousePosition
     l <- mouseButtonL
     r <- mouseButtonR
@@ -58,7 +58,9 @@             (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"
     bmp' <- readBitmap "logo.png"
@@ -74,7 +76,7 @@ 
         fontTest font
         translate (V2 240 240) $ do
-            mouseTest
+            mouseTest font
 
             fps <- getFPS
 
+ examples/fib.hs view
@@ -0,0 +1,67 @@+{-# 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
+    }
+makeLenses ''World
+
+fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
+
+speed = 1
+
+update :: Font -> StateT World Game ()
+update font = do
+    s0 <- use seq0
+    s1 <- use seq1
+    ofs <- use offset
+    t <- use target
+    
+    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)
+  where
+    p0 = V2 390 320
+
+mainLoop :: Font -> World -> Game ()
+mainLoop font s = do
+  s' <- execStateT (update font) s
+  tick
+  mainLoop font s'
+
+main = runGameDefault $ do
+    font <- loadFont "VL-PGothic-Regular.ttf"
+    runMaybeT $ forever $ do {tick;()<-whenM (keyDown KeySpace) mzero; return ()}
+    mainLoop font $ World [1,1] [1] (V2 400 0) 0 (Scroll 36)
free-game.cabal view
@@ -1,5 +1,5 @@ name:                free-game
-version:             1.1.79
+version:             1.1.80
 synopsis:            Create games for free
 description:
     free-game defines a monad that integrates features to create 2D games.
@@ -60,9 +60,9 @@     GLFW-b >= 1.3 && <2,
     hashable >= 1.2,
     JuicyPixels,
-    JuicyPixels-util == 0.1.*,
+    JuicyPixels-util >=0.1.1 && < 0.3,
     linear >= 1.0 && < 2,
-    mtl >= 2.1 && <3,
+    mtl >= 2.2 && <3,
     OpenGL == 2.9.*,
     OpenGLRaw >= 1.3 && < 1.6,
     random == 1.*,