scene_dash_v2_core 0.1.0
scene_dash_v2_core: ^0.1.0 copied to clipboard
Scene-Dash v2 headless core: organize, coordinate, and test gameplay code with an ECS runtime built on sparse sets, generational entities, events, clocks, command buffers, lifecycle hooks, GameState, [...]
Scene-Dash v2 #

An ECS-based way to organize, coordinate, and headlessly test gameplay code
built on top of flutter_scene. ECS is
the implementation model. the purpose is keeping a growing game's features,
state, lifecycles, and tests understandable.
This is the pure-Dart core: the ECS runtime and TestGame, no Flutter
dependency. The scene binding, widgets and SceneGame.boot shown below
live in scene_dash_v2, which
re-exports this package.
World-reactive widgets #
A widget selects one value out of the world and rebuilds only when that value changes:
EntityBuilder<Health, double>(
entity: player,
select: (h) => h.current, // compared once per frame
builder: (context, hp) => HealthBar(hp), // runs only when it changed
absent: const RespawnCountdown(), // entity dead / component gone
)
Same frame tick, same select-and-compare:
WorldBuilder<int>(select: (w) => w.query<Health>(require: const [Enemy]).count(),
builder: (ctx, n) => Text('$n enemies')) // any world-derived value
GameStateBuilder<GameStatus>(builder: (ctx, s) => switch (s) { ... })
// a subtree per game state
WorldEventListener<EnemyKilled>(onEvent: (ctx, e) => shakeScore(ctx),
child: const ScorePanel()) // world events into UI
The rest of the widget layer:
.matching resolves the entity through the world, .pulse drives transient
feedback, every: throttles a heavy select, GameScope reaches the game
from any context.
A complete game in one file #
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_scene/scene.dart';
import 'package:scene_dash_v2/scene_dash_v2.dart';
import 'package:vector_math/vector_math.dart' show Vector3;
Future<void> main() async {
final game = await SceneGame.boot(features: [installCubes]);
runApp(
GameScope( // provides the game to the subtree
game: game,
child: MaterialApp(
home: Scaffold(
body: SceneView( // flutter_scene widget; not wrapped
game.scene,
cameraBuilder: _camera,
onTick: game.onTick, // forwards frame ticks to the game
),
),
),
),
);
}
Camera _camera(Duration elapsed) =>
PerspectiveCamera(position: Vector3(0, 3, -6), target: Vector3.zero());
void installCubes(GameBuilder game) { // a feature: a plain function
game
..addSystem(Schedules.startup, spawnCube, writes: {Orbit, SceneTransform})
..addSystem(Schedules.update, orbitCubes, writes: {Orbit, SceneTransform});
}
void spawnCube(World world) => world.spawn(cubeBundle());
void orbitCubes(World world) { // a system: a plain function
world.query2<Orbit, SceneTransform>().each((entity, orbit, transform) {
orbit.phase += orbit.speed * world.dt; // dt is schedule-aware
transform
..x = orbit.radius * cos(orbit.phase)
..z = orbit.radius * sin(orbit.phase);
});
}
final class Orbit { // a component: a plain class
final double radius;
final double speed;
double phase;
Orbit({required this.radius, required this.speed, this.phase = 0});
}
List<Object> cubeBundle() => [ // a bundle: a function → the spawn list
Orbit(radius: 2, speed: 1),
SceneTransform.zero(),
NodeRef(Node(mesh: Mesh(CuboidGeometry(Vector3.all(0.8)), UnlitMaterial()))),
];
Hot reload applies edits to system bodies; there is no build step.
Quick start #
flutter channel master # flutter_scene needs Flutter GPU
flutter pub get # resolve the workspace (repo root)
cd examples/combat_sample
flutter run --enable-flutter-gpu
Reference #
- UI
- Boot
- World
- Frame
- Coordination
- flutter_scene
- Tooling
docs/concept.md for the architecture,
docs/integration.md for the flutter_scene bridge.
Packages and examples #
| Path | Purpose |
|---|---|
packages/scene_dash_v2_core |
Pure-Dart ECS runtime, authoring surface, headless TestGame. |
packages/scene_dash_v2 |
flutter_scene integration: SceneGame.boot, mounting, transform sync, physics bridge, gizmos, widget layer. Re-exports core, so one import covers both. |
packages/scene_dash_inspector |
Optional debug overlay: live entities, resources, system timings, event channels. Read-only, polled at 4 Hz. |
examples/scene_game |
Complete game: Rapier physics, one feature per folder. |
examples/headless_example |
The core without Flutter. |
examples/scene_benchmark |
On-device render benchmark: static vs mount-only vs ECS vs instanced. |
examples/combat_sample |
Combat slice: KayKit knight against waves of barbarians, lock-on, buyable skills, giants, Rapier ragdolls, authored .fmat materials. Gameplay pinned headless. |
benchmarks |
Query, structural, and record-overhead benchmarks. |
examples/scene_game/lib/features/ # feature based structure
├── player/ # else you keep beside it (hud/, fx/,
├── projectiles/ # common/, main.dart) is your call
├── rocks/
├── collectables/
├── rules/
├── world/
└── decor/
examples/scene_game/lib/features/player/ # every feature, same shape
├── player.dart # the Feature function: installs this feature's systems
├── data/ # components, bundles, config, resources
├── systems/ # one file per concern, not one file per feature
└── animation/ # optional; clip selection lives with its feature