From 0135f93493e32afa9af71603e52c45c024c8d75c Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 14 Nov 2020 14:34:39 +0100 Subject: [PATCH] Simplify BaseGame interactions --- CHANGELOG.md | 1 + example/lib/main.dart | 4 +-- lib/components/position_component.dart | 2 +- lib/game/base_game.dart | 48 ++++++++++++-------------- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8100f3059..799e96d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Effects duration and test suite for basic effects - Pause and resume for effects - Fix position bug in parallax effect + - Simplification of BaseGame. Removal of addLater (add is now addLater) and rename markForRemoval. ## 1.0.0-rc1 - Move all box2d related code and examples to the flame_box2d repo diff --git a/example/lib/main.dart b/example/lib/main.dart index 7484d7174..628b8fef6 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -73,12 +73,12 @@ class MyGame extends BaseGame with DoubleTapDetector, TapDetector { components.forEach((c) { if (c is PositionComponent && c.toRect().overlaps(touchArea)) { handled = true; - markToRemove(c); + remove(c); } }); if (!handled) { - addLater(Square() + add(Square() ..x = touchArea.left ..y = touchArea.top); } diff --git a/lib/components/position_component.dart b/lib/components/position_component.dart index d6abfb6b8..032762baf 100644 --- a/lib/components/position_component.dart +++ b/lib/components/position_component.dart @@ -193,7 +193,7 @@ abstract class PositionComponent extends Component { void addChild(Game gameRef, Component c) { if (gameRef is BaseGame) { - gameRef.preAdd(c); + gameRef.prepare(c); } _children.add(c); } diff --git a/lib/game/base_game.dart b/lib/game/base_game.dart index 0316dd1ca..28e074a5d 100644 --- a/lib/game/base_game.dart +++ b/lib/game/base_game.dart @@ -16,12 +16,13 @@ import 'game.dart'; /// This is a more complete and opinionated implementation of Game. /// -/// It still needs to be subclasses to add your game logic, but the [update], [render] and [resize] methods have default implementations. +/// BaseGame should be extended to add your game logic. +/// [update], [render] and [onResize] methods have default implementations. /// This is the recommended structure to use for most games. /// It is based on the Component system. class BaseGame extends Game with FPSCounter { /// The list of components to be updated and rendered by the base game. - OrderedSet components = + final OrderedSet components = OrderedSet(Comparing.on((c) => c.priority())); /// Components added by the [addLater] method @@ -31,17 +32,15 @@ class BaseGame extends Game with FPSCounter { final List _removeLater = []; /// Current game viewport size, updated every resize via the [resize] method hook - Vector2 size; + final Vector2 size = Vector2.zero(); + set size(Vector2 size) => this.size.setFrom(size); /// Camera position; every non-HUD component is translated so that the camera position is the top-left corner of the screen. Vector2 camera = Vector2.zero(); - /// This method is called for every component added, both via [add] and [addLater] methods. - /// - /// You can use this to setup your mixins, pre-calculate stuff on every component, or anything you desire. - /// By default, this calls the first time resize for every component, so don't forget to call super.preAdd when overriding. + /// Does preparation on a component before any update or render method is called on it @mustCallSuper - void preAdd(Component c) { + void prepare(Component c) { if (c is Tapable) { assert( this is HasTapableComponents, @@ -61,32 +60,30 @@ class BaseGame extends Game with FPSCounter { if (size != null) { c.onGameResize(size); } - - c.onMount(); } - /// Adds a new component to the components list. - /// - /// Also calls [preAdd], witch in turn sets the current size on the component (because the resize hook won't be called until a new resize happens). + /// Prepares and registers a component to be added on the next game tick void add(Component c) { - preAdd(c); - components.add(c); - } - - /// Registers a component to be added on the components on the next tick. - /// - /// Use this to add components in places where a concurrent issue with the update method might happen. - /// Also calls [preAdd] for the component added, immediately. - void addLater(Component c) { - preAdd(c); + prepare(c); _addLater.add(c); } + /// Prepares and registers a list of components to be added on the next game tick + void addAll(Iterable components) { + components.forEach(prepare); + _addLater.addAll(components); + } + /// Marks a component to be removed from the components list on the next game loop cycle - void markToRemove(Component c) { + void remove(Component c) { _removeLater.add(c); } + /// Marks a list of components to be removed from the components list on the next game loop cycle + void removeAll(Iterable components) { + _removeLater.addAll(components); + } + /// This implementation of render basically calls [renderComponent] for every component, making sure the canvas is reset for each one. /// /// You can override it further to add more custom behaviour. @@ -126,6 +123,7 @@ class BaseGame extends Game with FPSCounter { _removeLater.clear(); components.addAll(_addLater); + _addLater.forEach((component) => component.onMount()); _addLater.clear(); components.forEach((c) => c.update(t)); @@ -139,7 +137,7 @@ class BaseGame extends Game with FPSCounter { @override @mustCallSuper void onResize(Vector2 size) { - this.size = size; + this.size.setFrom(size); components.forEach((c) => c.onGameResize(size)); }