Skip to content

RowDaBoat/vecs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vecs

Vexel's ECS library for Nim👑, heavily inspired by Beef🥩's yeacs, a lot of his ideas were used, and some of his macros were directly copied.

vecs's API aims to be mostly the same, with minor differences.

The main design differences between vecs and yeacs are in the implementation:

  • vecs avoids manually copying memory, erasure is implemented by using abstract types, then casting to concrete types when needed. This simplifies book-keeping a bit, and goes easier on references, not needing to track move semantics.
  • vecs approaches ECS with a collection for each component in the archetype, while yeacs instead uses a single collection of tuples of components for each archetype.

Documentation

The API reference is available here.

Basic Usage

# Create a world
var world = World()
# Add an entity
let entityId = world.addEntity (
  Character(name: "Marcus", class: "Warrior"),
  Health(health: 120, maxHealth: 120)
)
# Get a component from an entity
for health in world.component(entityId, Health):
  health.health += 75
# Get multiple components from an entity
for (character, health) in world.component(entityId, (Character, Health)):
  character.name = "Happy " & character.name
  health.health += 75
# Query for components
var characterWithSwordsQuery = Query[(Character, Sword)]()
for (character, sword) in world.query(characterWithSwordsQuery):
  echo character.name, " has a sword, ", sword.name, "!"
# Removing an entity
world.removeEntity entityId
# Adding a component
world.addComponent(entityId, Shield(name: "Steel Shield", defense: 15))
# Removing a component
world.removeComponent(entityId, Shield)
# Using an Id component fills it with the Id of the entity
# This is useful for embedding references to other entities into components
let entityId = world.addEntity (Id(), Character(name: "Leon", class: "Paladin"))

for idComponent in world.component(entityId, Id):
  assert entityId == idComponent

Advanced querying

# Query components for writting
var characterWithSwordsQuery = Query[(Character, Write[Health])]()
for (character, health) in world.query(characterWithSwordsQuery):
  health.health += 10
# Query for optional components
var characterWithSwordsQuery = Query[(Character, Opt[Weapon])]()
for (character, weapon) in world.query(characterWithSwordsQuery):
  weapon.isSmoething:
    echo character.name, " has a weapon, ", weapon.name
  weapon.isNothing:
    echo character.name, " has no weapon"
# Exclude components from a query
var disarmedCharacters = Query[(Character, Not[Weapon])]()
for (character,) in world.query(disarmedCharacters):
  echo character.name, " has no weapon"

Roadmap

  • Add entities

  • Archetypes

  •  Queries

  • Remove entities

  • Support dynamic archetypes

  • Add component

  • Remove component

  • Special Id component

  • Restrict generic T on queries and components procs to be tuples

  •  'Not' Queries

  • 'Opt' Queries

  • 'Write' Queries

  • Stable ids for components

  • Polish console output

  • Convenience procs and checks

    • Allow read access to components without an iterator
    • component fails to compile silently when used with a Tuple
    • components sys-fatals when searching for a non existing Id
  • Text serialization

  •  Binary serialization

  • Convenience procs

    • component and components accept a list of entity ids
    • Add and Remove multiple components
  • Concurrency support

  • Zero-allocation?

  • Spatial and custom queries

  • Integrate with inim?

    • Pull req: show current code
    • Pull req: use nim --eval

About

Vexel's ECS, free as in freedom.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages