Skip to content

Latest commit

 

History

History
202 lines (177 loc) · 5.24 KB

README.md

File metadata and controls

202 lines (177 loc) · 5.24 KB

TECS

Simple archetype based ECS written in dart.
Made for learning purposes so keep that in mind before using it.
Any improvements or suggestions are welcome.

World

import 'package:tecs/tecs.dart';

// Create a World
final world = World();

// Reset and Clear the World
world.clear();

Entities

// Create Entities
final entity1 = world.createEntity();
final entity2 = world.createEntity();

// Remove Entities
world.removeEntity(entity1); // returns true
world.removeEntity(entity2); // returns true
world.removeEntity(entity1); // returns false, entity1 is not alive
// Check Entity Status
final entity1Status = world.isAlive(entity1);
if(entity1Status) {
  print("entity1 is alive");
} else {
  print("entity1 is dead");
}
// Create entities in bulk
final entityIDs = world.createEntities([
	[NameComponent(name: "Entity1"), PositionComponent(x:  10.0, y:  20.0)],
	[NameComponent(name: "Entity2"), PositionComponent(x:  30.0, y:  40.0)],
	[NameComponent(name: "Entity3"), PositionComponent(x:  50.0, y:  60.0)],
]);
print(entityIDs.length); // 3

Components

class PositionComponent extends Component {
  PositionComponent({
    required this.x,
    required this.y,
  });

  double x;
  double y;
}
class VelocityComponent extends Component {
  VelocityComponent({
    required this.x,
    required this.y,
  });

  double x;
  double y;
}
// Add a component to an entity
world.addComponent(entity1, PositionComponent(x: 150, y: 150));
world.addComponent(entity1, VelocityComponent(x: -800, y: 400));

// Add components to an entity in bulk
world.addComponents(entity1, components: [
  PositionComponent(x: 150, y: 150),
  VelocityComponent(x: -800, y: 400),
]);
// Get component of an entity (returns null if the entity does not have the component)
final position = world.getComponent<PositionComponent>(entity1);
final velocity = world.getComponent<VelocityComponent>(entity1);
// Remove a component
world.removeComponent<PositionComponent>(entity1);
world.removeComponent<VelocityComponent>(entity1);

// Remove components in bulk
world.removeComponents(entity1, components: [
  PositionComponent,
  VelocityComponent,
]);

Queries

final queryResult = world.query([PositionComponent, VelocityComponent]);

for (final row in queryResult.rows) {
    final position = row.get<PositionComponent>();
    final velocity = row.get<VelocityComponent>();

    position.x += velocity.x;
    position.y += velocity.y;
}

Systems

// extending with System<T> you can change the type of argument the update function will take.
class MoveSystem extends System<double> {
  @override
  void update(double deltaTime) {
    // has access to the world
    final queryResult = world.query([PositionComponent, VelocityComponent]);

    for (final row in queryResult.rows) {
        final position = row.get<PositionComponent>();
        final velocity = row.get<VelocityComponent>();

        position.x += velocity.x * deltaTime;
        position.y += velocity.y * deltaTime;
    }
  }
}
// Add a system
world.addSystem(MoveSystem());
// Update all systems sequantially (add order matters)

// A game loop that provides 'double deltaTime'
world.update(deltaTime);
// A game loop that provides 'double deltaTime'

System Tags

// You can give tags to your systems to update differently and pass different arguments.
// You can use the new records capability dart3 provides to accept multiple arguments
class RenderSystem extends System<({Canvas canvas, Size size})> {
  @override
  void update(args) {
    final queryResult = world.query([RectComponent, ColorComponent]);

    for (final row in queryResult.rows) {
        final rect = row.get<RectComponent>();
        final color = row.get<ColorComponent>();

        final paint = Paint()
            ..color = color.value
            ..style = PaintingStyle.fill;

        args.canvas.drawRect(rect.value, paint);
    }
  }
}
// Add the system with tag
world.addSystem(MoveSystem()); // default
world.addSystem(CollisionSystem()); // default

world.addSystem(RenderSystem(), tag: "render");
world.addSystem(RenderCollidersDebug(), tag: "render");
// A game loop that provides 'double deltaTime'
world.update(deltaTime); // MoveSystem and CollisionSystem will run
// A game loop that provides 'double deltaTime'

// A render loop that provides canvas and size
world.update(canvas, size, tag: "render"); // RenderSystem and RenderCollidersDebug will run
// A render loop that provides canvas and size

Resources

class GameTime {
    double seconds = 0;
}

// Add Resource
world.addResource(GameTime());

// Get Resource and Manipulate
final gameTime = world.getResource<GameTime>();
gameTime.seconds += 1;

// If you add same resource, it will replace the old one
world.addResource(GameTime()); // replace the old GameTime

// You can give tags to add the same resource type without replacing
world.addResource(GameTime(), tag: "menu");
final gameTime = world.getResource<GameTime>();
final gameTimeMenu = world.getResource<GameTime>(tag: "menu");

// Remove resource
world.removeResource<GameTime>(); // returns GameTime if the resource exists, null otherwise
world.removeResource<GameTime>(tag: "menu");