packages feed

animate 0.3.0 → 0.4.0

raw patch · 3 files changed

+56/−60 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Animate: data Animations key loc
- Animate: instance Data.Aeson.Types.FromJSON.FromJSON Animate.SpriteSheetInfo
- Animate: instance Data.Aeson.Types.ToJSON.ToJSON Animate.SpriteSheetInfo
- Animate: instance GHC.Classes.Eq Animate.FrameStep
- Animate: instance GHC.Classes.Eq Animate.SpriteSheetInfo
- Animate: instance GHC.Classes.Eq key => GHC.Classes.Eq (Animate.Position key)
- Animate: instance GHC.Classes.Eq loc => GHC.Classes.Eq (Animate.Animations key loc)
- Animate: instance GHC.Classes.Eq loc => GHC.Classes.Eq (Animate.Frame loc)
- Animate: instance GHC.Show.Show Animate.FrameStep
- Animate: instance GHC.Show.Show Animate.SpriteSheetInfo
- Animate: instance GHC.Show.Show key => GHC.Show.Show (Animate.Position key)
- Animate: instance GHC.Show.Show loc => GHC.Show.Show (Animate.Animations key loc)
- Animate: instance GHC.Show.Show loc => GHC.Show.Show (Animate.Frame loc)
- Animate: type DeltaSeconds = Seconds
- Animate: type Seconds = Float
+ Animate: Animations :: Vector (Vector (Frame loc delay)) -> Animations key loc delay
+ Animate: [$sel:fDelay:Frame] :: Frame loc delay -> delay
+ Animate: [$sel:fLocation:Frame] :: Frame loc delay -> loc
+ Animate: [$sel:pCounter:Position] :: Position key delay -> delay
+ Animate: [$sel:pFrameIndex:Position] :: Position key delay -> FrameIndex
+ Animate: [$sel:pKey:Position] :: Position key delay -> key
+ Animate: [$sel:pLoop:Position] :: Position key delay -> Loop
+ Animate: [$sel:scH:SpriteClip] :: SpriteClip -> Int
+ Animate: [$sel:scOffset:SpriteClip] :: SpriteClip -> Maybe (Int, Int)
+ Animate: [$sel:scW:SpriteClip] :: SpriteClip -> Int
+ Animate: [$sel:scX:SpriteClip] :: SpriteClip -> Int
+ Animate: [$sel:scY:SpriteClip] :: SpriteClip -> Int
+ Animate: [$sel:ssAnimations:SpriteSheet] :: SpriteSheet key img delay -> Animations key SpriteClip delay
+ Animate: [$sel:ssImage:SpriteSheet] :: SpriteSheet key img delay -> img
+ Animate: [$sel:ssiAlpha:SpriteSheetInfo] :: SpriteSheetInfo delay -> Maybe Color
+ Animate: [$sel:ssiAnimations:SpriteSheetInfo] :: SpriteSheetInfo delay -> Map Text [(FrameIndex, delay)]
+ Animate: [$sel:ssiClips:SpriteSheetInfo] :: SpriteSheetInfo delay -> [SpriteClip]
+ Animate: [$sel:ssiImage:SpriteSheetInfo] :: SpriteSheetInfo delay -> FilePath
+ Animate: [$sel:unAnimations:Animations] :: Animations key loc delay -> Vector (Vector (Frame loc delay))
+ Animate: instance (GHC.Classes.Eq delay, GHC.Classes.Eq key) => GHC.Classes.Eq (Animate.Position key delay)
+ Animate: instance (GHC.Classes.Eq delay, GHC.Classes.Eq loc) => GHC.Classes.Eq (Animate.Frame loc delay)
+ Animate: instance (GHC.Classes.Eq loc, GHC.Classes.Eq delay) => GHC.Classes.Eq (Animate.Animations key loc delay)
+ Animate: instance (GHC.Show.Show delay, GHC.Show.Show key) => GHC.Show.Show (Animate.Position key delay)
+ Animate: instance (GHC.Show.Show delay, GHC.Show.Show loc) => GHC.Show.Show (Animate.Frame loc delay)
+ Animate: instance (GHC.Show.Show loc, GHC.Show.Show delay) => GHC.Show.Show (Animate.Animations key loc delay)
+ Animate: instance Data.Aeson.Types.FromJSON.FromJSON delay => Data.Aeson.Types.FromJSON.FromJSON (Animate.SpriteSheetInfo delay)
+ Animate: instance Data.Aeson.Types.ToJSON.ToJSON delay => Data.Aeson.Types.ToJSON.ToJSON (Animate.SpriteSheetInfo delay)
+ Animate: instance GHC.Classes.Eq delay => GHC.Classes.Eq (Animate.FrameStep delay)
+ Animate: instance GHC.Classes.Eq delay => GHC.Classes.Eq (Animate.SpriteSheetInfo delay)
+ Animate: instance GHC.Generics.Generic (Animate.Frame loc delay)
+ Animate: instance GHC.Generics.Generic (Animate.FrameStep delay)
+ Animate: instance GHC.Generics.Generic (Animate.Position key delay)
+ Animate: instance GHC.Generics.Generic (Animate.SpriteSheet key img delay)
+ Animate: instance GHC.Generics.Generic (Animate.SpriteSheetInfo delay)
+ Animate: instance GHC.Generics.Generic Animate.Loop
+ Animate: instance GHC.Generics.Generic Animate.SpriteClip
+ Animate: instance GHC.Show.Show delay => GHC.Show.Show (Animate.FrameStep delay)
+ Animate: instance GHC.Show.Show delay => GHC.Show.Show (Animate.SpriteSheetInfo delay)
+ Animate: newtype Animations key loc delay
- Animate: Frame :: loc -> Seconds -> Frame loc
+ Animate: Frame :: loc -> delay -> Frame loc delay
- Animate: FrameStep'Counter :: Seconds -> FrameStep
+ Animate: FrameStep'Counter :: delay -> FrameStep delay
- Animate: FrameStep'Delta :: DeltaSeconds -> FrameStep
+ Animate: FrameStep'Delta :: delay -> FrameStep delay
- Animate: Position :: key -> FrameIndex -> Seconds -> Loop -> Position key
+ Animate: Position :: key -> FrameIndex -> delay -> Loop -> Position key delay
- Animate: SpriteSheet :: Animations key SpriteClip -> img -> SpriteSheet key img
+ Animate: SpriteSheet :: Animations key SpriteClip delay -> img -> SpriteSheet key img delay
- Animate: SpriteSheetInfo :: FilePath -> Maybe Color -> [SpriteClip] -> Map Text [(FrameIndex, Seconds)] -> SpriteSheetInfo
+ Animate: SpriteSheetInfo :: FilePath -> Maybe Color -> [SpriteClip] -> Map Text [(FrameIndex, delay)] -> SpriteSheetInfo delay
- Animate: animations :: Key key => (key -> [Frame loc]) -> Animations key loc
+ Animate: animations :: Key key => (key -> [Frame loc delay]) -> Animations key loc delay
- Animate: currentFrame :: Key key => Animations key loc -> Position key -> Frame loc
+ Animate: currentFrame :: (Num delay, Key key) => Animations key loc delay -> Position key delay -> Frame loc delay
- Animate: currentLocation :: Key key => Animations key loc -> Position key -> loc
+ Animate: currentLocation :: (Num delay, Key key) => Animations key loc delay -> Position key delay -> loc
- Animate: data Frame loc
+ Animate: data Frame loc delay
- Animate: data FrameStep
+ Animate: data FrameStep delay
- Animate: data Position key
+ Animate: data Position key delay
- Animate: data SpriteSheet key img
+ Animate: data SpriteSheet key img delay
- Animate: data SpriteSheetInfo
+ Animate: data SpriteSheetInfo delay
- Animate: framesByAnimation :: Key key => Animations key loc -> key -> Vector (Frame loc)
+ Animate: framesByAnimation :: Key key => Animations key loc delay -> key -> Vector (Frame loc delay)
- Animate: initPosition :: Key key => key -> Position key
+ Animate: initPosition :: (Num delay, Key key) => key -> Position key delay
- Animate: initPositionLoops :: Key key => key -> Int -> Position key
+ Animate: initPositionLoops :: (Num delay, Key key) => key -> Int -> Position key delay
- Animate: initPositionWithLoop :: Key key => key -> Loop -> Position key
+ Animate: initPositionWithLoop :: (Num delay, Key key) => key -> Loop -> Position key delay
- Animate: isAnimationComplete :: Key key => Animations key loc -> Position key -> Bool
+ Animate: isAnimationComplete :: (Key key, Num delay, Ord delay) => Animations key loc delay -> Position key delay -> Bool
- Animate: positionHasLooped :: Position key -> Position key -> Bool
+ Animate: positionHasLooped :: Position key delay -> Position key delay -> Bool
- Animate: readSpriteSheetInfoJSON :: FilePath -> IO SpriteSheetInfo
+ Animate: readSpriteSheetInfoJSON :: FromJSON delay => FilePath -> IO (SpriteSheetInfo delay)
- Animate: readSpriteSheetJSON :: KeyName key => (FilePath -> Maybe Color -> IO img) -> FilePath -> IO (SpriteSheet key img)
+ Animate: readSpriteSheetJSON :: (KeyName key, FromJSON delay) => (FilePath -> Maybe Color -> IO img) -> FilePath -> IO (SpriteSheet key img delay)
- Animate: stepFrame :: Frame loc -> Position key -> DeltaSeconds -> FrameStep
+ Animate: stepFrame :: (Num delay, Ord delay) => Frame loc delay -> Position key delay -> delay -> FrameStep delay
- Animate: stepPosition :: Key key => Animations key loc -> Position key -> DeltaSeconds -> Position key
+ Animate: stepPosition :: (Num delay, Ord delay, Key key) => Animations key loc delay -> Position key delay -> delay -> Position key delay

