packages feed

apecs 0.7.1 → 0.7.2

raw patch · 12 files changed

+154/−115 lines, 12 filesdep ~QuickCheckdep ~basedep ~containersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: QuickCheck, base, containers, criterion, linear, mtl, template-haskell, vector

API changes (from Hackage documentation)

+ Apecs: Proxy :: Proxy
+ Apecs: data Proxy (t :: k) :: forall k. () => k -> Type
+ Apecs.Stores.Extra: instance Data.Foldable.Foldable Apecs.Stores.Extra.Stack
+ Apecs.Stores.Extra: instance GHC.Base.Applicative Apecs.Stores.Extra.Stack
+ Apecs.Stores.Extra: instance GHC.Base.Functor Apecs.Stores.Extra.Stack
+ Apecs.Stores.Extra: instance GHC.Base.Monad Apecs.Stores.Extra.Stack
+ Apecs.Stores.Extra: instance GHC.Base.Monoid (Apecs.Stores.Extra.Stack c)
+ Apecs.Stores.Extra: instance GHC.Base.Semigroup (Apecs.Stores.Extra.Stack c)
+ Apecs.Stores.Extra: instance GHC.Classes.Eq c => GHC.Classes.Eq (Apecs.Stores.Extra.Stack c)
+ Apecs.Stores.Extra: instance GHC.Show.Show c => GHC.Show.Show (Apecs.Stores.Extra.Stack c)

Files

