flutter3d
Showcase Changelog 38 packages API reference

Actors, brains and health

since 0.4.0 or earlier Simulation, audio and XR

An Actor is a thin handle onto an entity: everything it answers, health, brain, body, facing, is read off a component that may or may not be there. A turret has no body; a barrel has no brain. Nothing forces an actor to carry parts it never uses.

Step 1: A brain with its own memory #

A game's own brain extends Brain and overrides only the hooks it cares about. This one remembers whether it has ever been hurt.

/// A brain with one bit of memory: whether it has ever been hurt.
final class _WaryBrain extends Brain {
  bool everHurt = false;

  @override
  void onHurt(Mind it, double amount) => everHurt = true;

  @override
  Map<String, Object?> save() => <String, Object?>{'everHurt': everHurt};

  @override
  void restore(Map<String, Object?> from) =>
      everHurt = from['everHurt'] == true;
}

Step 2: Build an actor from components #

Vitality wraps a Health; Thinking wraps a Brain. Setting both on an entity and wrapping it in an Actor gives a single handle onto them.

final entities = EcsWorld();
final entity = entities.spawn();
entities
  ..set(entity, Vitality(Health(30.0)))
  ..set(entity, Thinking(_WaryBrain()));
final goblin = Actor(entities, entity, name: 'goblin');

Step 3: Hurt it and read the result #

applyDamage goes through Health.damage, which returns true only on the hit that kills. The brain hears about it separately, through onHurt.

final brain = goblin.brain! as _WaryBrain;
goblin.applyDamage(12.0);
brain.onHurt(Mind(_stubSystem()), 12.0);
final currentHealth = goblin.health!.current;

Twelve damage against thirty health leaves the goblin at eighteen, still alive, and its brain now remembers being hurt.

Step 4: Hit it and watch #

The same goblin, on the floor, with a bar over its head. Hit it for 12 runs the damage through Health and tells the brain, exactly as above: the bar shrinks, the goblin goes amber the first time it is hurt (the brain's own memory, not a colour the page keeps), and after three hits it is flat and grey. A fresh goblin builds it again from nothing.

final EcsWorld entities = EcsWorld();
final entity = entities.spawn();
_brain = _WaryBrain();
entities
  ..set(entity, Vitality(Health(30.0)))
  ..set(entity, Thinking(_brain));
_goblin = Actor(entities, entity, name: 'goblin');
// The damage goes through `Health`; the brain hears of it separately.
_goblin.applyDamage(_hitAsked);
_brain.onHurt(Mind(_stubSystem()), _hitAsked);