Files

animate.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack  name:           animate-version:        0.3.0+version:        0.4.0 synopsis:       Animation for sprites description:    Prototypical sprite animation with type-safety. category:       Game
library/Animate.hs view
@@ -1,10 +1,9 @@+{-# LANGUAGE DeriveGeneric #-} module Animate-  ( Seconds-  , DeltaSeconds-  , Color+  ( Color   , FrameIndex   , Frame(..)-  , Animations+  , Animations(..)   , Loop(..)   , Position(..)   , FrameStep(..)@@ -39,28 +38,23 @@ import Data.Map (Map) import Data.Word (Word8) import Data.Text (Text)---- | Avoided newtype wrapper for convenience-type Seconds = Float---- | Type aliased seconds-type DeltaSeconds = Seconds+import GHC.Generics (Generic)  -- | Alias for RGB (8bit, 8bit, 8bit) type Color = (Word8, Word8, Word8)  type FrameIndex = Int -data Frame loc = Frame+data Frame loc delay = Frame   { fLocation :: loc -- ^ User defined reference to the location of a sprite. For example, a sprite sheet clip.-  , fDelay :: Seconds -- ^ Minimium amount of time for the frame to last.-  } deriving (Show, Eq)+  , fDelay :: delay -- ^ Minimium amount of units for the frame to last.+  } deriving (Show, Eq, Generic) --- | Type safe animation set. Use an sum type with an `Enum` and `Bounded` instance for the animation, 'a'.-newtype Animations key loc = Animations { unAnimations :: V.Vector (V.Vector (Frame loc)) }+-- | Type safe animation set. Use a sum type with an `Enum` and `Bounded` instance for the animation, @a@.+newtype Animations key loc delay = Animations { unAnimations :: V.Vector (V.Vector (Frame loc delay)) }   deriving (Show, Eq) --- | Sematically for an animation key constraint+-- | Semantically for an animation key constraint class (Ord key, Bounded key, Enum key) => Key key  -- | Animation Keyframe. `keyName` is used for JSON parsing.@@ -74,7 +68,7 @@   , scW :: Int   , scH :: Int   , scOffset :: Maybe (Int, Int)-  } deriving (Show, Eq)+  } deriving (Show, Eq, Generic)  instance ToJSON SpriteClip where   toJSON SpriteClip{scX,scY,scW,scH,scOffset} = case scOffset of@@ -92,21 +86,21 @@       return SpriteClip { scX = x, scY = y, scW = w, scH = h, scOffset = Just (ofsX, ofsY) })  -- | Generalized sprite sheet data structure-data SpriteSheet key img = SpriteSheet-  { ssAnimations :: Animations key SpriteClip+data SpriteSheet key img delay = SpriteSheet+  { ssAnimations :: Animations key SpriteClip delay   , ssImage :: img-  }+  } deriving (Generic)  -- | One way to represent sprite sheet information.--- | JSON loading is included.-data SpriteSheetInfo = SpriteSheetInfo+--   JSON loading is included.+data SpriteSheetInfo delay = SpriteSheetInfo   { ssiImage :: FilePath   , ssiAlpha :: Maybe Color   , ssiClips :: [SpriteClip]-  , ssiAnimations :: Map Text [(FrameIndex, Seconds)]-  } deriving (Show, Eq)+  , ssiAnimations :: Map Text [(FrameIndex, delay)]+  } deriving (Show, Eq, Generic) -instance ToJSON SpriteSheetInfo where+instance ToJSON delay => ToJSON (SpriteSheetInfo delay) where   toJSON SpriteSheetInfo{ssiImage,ssiAlpha,ssiClips,ssiAnimations} = object     [ "image" .= ssiImage     , "alpha" .= ssiAlpha@@ -114,7 +108,7 @@     , "animations" .= ssiAnimations     ] -instance FromJSON SpriteSheetInfo where+instance FromJSON delay => FromJSON (SpriteSheetInfo delay) where   parseJSON (Object o) = do     image <- o .: "image"     alpha <- o .: "alpha"@@ -124,37 +118,38 @@   parseJSON _ = mzero  -- | Generate animations given each constructor-animations :: Key key => (key -> [Frame loc]) -> Animations key loc+animations :: Key key => (key -> [Frame loc delay]) -> Animations key loc delay animations getFrames = Animations $ V.fromList $ map (V.fromList . getFrames) [minBound..maxBound]  -- | Lookup the frames of an animation-framesByAnimation :: Key key => Animations key loc -> key -> V.Vector (Frame loc)+framesByAnimation :: Key key => Animations key loc delay -> key -> V.Vector (Frame loc delay) framesByAnimation (Animations as) k = as V.! fromEnum k  data Loop   = Loop'Always -- ^ Never stop looping. Animation can never be completed.   | Loop'Count Int -- ^ Count down loops to below zero. 0 = no loop. 1 = one loop. 2 = two loops. etc.-  deriving (Show, Eq)+  deriving (Show, Eq, Generic)  -- | State for progression through an animation--- | `example = Position minBound 0 0 Loop'Always`-data Position key = Position+--+-- > example = Position minBound 0 0 Loop'Always+data Position key delay = Position   { pKey :: key -- ^ Index for the animation.   , pFrameIndex :: FrameIndex -- ^ Index wihin the animation. WARNING: Modifying to below zero or equal-to-or-greater-than-the-frame-count will throw out of bounds errors.-  , pCounter :: Seconds -- ^ Accumulated seconds to end of the frame. Will continue to compound if animation is completed.+  , pCounter :: delay -- ^ Accumulated units to end of the frame. Will continue to compound if animation is completed.   , pLoop :: Loop -- ^ How to loop through an animation. Loop'Count is a count down.-  } deriving (Show, Eq)+  } deriving (Show, Eq, Generic)  -- | New `Position` with its animation key to loop forever-initPosition :: Key key => key -> Position key+initPosition :: (Num delay, Key key) => key -> Position key delay initPosition key = initPositionWithLoop key Loop'Always  -- | New `Position` with its animation key with a limited loop-initPositionLoops :: Key key => key -> Int -> Position key+initPositionLoops :: (Num delay, Key key) => key -> Int -> Position key delay initPositionLoops key count = initPositionWithLoop key (Loop'Count count)  -- | New `Position`-initPositionWithLoop :: Key key => key -> Loop -> Position key+initPositionWithLoop :: (Num delay, Key key) => key -> Loop -> Position key delay initPositionWithLoop key loop = Position   { pKey = key   , pFrameIndex = 0@@ -163,20 +158,20 @@   }  -- | You can ignore. An intermediate type for `stepPosition` to judge how to increment the current frame.-data FrameStep-  = FrameStep'Counter Seconds -- ^ New counter to compare against the frame's delay.-  | FrameStep'Delta DeltaSeconds -- ^ How much delta to carry over into the next frame.-  deriving (Show, Eq)+data FrameStep delay+  = FrameStep'Counter delay -- ^ New counter to compare against the frame's delay.+  | FrameStep'Delta delay -- ^ How much delta to carry over into the next frame.+  deriving (Show, Eq, Generic)  -- | Intermediate function for how a frame should be step through.-stepFrame :: Frame loc -> Position key -> DeltaSeconds -> FrameStep+stepFrame :: (Num delay, Ord delay) => Frame loc delay -> Position key delay -> delay -> FrameStep delay stepFrame Frame{fDelay} Position{pCounter} delta =   if pCounter + delta >= fDelay     then FrameStep'Delta $ pCounter + delta - fDelay     else FrameStep'Counter $ pCounter + delta  -- | Step through the animation resulting a new position.-stepPosition :: Key key => Animations key loc -> Position key -> DeltaSeconds -> Position key+stepPosition :: (Num delay, Ord delay, Key key) => Animations key loc delay -> Position key delay -> delay -> Position key delay stepPosition as p d =   case frameStep of     FrameStep'Counter counter -> p{pCounter = counter }@@ -196,16 +191,16 @@           , pLoop = Loop'Count n' }  -- | Use the position to find the current frame of the animation.-currentFrame :: Key key => Animations key loc -> Position key -> Frame loc+currentFrame :: (Num delay, Key key) => Animations key loc delay -> Position key delay -> Frame loc delay currentFrame anis Position{pKey,pFrameIndex} = (framesByAnimation anis pKey) V.! pFrameIndex  -- | Use the position to find the current location, lik a sprite sheet clip, of the animation.-currentLocation :: Key key => Animations key loc -> Position key -> loc+currentLocation :: (Num delay, Key key) => Animations key loc delay -> Position key delay -> loc currentLocation anis p = fLocation (currentFrame anis p)  -- | The animation has finished all its frames. Useful for signalling into switching to another animation. --   With a Loop'Always, the animation will never be completed.-isAnimationComplete :: Key key => Animations key loc -> Position key -> Bool+isAnimationComplete :: (Key key, Num delay, Ord delay) => Animations key loc delay -> Position key delay -> Bool isAnimationComplete as p = case pLoop p of   Loop'Always -> False   Loop'Count n -> n < 0 && pFrameIndex p == lastIndex && pCounter p >= fDelay lastFrame@@ -214,41 +209,42 @@     lastIndex = V.length frames - 1     lastFrame = frames V.! lastIndex --- | Cycle through the next animation key+-- | Cycle through the next animation key. nextKey :: Key key => key -> key nextKey key = if key == maxBound then minBound else succ key --- | Cycle through the previous animation key+-- | Cycle through the previous animation key. prevKey :: Key key => key -> key prevKey key = if key == minBound then maxBound else pred key --- | Simple function diff'ing the position for loop change+-- | Simple function diff'ing the position for loop change. positionHasLooped-  :: Position key -- ^ Previous-  -> Position key -- ^ Next+  :: Position key delay -- ^ Previous+  -> Position key delay -- ^ Next   -> Bool positionHasLooped Position{ pLoop = Loop'Count c } Position{ pLoop = Loop'Count c' } = c > c' positionHasLooped Position{ pLoop = Loop'Always } _ = False positionHasLooped _ Position{ pLoop = Loop'Always } = False  -- | Quick function for loading `SpriteSheetInfo`.--- | Check the example.+--   Check the example. readSpriteSheetInfoJSON-  :: FilePath -- ^ Path of the sprite sheet info JSON file-  -> IO SpriteSheetInfo+  :: FromJSON delay+  => FilePath -- ^ Path of the sprite sheet info JSON file+  -> IO (SpriteSheetInfo delay) readSpriteSheetInfoJSON path = do   metaBytes <- BL.readFile path   case eitherDecode metaBytes of     Left _err -> error $ "Cannot parse Sprite Sheet Info \"" ++ path ++ "\""     Right ssi -> return ssi --- | Quick function for loading `SpriteSheetInfo`, then using it to load its image for a `SpriteSheet`--- | Check the example.+-- | Quick function for loading `SpriteSheetInfo`, then using it to load its image for a `SpriteSheet`.+--   Check the example. readSpriteSheetJSON-  :: KeyName key-  => (FilePath -> Maybe Color -> IO img) -- ^ Inject animage loading function+  :: (KeyName key, FromJSON delay)+  => (FilePath -> Maybe Color -> IO img) -- ^ Inject an image loading function   -> FilePath -- ^ Path of the sprite sheet info JSON file-  -> IO (SpriteSheet key img)+  -> IO (SpriteSheet key img delay) readSpriteSheetJSON loadImage infoPath = do   SpriteSheetInfo{ssiImage, ssiClips, ssiAnimations, ssiAlpha} <- readSpriteSheetInfoJSON infoPath   i <- loadImage ssiImage ssiAlpha
package.yaml view
@@ -1,5 +1,5 @@ name: animate-version: '0.3.0'+version: '0.4.0' category: Game synopsis: Animation for sprites description: Prototypical sprite animation with type-safety.