CHANGELOG.md view
@@ -1,7 +1,13 @@+## [Unreleased]+### Changed+- Fixed bug in the `Pushdown` store+- `Apecs` module no longer re-exports the entire `Data.Proxy` module, but instead just `Proxy (..)`.+- Added (approximate?) lower and upper version bounds to dependencies+ ## [0.7.1]-## Added+### Added - `$=` and `$~` operators as synonyms for `set` and `get` respectively-## Removed+### Removed - `getAll` and `count`, which were made redundant by `cfold`.  ## [0.7.0]
README.md view
@@ -1,31 +1,45 @@-# apecs--apecs is an _Entity Component System_ (ECS) framework inspired by [specs](https://github.com/slide-rs/specs) and [Entitas](https://github.com/sschmid/Entitas-CSharp).+# apecs [![Build Status](https://travis-ci.org/jonascarpay/apecs.svg?branch=master)](https://travis-ci.org/jonascarpay/apecs)+apecs is an _Entity Component System_ (ECS) library inspired by [specs](https://github.com/slide-rs/specs) and [Entitas](https://github.com/sschmid/Entitas-CSharp). ECS presents a data-driven approach to game development, that elegantly tackles many of the unique issues of game programming.+ apecs aims to be-* **Fast** - apecs is designed for high-performance applications. Its performance is competitive with Rust ECS libraries.-* **Simple** - Game logic is expressed using a small number of combinators, and minimal boilerplate.-* **Safe** - The `cmap`/`cfold`-DSL hides all the dangers of the low-level API.-* **Extensible** - apecs can be used with anything that implements the low-level API. See [apecs-physics](apecs-physics/) or [apecs-stm](apecs-stm/) for examples.+* **Fast** - Performance is competitive with Rust ECS libraries (see benchmark results below).+* **Concise** - Game logic is expressed using a small number of powerful combinators.+* **Safe** - The `cmap`/`cfold`-DSL completely hides the dangers of the low-level API.+* **Extensible** - At its heart apecs is just a data manipulation DSL that can be implemented with any number of backends. as a monad transformer it easily integrates into larger applications.+* **Cool** +![Benchmarks](apecs/bench/chart.png)+ #### Links-- [manual](https://github.com/jonascarpay/apecs/blob/master/prepub.pdf) (see [#19](https://github.com/jonascarpay/apecs/issues/19))-- [tutorial](https://github.com/jonascarpay/apecs/blob/master/examples/Shmup.md)-- [documentation](https://hackage.haskell.org/package/apecs/docs/Apecs.html)-- [apecs-physics](https://github.com/jonascarpay/apecs-physics)+- [documentation on hackage](https://hackage.haskell.org/package/apecs/docs/Apecs.html)+- [tutorial](examples/Shmup.md) and other [examples](examples/)+- [paper (prepublication)](apecs/prepub.pdf) (see [#19](https://github.com/jonascarpay/apecs/issues/19))+- [apecs-physics](apecs-physics/) - 2D physics using the [Chipmunk2D](https://github.com/slembcke/Chipmunk2D) engine+- [apecs-gloss](apecs-gloss/) - Simple frontend for [gloss](http://hackage.haskell.org/package/gloss)-based rendering+- [apecs-stm](apecs-stm/) - STM-based stores for easy concurrency -#### Performance-[ecs-bench](https://github.com/lschmierer/ecs_bench) shows that apecs is competitive with the fastest Rust ECS frameworks.+##### By other authors+- [An Introduction to Developing Games in Haskell with Apecs](https://blog.aas.sh/posts/2018-09-10-Making-A-Game-With-Haskell-And-Apecs/) by Ashley Smith -![Benchmarks](bench/chart.png)+#### Status+| Package | Hackage | Stack LTS | Stack Nightly |+|---|---|---|---|+| [apecs](apecs/) | [![Hackage](https://img.shields.io/hackage/v/apecs.svg)](https://hackage.haskell.org/package/apecs) | [![Stackage](https://www.stackage.org/package/apecs/badge/lts?label=lts)](https://www.stackage.org/package/apecs) | [![Stackage](https://www.stackage.org/package/apecs/badge/nightly?label=nightly)](https://www.stackage.org/package/apecs)+| [apecs-physics](apecs-physics/) |  [![Hackage](https://img.shields.io/hackage/v/apecs-physics.svg)](https://hackage.haskell.org/package/apecs-physics) | [![Stackage](https://www.stackage.org/package/apecs-physics/badge/lts?label=lts)](https://www.stackage.org/package/apecs-physics) | [![Stackage](https://www.stackage.org/package/apecs-physics/badge/nightly?label=nightly)](https://www.stackage.org/package/apecs-physics) |+| [apecs-gloss](apecs-gloss/) | [![Hackage](https://img.shields.io/hackage/v/apecs-gloss.svg)](https://hackage.haskell.org/package/apecs-gloss) | [![Stackage](https://www.stackage.org/package/apecs-gloss/badge/lts?label=lts)](https://www.stackage.org/package/apecs-gloss) | [![Stackage](https://www.stackage.org/package/apecs-gloss/badge/nightly?label=nightly)](https://www.stackage.org/package/apecs-gloss) |+| [apecs-stm](apecs-stm/) | [![Hackage](https://img.shields.io/hackage/v/apecs-stm.svg)](https://hackage.haskell.org/package/apecs-stm) | - | - |+| [examples](examples/) | - | - | - |  #### Example ```haskell-{-# LANGUAGE DataKinds, FlexibleInstances, ScopedTypeVariables, TypeFamilies, MultiParamTypeClasses, TemplateHaskell #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TemplateHaskell       #-}+{-# LANGUAGE TypeFamilies          #-}  import Apecs-import Control.Monad-import Apecs.Util import Linear (V2 (..))  newtype Position = Position (V2 Double) deriving Show
apecs.cabal view
@@ -1,5 +1,5 @@ name:                apecs-version:             0.7.1+version:             0.7.2 homepage:            https://github.com/jonascarpay/apecs#readme license:             BSD3 license-file:        LICENSE@@ -8,10 +8,10 @@ category:            Game, Control, Data build-type:          Simple cabal-version:       >=1.10-synopsis:            Fast ECS framework for game programming+synopsis:            Fast Entity-Component-System library for game programming description:-  Entity-Component-System frameworks provide a game programming paradigm that tackles many of the shortcomings of a more OO-oriented approach.-  apecs is a type-driven ECS, that leverages strong typing for an expressive DSL that turns into fast game code.+  The Entity-Component-System architecture provides an imperative game programming paradigm that tackles many of the shortcomings of more OO-oriented approaches.+  apecs is a type-driven ECS library, that leverages strong typing for an expressive DSL that compiles into fast game code.  extra-source-files:   README.md,@@ -39,11 +39,11 @@   default-language:     Haskell2010   build-depends:-    base >= 4.7 && < 5,-    containers,-    mtl,-    template-haskell,-    vector+    base             >= 4.9  && < 5,+    containers       >= 0.5  && < 0.8,+    mtl              >= 2.2  && < 2.3,+    template-haskell >= 2.12 && < 3,+    vector           >= 0.11 && < 0.13   ghc-options:     -Wall @@ -55,13 +55,12 @@   hs-source-dirs:     test   build-depends:-    base >= 4.7 && < 5,     apecs,-    QuickCheck,-    criterion,-    linear,-    containers,-    vector+    base       >= 4.9  && < 5,+    containers >= 0.5  && < 0.8,+    linear     >= 1.20 && < 2,+    vector     >= 0.10 && < 0.13,+    QuickCheck >= 2.10 && < 3   default-language:     Haskell2010   ghc-options: -Wall@@ -74,19 +73,17 @@   main-is:     Main.hs   build-depends:-    base >= 4.7 && < 5,     apecs,-    criterion,-    linear+    base      >= 4.9  && < 5,+    criterion >= 1.3  && < 2,+    linear    >= 1.20 && < 2   default-language:     Haskell2010   ghc-options:     -Wall-    -- LLVM is disabled by default for travis/compatibility reasons-    -- For serious benchmarks, please run with -fllvm-    -- -fllvm     -O2     -optlo-O3+    -- -fllvm     -threaded     -funfolding-use-threshold1000     -funfolding-keeness-factor1000
src/Apecs.hs view
@@ -3,7 +3,6 @@ It selectively re-exports the user-facing functions from the submodules. -} module Apecs (-  module Data.Proxy,   -- * Core types     SystemT(..), System, Component(..), Entity(..), Has(..), Not(..),     Get, Set, Destroy, Members,@@ -15,7 +14,7 @@   -- * Systems     get, set, ($=),     destroy, exists,-    modify, ($~), +    modify, ($~),     cmap,  cmapM,  cmapM_,     cfold, cfoldM, cfoldM_, @@ -25,16 +24,15 @@     makeWorld, makeWorldAndComponents,    -- * Re-exports-    asks, ask, liftIO, lift,+    asks, ask, liftIO, lift, Proxy (..) ) where -import           Control.Monad.Reader (ask, asks, lift, liftIO)-import           Data.Proxy--import           Apecs.Stores-import           Apecs.Components-import           Apecs.System-import           Apecs.TH-import           Apecs.Core-import           Apecs.Util+import Control.Monad.Reader (ask, asks, lift, liftIO)+import Data.Proxy +import Apecs.Components+import Apecs.Core+import Apecs.Stores+import Apecs.System+import Apecs.TH+import Apecs.Util
src/Apecs/Components.hs view
@@ -13,10 +13,10 @@  module Apecs.Components where -import           Data.Functor.Identity+import Data.Functor.Identity  import           Apecs.Core-import qualified Apecs.THTuples        as T+import qualified Apecs.THTuples as T  -- | Identity component. @Identity c@ is equivalent to @c@, so mostly useless. instance Component c => Component (Identity c) where
src/Apecs/Core.hs view
@@ -12,7 +12,7 @@ module Apecs.Core where  import           Control.Monad.Reader-import qualified Data.Vector.Unboxed   as U+import qualified Data.Vector.Unboxed  as U  -- | An Entity is just an integer, used to index into a component store. --   In general, use @newEntity@, @cmap@, and component tags instead of manipulating these directly.@@ -76,4 +76,3 @@ type Set     w m c = (Has w m c, ExplSet     m (Storage c)) type Members w m c = (Has w m c, ExplMembers m (Storage c)) type Destroy w m c = (Has w m c, ExplDestroy m (Storage c))-
src/Apecs/Stores.hs view
@@ -26,7 +26,7 @@ import qualified Data.Vector.Unboxed.Mutable as UM import           GHC.TypeLits -import           Apecs.Core+import Apecs.Core  -- | A map based on @Data.IntMap.Strict@. O(log(n)) for most operations. newtype Map c = Map (IORef (M.IntMap c))
src/Apecs/Stores/Extra.hs view
@@ -4,42 +4,53 @@ Containment module for stores that are experimental/too weird for @Apecs.Stores@. -} -{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE UndecidableInstances  #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE PatternSynonyms            #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE UndecidableInstances       #-}  module Apecs.Stores.Extra   ( Pushdown(..), Stack(..)   , ReadOnly(..), setReadOnly, destroyReadOnly   ) where -import           Control.Monad.Reader-import           Data.Proxy+import Control.Monad.Reader+import Data.Proxy -import           Apecs.Core+import Apecs.Components (MaybeStore (..))+import Apecs.Core  -- | Overrides a store to have history/pushdown semantics. --   Setting this store adds a new value on top of the stack. --   Destroying pops the stack.---   You can view the entire stack using the @Stack c@ component.+--   You can view the entire stack using the 'Stack' wrapper. newtype Pushdown s c = Pushdown (s (Stack c))-newtype Stack c = Stack {getStack :: [c]}+newtype Stack c = Stack {getStack :: [c]} deriving (Eq, Show, Functor, Applicative, Monad, Foldable, Monoid, Semigroup)  type instance Elem (Pushdown s c) = c  instance (Functor m, ExplInit m (s (Stack c))) => ExplInit m (Pushdown s c) where   explInit = Pushdown <$> explInit +pattern StackList :: c -> [c] -> Maybe (Stack c)+pattern StackList x xs = Just (Stack (x:xs))+ instance   ( Monad m   , ExplGet m (s (Stack c))   , Elem (s (Stack c)) ~ Stack c   ) => ExplGet m (Pushdown s c) where-    explExists (Pushdown s) = explExists s-    explGet    (Pushdown s) ety = head . getStack <$> explGet s ety+    explExists (Pushdown s) ety = f <$> explGet (MaybeStore s) ety+      where+        f (StackList _ _) = True+        f _               = False+    explGet (Pushdown s) ety = head . getStack <$> explGet s ety  instance   ( Monad m@@ -48,8 +59,10 @@   , Elem (s (Stack c)) ~ Stack c   ) => ExplSet m (Pushdown s c) where     explSet (Pushdown s) ety c = do-      Stack cs <- explGet s ety-      explSet s ety (Stack (c:cs))+      ms <- explGet (MaybeStore s) ety+      let tail (StackList _ cs) = cs+          tail _                = []+      explSet s ety (Stack (c:tail ms))  instance   ( Monad m@@ -59,10 +72,10 @@   , Elem (s (Stack c)) ~ Stack c   ) => ExplDestroy m (Pushdown s c) where     explDestroy (Pushdown s) ety = do-      Stack cs <- explGet s ety-      case cs of-        _:cs' -> explSet s ety (Stack cs')-        []    -> explDestroy s ety+      mscs <- explGet (MaybeStore s) ety+      case mscs of+        StackList _ cs' -> explSet s ety (Stack cs')+        _               -> explDestroy s ety  instance   ( Monad m
src/Apecs/System.hs view
@@ -10,8 +10,8 @@ import           Data.Proxy import qualified Data.Vector.Unboxed  as U -import           Apecs.Core-import           Apecs.Components ()+import Apecs.Components ()+import Apecs.Core  -- | Run a system in a game world {-# INLINE runSystem #-}@@ -100,7 +100,7 @@     sl <- explMembers (sx,sp)     U.forM_ sl $ \ e -> do       p <- explGet sp e-      when (cond p) $ do +      when (cond p) $ do         x <- explGet sx e         explSet sy e (f x) 
src/Apecs/TH.hs view
@@ -1,15 +1,16 @@ {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies    #-}  module Apecs.TH   ( makeWorld, makeWorldNoEC, makeWorldAndComponents   ) where -import           Language.Haskell.TH-import           Control.Monad+import Control.Monad+import Language.Haskell.TH -import           Apecs.Core-import           Apecs.Stores-import           Apecs.Util          (EntityCounter)+import Apecs.Core+import Apecs.Stores+import Apecs.Util   (EntityCounter)  genName :: String -> Q Name genName s = mkName . show <$> newName s@@ -52,14 +53,14 @@ makeComponent comp = do   let ct = return$ ConT comp   head <$> [d| instance Component $ct where type Storage $ct = Map $ct |]-  + -- | Same as makeWorld, but also defines @Component@ instances with a @Map@ store. makeWorldAndComponents :: String -> [Name] -> Q [Dec] makeWorldAndComponents worldName cTypes = do   wdecls <- makeWorld worldName cTypes   cdecls <- mapM makeComponent cTypes   return $ wdecls ++ cdecls-  + {-|  > makeWorld "WorldName" [''Component1, ''Component2, ...]
src/Apecs/Util.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-unused-imports #-} {-# LANGUAGE FlexibleContexts           #-} {-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -18,16 +19,16 @@   quantize, flatten, inbounds, region, flatten', ) where -import           Control.Applicative  (liftA2)-import           Control.Monad.Reader-import           Data.Monoid-import           Data.Semigroup-import           System.Mem           (performMajorGC)+import Control.Applicative  (liftA2)+import Control.Monad.Reader+import Data.Monoid+import Data.Semigroup+import System.Mem           (performMajorGC) -import           Apecs.Core-import           Apecs.Stores-import           Apecs.Stores.Extra-import           Apecs.System+import Apecs.Core+import Apecs.Stores+import Apecs.Stores.Extra+import Apecs.System  -- | Convenience entity, for use in places where the entity value does not matter, i.e. a global store. global :: Entity
test/Main.hs view
@@ -1,28 +1,30 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE DataKinds                  #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE UndecidableInstances       #-}  {-# OPTIONS_GHC -w #-} -import Test.QuickCheck-import Test.QuickCheck.Monadic-import qualified Data.IntSet as S-import qualified Data.Vector.Unboxed as U-import Data.IORef-import Data.List (sort)-import Control.Monad+import           Control.Monad+import qualified Data.IntSet             as S+import           Data.IORef+import           Data.List               (sort)+import qualified Data.Vector.Unboxed     as U+import           Test.QuickCheck+import           Test.QuickCheck.Monadic -import Apecs-import Apecs.Reactive-import Apecs.Core-import Apecs.Stores-import Apecs.Util+import           Apecs+import           Apecs.Core+import           Apecs.Reactive+import           Apecs.Stores+import           Apecs.Stores.Extra+import           Apecs.Util  type Vec = (Double, Double) @@ -136,6 +138,14 @@          && sort rf == sort ef          && all (`notElem` ef) et          )++-- Tests Pushdown+newtype StackInt = StackInt Int deriving (Eq, Show, Arbitrary)+instance Component StackInt where type Storage StackInt = Pushdown Map StackInt++makeWorld "StackWld" [''StackInt]++prop_setGetStack = genericSetSet initStackWld (undefined :: StackInt)  return [] main = $quickCheckAll