The apecs package

[ Tags: bsd3, control, data, game, library ] [ Propose Tags ]

A fast ECS for game engine programming


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.1.0, 0.2.0.0, 0.2.0.1, 0.2.0.2, 0.2.0.3, 0.2.1.0, 0.2.1.1, 0.2.2.0, 0.2.3.0, 0.2.4.0, 0.2.4.1, 0.2.4.2, 0.2.4.3
Dependencies async, base (>=4.7 && <5), containers, mtl, template-haskell, vector [details]
License BSD3
Author Jonas Carpay
Maintainer jonascarpay@gmail.com
Category Game, Control, Data
Home page https://github.com/jonascarpay/apecs#readme
Source repository head: git clone git://github.com/jonascarpay/apecs.git
Uploaded Tue Oct 17 04:32:01 UTC 2017 by jonascarpay
Distributions NixOS:0.2.0.2, Stackage:0.2.4.3
Downloads 373 total (289 in the last 30 days)
Rating 0.0 (0 ratings) [clear rating]
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2017-10-17 [all 1 reports]
Hackage Matrix CI

Modules

[Index]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees


Readme for apecs-0.2.4.3

[back to package description]

apecs

hackage | documentation | tutorials

apecs is an Entity Component System inspired by specs and Entitas. It exposes a DSL that translates to fast storage operations, resulting in expressivity without sacrificing performance or safety.

There is an example below, and a tutorial can be found here. For a general introduction to ECS, see this talk or here.

Performance

Performance is good. Running ecs-bench shows that apecs is competitive with the fastest Rust ECS frameworks.

| | pos_vel build | pos_vel step | parallel build | parallel step | | ------------- | ------------- | ------------ | -------------- | ------------- | | apecs | 239 | 34 | 777 | 371 | | calx | 261 | 21 | 442 | 72 | | constellation | 306 | 10 | 567 | 256 | | froggy | 594 | 13 | 1565 | 97 | | specs | 753 | 38 | 1016 | 205 |

Benchmarks

There is a performance guide here.

Example

import Apecs
import Apecs.TH (makeWorld)
import Apecs.Stores (Cache)
import Apecs.Concurrent (prmap)
import Linear

newtype Position = Position (V2 Double) deriving Show
-- Turn Position into a component by specifiying the type of its Storage
instance Component Position where
  -- The simplest store is a Map
  type Storage Position = Map Position

newtype Velocity = Velocity (V2 Double)
instance Component Velocity where
  -- We can add a Cache for faster access
  type Storage Velocity = Cache 100 (Map Velocity)

data Player = Player -- A single constructor component for tagging the player
instance Component Player where
  -- Unique contains at most one component. See the Stores module.
  type Storage Player = Unique Player

-- Generate a world type and instances
makeWorld "World" [''Position, ''Velocity, ''Player]

game :: System World ()
game = do
  -- Create new entities
  ety <- newEntity (Position 0)
  -- Components can be composed using tuples
  newEntity (Position 0, Velocity 1)
  newEntity (Position 1, Velocity 1, Player)

  -- set (over)writes components
  set ety (Velocity 2)

  let stepVelocity (Position p, Velocity v) = Position (v+p)

  -- Side effects
  liftIO$ putStrLn "Stepping velocities"
  -- rmap maps a pure function over all entities in its domain
  rmap stepVelocity
  -- prmap n does the same, but in parallel
  prmap 2 stepVelocity

  -- Print all positions
  cmapM_ $ \(Position p) -> liftIO (print p)

main :: IO ()
main = initWorld >>= runSystem game