a fast, type driven, extensible ECS for game development
Switch branches/tags
Clone or download
Permalink
Failed to load latest commit information.
bench 0.5.1.0 Sep 28, 2018
examples Make shmup example 8.6 compatible Oct 15, 2018
src Disable Register for ghc 8.6.2 Oct 2, 2018
test Disable Register for ghc 8.6.2 Oct 2, 2018
tutorials Expand example text Jul 10, 2018
.gitignore cleanup Mar 29, 2018
.travis.yml travis ghc 861 Oct 1, 2018
CHANGELOG.md 0.6 Oct 10, 2018
LICENSE initial commit Jul 22, 2017
README.md Also export as markdown Jul 10, 2018
Setup.hs initial commit Jul 22, 2017
apecs.cabal 0.6 Oct 10, 2018
prepub.pdf Add prepublication paper Jul 3, 2018
stack.yaml - Oct 8, 2018

README.md

apecs

Build Status Hackage Stackage

apecs is an Entity Component System (ECS) framework inspired by specs and Entitas. ECS presents a data-driven approach to game development, that elegantly tackles many of the unique issues of game programming. The apecs front-end DSL exposes a small number of combinators that allow game logic to be expressive and extremely fast.

Links

Performance

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

Benchmarks

Example

{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeFamilies, MultiParamTypeClasses, TemplateHaskell #-}

import Apecs
import Linear (V2 (..))

newtype Position = Position (V2 Double) deriving Show
-- To declare a component, we need to specify how to store it
instance Component Position where
  type Storage Position = Map Position -- The simplest store is a Map

newtype Velocity = Velocity (V2 Double) deriving Show
instance Component Velocity where
  type Storage Velocity = Cache 100 (Map Velocity) -- Caching adds fast reads/writes

data Flying = Flying
instance Component Flying where
  type Storage Flying = Map Flying

makeWorld "World" [''Position, ''Velocity, ''Flying] -- Generate World and instances

game :: System World ()
game = do
  newEntity (Position 0, Velocity 1)
  newEntity (Position 2, Velocity 1)
  newEntity (Position 1, Velocity 2, Flying)

  -- Add velocity to position
  cmap $ \(Position p, Velocity v) -> Position (v+p)
  -- Apply gravity to non-flying entities
  cmap $ \(Velocity v, _ :: Not Flying) -> Velocity (v - (V2 0 1))
  -- Print a list of entities and their positions
  cmapM_ $ \(Position p, Entity e) -> liftIO . print $ (e, p)

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