mirror of
https://github.com/flame-engine/flame.git
synced 2025-10-30 08:27:36 +08:00
feat: adding loaded future to the component (#1466)
* feat: adding loaded future to the component * fix: flame flare example game * docs * Update doc/flame/components.md Co-authored-by: Lukas Klingsbo <me@lukas.fyi> Co-authored-by: Lukas Klingsbo <me@lukas.fyi>
This commit is contained in:
@ -28,14 +28,19 @@ the `Component` remove method.
|
||||
The `onLoad` method can be overridden to run asynchronous initialization code for the component,
|
||||
like loading an image for example. This method is executed after `onGameResize`, but before
|
||||
`onMount`. This method is guaranteed to execute only once during the lifetime of the component, so
|
||||
you can think of it as an "asynchronous constructor".
|
||||
you can think of it as an "asynchronous constructor".
|
||||
|
||||
The `onMount` method runs every time when the component is mounted into a game tree. This means that
|
||||
The `onMount` method runs every time when the component is mounted into a game tree. This means that
|
||||
you should not initialize `late final` variables here, since this method might run several times
|
||||
throughout the component's lifetime. This method will only run if the parent is already mounted.
|
||||
If the parent is not mounted yet, then this method will wait in a queue (this will have no effect
|
||||
on the rest of the game engine).
|
||||
on the rest of the game engine).
|
||||
|
||||
A component lifecycle state can be checked by a series of getters:
|
||||
- `isLoaded`: Returns a bool with the current loaded state
|
||||
- `loaded`: Returns a future that will complete once the component has finished loading
|
||||
- `isMounted`: Returns a bool with the current mounted state
|
||||
- `mounted`: Returns a future that will complete once the component has finished mounting
|
||||
|
||||
### Priority
|
||||
|
||||
@ -62,14 +67,14 @@ class MyGame extends FlameGame {
|
||||
}
|
||||
```
|
||||
|
||||
To update the priority of a component you have to either just set it to a new value, like
|
||||
To update the priority of a component you have to either just set it to a new value, like
|
||||
`component.priority = 2`, and it will be updated in the next tick.
|
||||
|
||||
Example:
|
||||
|
||||
```dart
|
||||
class MyComponent extends PositionComponent with Tappable {
|
||||
|
||||
|
||||
MyComponent() : super(priority: 1);
|
||||
|
||||
@override
|
||||
|
||||
@ -54,6 +54,7 @@ class Component {
|
||||
ComponentSet? _children;
|
||||
|
||||
Completer<void>? _mountCompleter;
|
||||
Completer<void>? _loadCompleter;
|
||||
|
||||
@protected
|
||||
_LifecycleManager get lifecycle {
|
||||
@ -208,6 +209,17 @@ class Component {
|
||||
/// the lifetime of the [Component] object. Do not call this method manually.
|
||||
Future<void>? onLoad() => null;
|
||||
|
||||
/// A future that will complete once this component has finished loading.
|
||||
Future<void> get loaded {
|
||||
if (isLoaded) {
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
_loadCompleter ??= Completer<void>();
|
||||
|
||||
return _loadCompleter!.future;
|
||||
}
|
||||
|
||||
/// Called when the component is added to its parent.
|
||||
///
|
||||
/// This method only runs when the component is fully loaded, i.e. after
|
||||
@ -420,6 +432,7 @@ class Component {
|
||||
} else {
|
||||
return onLoadFuture.then((_) {
|
||||
_state = LifecycleState.loaded;
|
||||
_loadCompleter?.complete();
|
||||
});
|
||||
}
|
||||
return null;
|
||||
|
||||
@ -93,6 +93,30 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
flameGame.test('component loaded completes', (game) async {
|
||||
final component = _MyComponent();
|
||||
await game.add(component);
|
||||
final loaded = component.loaded;
|
||||
|
||||
await game.ready();
|
||||
|
||||
return expectLater(loaded, completes);
|
||||
});
|
||||
|
||||
flameGame.test(
|
||||
'component loaded completes even after the '
|
||||
'component is already loaded',
|
||||
(game) async {
|
||||
final component = _MyComponent();
|
||||
await game.add(component);
|
||||
await game.ready();
|
||||
|
||||
final loaded = component.loaded;
|
||||
|
||||
return expectLater(loaded, completes);
|
||||
},
|
||||
);
|
||||
|
||||
// Obsolete scenario, when we used to have a separate "prepare" stage
|
||||
flameGame.test('parent prepares the component', (game) async {
|
||||
final parent = _MyComponent('parent');
|
||||
|
||||
@ -19,8 +19,6 @@ class MyGame extends FlameGame with TapDetector, DoubleTapDetector {
|
||||
|
||||
late final MinionComponent minionComponent;
|
||||
|
||||
bool loaded = false;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
add(BGComponent());
|
||||
|
||||
Reference in New Issue
Block a user