good 0.2.0
good: ^0.2.0 copied to clipboard
Dimension-agnostic game engine kernel for Flutter: an ECS, native memory pools and ring buffers, scenes, a fixed-tick simulation isolate, hierarchy, assets and the GameView widget.
good #
Game Overdrive On Dart. The kernel every good engine is built on: the ECS, the fixed-tick loop, scenes, native component storage, input, assets and coroutines.
Building a 2D game? Install goo2d
instead. It re-exports everything here, so you get this package anyway and a
renderer with it. Depend on good directly when you are writing a renderer, a
headless server, or a package that should work under either engine.
flutter pub add good
The one idea #
Components are not objects. A field declared on an entity kind is a column in native memory, and an entity is a row index into it:
import 'package:good/good.dart';
class Player extends EntityStruct {
final speed = Field.float64(220); // the default every new row starts at
}
speed[entity] = 400; // write one row
That is what keeps the frame loop free of allocation, and it is the thing worth understanding before anything else. Systems then query for the entities they care about and walk those columns:
class PlayerSystem extends GameSystem with FixedTickable {
late final Query players;
@override
void describeQuery(QueryDescriptor descriptor) {
super.describeQuery(descriptor);
players = descriptor.query().withAll(Player).build();
}
@override
void onFixedUpdate() { /* ... */ }
}
Next #
- Entities and components for the column-and-row model in full.
- Architecture for how the Flutter isolate and the game isolate split the work.
It does depend on Flutter, because GameView is a widget and StateChannel is
a ValueListenable.
The ECS, memory pool, scheduler, scenes, hierarchy, input, assets, coroutines
and timelines work today. Audio playback and array-typed fields are not
implemented, and the web is unsupported because this needs dart:ffi and
isolates. What works today.