Skip to content

matthunz/aztecs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aztecs

Package License CI status

Aztecs: An Empirical Entity Component System (ECS) for Haskell [Draft]

A type-safe and friendly ECS for Haskell. An ECS is a modern approach to organizing your application state as a database, providing patterns for data-oriented design and parallel processing. For more information, please see the documentation on Hackage.

Features

  • High-performance: Components are stored by their unique sets in archetypes
  • Dynamic components: Scripts and remote interfaces can create unique components with runtime-specified components
  • Type-safe DSL: Queries and systems use Arrow syntax for compile-time gurantees
  • Modular design: Aztecs can be extended for a variety of use cases
import Control.Arrow ((>>>))
import Data.Aztecs
import qualified Data.Aztecs.Access as A
import qualified Data.Aztecs.Query as Q
import qualified Data.Aztecs.System as S

newtype Position = Position Int deriving (Show)

instance Component Position

newtype Velocity = Velocity Int deriving (Show)

instance Component Velocity

setup :: System () ()
setup = S.queue . const . A.spawn_ $ bundle (Position 0) <> bundle (Velocity 1)

move :: System () ()
move =
  S.map
    ( proc () -> do
        Velocity v <- Q.fetch -< ()
        Position p <- Q.fetch -< ()
        Q.set -< Position $ p + v
    )
    >>> S.run print

main :: IO ()
main = runSystem_ $ setup >>> S.forever move

SDL

import Control.Arrow (returnA, (>>>))
import Data.Aztecs
import qualified Data.Aztecs.Access as A
import Data.Aztecs.Asset (load)
import qualified Data.Aztecs.Query as Q
import Data.Aztecs.SDL (Image (..), Window (..))
import qualified Data.Aztecs.SDL as SDL
import qualified Data.Aztecs.System as S
import Data.Aztecs.Transform (Transform (..), transform)
import SDL (V2 (..))

setup :: System () ()
setup =
  S.mapSingle
    ( proc () -> do
        assetServer <- Q.fetch -< ()
        (texture, assetServer') <- Q.run (load "example.png") -< assetServer
        Q.set -< assetServer'
        returnA -< texture
    )
    >>> S.queue
      ( \texture -> do
          A.spawn_ $ bundle Window {windowTitle = "Aztecs"}
          A.spawn_ $
            bundle Image {imageTexture = texture, imageSize = V2 100 100}
              <> bundle transform {transformPosition = V2 100 100}
          A.spawn_ $
            bundle Image {imageTexture = texture, imageSize = V2 200 200}
              <> bundle transform {transformPosition = V2 500 100}
      )

main :: IO ()
main = runSystem_ $ SDL.setup >>> setup >>> S.forever SDL.update

Benchmarks

Aztecs is currently faster than bevy-ecs, a popular and high-performance ECS written in Rust, for simple mutating queries.

benchmark results: Aztecs 932us vs Bevy 6,966us

Inspiration

Aztecs' approach to type-safety is inspired by Bevy, but with direct archetype-based storage similar to Flecs.