import 'package:flame/components.dart'; import 'package:flame/game.dart'; import 'package:flame_forge2d/flame_forge2d.dart'; import 'package:flutter/foundation.dart'; const _attachedErrorMessage = "Can't add to attached Blueprints"; // TODO(erickzanardo): Keeping this inside our code base // so we can experiment with the idea, but this is a // potential upstream change on Flame. /// A [Blueprint] is a virtual way of grouping [Component]s /// that are related, but they need to be added directly on /// the [FlameGame] level. abstract class Blueprint { final List _components = []; final List _blueprints = []; bool _isAttached = false; /// Called before the the [Component]s managed /// by this blueprint is added to the [FlameGame] void build(T gameRef); /// Attach the [Component]s built on [build] to the [game] /// instance @mustCallSuper Future attach(T game) async { build(game); await Future.wait([ game.addAll(_components), ..._blueprints.map(game.addFromBlueprint).toList(), ]); _isAttached = true; } /// Adds a list of [Component]s to this blueprint. void addAll(List components) { assert(!_isAttached, _attachedErrorMessage); _components.addAll(components); } /// Adds a single [Component] to this blueprint. void add(Component component) { assert(!_isAttached, _attachedErrorMessage); _components.add(component); } /// Adds a list of [Blueprint]s to this blueprint. void addAllBlueprints(List blueprints) { assert(!_isAttached, _attachedErrorMessage); _blueprints.addAll(blueprints); } /// Adds a single [Blueprint] to this blueprint. void addBlueprint(Blueprint blueprint) { assert(!_isAttached, _attachedErrorMessage); _blueprints.add(blueprint); } /// Returns a copy of the components built by this blueprint List get components => List.unmodifiable(_components); /// Returns a copy of the children blueprints List get blueprints => List.unmodifiable(_blueprints); } /// A [Blueprint] that provides additional /// structures specific to flame_forge2d abstract class Forge2DBlueprint extends Blueprint { final List _callbacks = []; /// Adds a single [ContactCallback] to this blueprint void addContactCallback(ContactCallback callback) { assert(!_isAttached, _attachedErrorMessage); _callbacks.add(callback); } /// Adds a collection of [ContactCallback]s to this blueprint void addAllContactCallback(List callbacks) { assert(!_isAttached, _attachedErrorMessage); _callbacks.addAll(callbacks); } @override Future attach(Forge2DGame game) async { await super.attach(game); for (final callback in _callbacks) { game.addContactCallback(callback); } } /// Returns a copy of the callbacks built by this blueprint List get callbacks => List.unmodifiable(_callbacks); } /// Adds helper methods regardin [Blueprint]s to [FlameGame] extension FlameGameBlueprint on FlameGame { /// Shortcut to attach a [Blueprint] instance to this game /// equivalent to `MyBluepinrt().attach(game)` Future addFromBlueprint(Blueprint blueprint) async { await blueprint.attach(this); } }