mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 03:15:43 +08:00
Improvements on the overlay API (#592)
* Adding game to overlaybuilder and visible overlays * Fixing things * Format * Adding Renan's suggestions * Removing wrongly commited integration test files * Fixing active overlay when it is null * Update CHANGELOG.md Co-authored-by: Jochum van der Ploeg <jochum@vdploeg.net> * Adding some more changes from suggestions * Removing unnecessary elvis operator Co-authored-by: Jochum van der Ploeg <jochum@vdploeg.net>
This commit is contained in:
@ -1,6 +1,8 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
## [next]
|
## [next]
|
||||||
|
- Option for overlays to be already visible on the GameWidget
|
||||||
|
- Adding game to the overlay builder
|
||||||
- Rename retreive -> Retrieve
|
- Rename retreive -> Retrieve
|
||||||
- Use internal children set in BaseComponent (fixes issue adding multiple children)
|
- Use internal children set in BaseComponent (fixes issue adding multiple children)
|
||||||
- Remove develop branches from github workflow definition
|
- Remove develop branches from github workflow definition
|
||||||
|
|||||||
@ -5,8 +5,6 @@ import 'package:flame/palette.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ExampleGame extends Game with TapDetector {
|
class ExampleGame extends Game with TapDetector {
|
||||||
bool isPaused = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void update(double dt) {}
|
void update(double dt) {}
|
||||||
|
|
||||||
@ -25,14 +23,10 @@ class ExampleGame extends Game with TapDetector {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onTap() {
|
void onTap() {
|
||||||
if (isPaused) {
|
if (overlays.isActive('PauseMenu')) {
|
||||||
overlays.remove('PauseMenu');
|
overlays.remove('PauseMenu');
|
||||||
isPaused = false;
|
|
||||||
} else {
|
} else {
|
||||||
overlays.add(
|
overlays.add('PauseMenu');
|
||||||
'PauseMenu',
|
|
||||||
);
|
|
||||||
isPaused = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class MyHomePage extends StatefulWidget {
|
|||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
ExampleGame _myGame;
|
ExampleGame _myGame;
|
||||||
|
|
||||||
Widget pauseMenuBuilder(BuildContext buildContext) {
|
Widget pauseMenuBuilder(BuildContext buildContext, ExampleGame game) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 100,
|
width: 100,
|
||||||
@ -52,6 +52,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
overlayBuilderMap: {
|
overlayBuilderMap: {
|
||||||
"PauseMenu": pauseMenuBuilder,
|
"PauseMenu": pauseMenuBuilder,
|
||||||
},
|
},
|
||||||
|
initialActiveOverlays: const ['PauseMenu'],
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () => newGame(),
|
onPressed: () => newGame(),
|
||||||
|
|||||||
@ -191,4 +191,7 @@ class ActiveOverlaysNotifier extends ChangeNotifier {
|
|||||||
|
|
||||||
/// A [Set] of the active overlay names.
|
/// A [Set] of the active overlay names.
|
||||||
Set<String> get value => _activeOverlays;
|
Set<String> get value => _activeOverlays;
|
||||||
|
|
||||||
|
/// Returns if the given [overlayName] is active
|
||||||
|
bool isActive(String overlayName) => _activeOverlays.contains(overlayName);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,11 @@ typedef GameLoadingWidgetBuilder = Widget Function(
|
|||||||
bool error,
|
bool error,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
typedef OverlayWidgetBuilder<T extends Game> = Widget Function(
|
||||||
|
BuildContext context,
|
||||||
|
T game,
|
||||||
|
);
|
||||||
|
|
||||||
/// A [StatefulWidget] that is in charge of attaching a [Game] instance into the flutter tree
|
/// A [StatefulWidget] that is in charge of attaching a [Game] instance into the flutter tree
|
||||||
///
|
///
|
||||||
class GameWidget<T extends Game> extends StatefulWidget {
|
class GameWidget<T extends Game> extends StatefulWidget {
|
||||||
@ -36,7 +41,15 @@ class GameWidget<T extends Game> extends StatefulWidget {
|
|||||||
/// See also:
|
/// See also:
|
||||||
/// - [new GameWidget]
|
/// - [new GameWidget]
|
||||||
/// - [Game.overlays]
|
/// - [Game.overlays]
|
||||||
final Map<String, WidgetBuilder> overlayBuilderMap;
|
final Map<String, OverlayWidgetBuilder<T>> overlayBuilderMap;
|
||||||
|
|
||||||
|
/// A List of the initially active overlays, this is used only on the first build of the widget.
|
||||||
|
/// To control the overlays that are active use [Game.overlays]
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// - [new GameWidget]
|
||||||
|
/// - [Game.overlays]
|
||||||
|
final List<String> initialActiveOverlays;
|
||||||
|
|
||||||
/// Renders a [game] in a flutter widget tree.
|
/// Renders a [game] in a flutter widget tree.
|
||||||
///
|
///
|
||||||
@ -82,6 +95,7 @@ class GameWidget<T extends Game> extends StatefulWidget {
|
|||||||
this.loadingBuilder,
|
this.loadingBuilder,
|
||||||
this.backgroundBuilder,
|
this.backgroundBuilder,
|
||||||
this.overlayBuilderMap,
|
this.overlayBuilderMap,
|
||||||
|
this.initialActiveOverlays,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Renders a [game] in a flutter widget tree alongside widgets overlays.
|
/// Renders a [game] in a flutter widget tree alongside widgets overlays.
|
||||||
@ -89,11 +103,11 @@ class GameWidget<T extends Game> extends StatefulWidget {
|
|||||||
/// To use overlays, the game subclass has to be mixed with [HasWidgetsOverlay],
|
/// To use overlays, the game subclass has to be mixed with [HasWidgetsOverlay],
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_GameWidgetState createState() => _GameWidgetState();
|
_GameWidgetState<T> createState() => _GameWidgetState<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GameWidgetState extends State<GameWidget> {
|
class _GameWidgetState<T extends Game> extends State<GameWidget<T>> {
|
||||||
Set<String> activeOverlays = {};
|
Set<String> initialActiveOverlays;
|
||||||
|
|
||||||
Future<void> _gameLoaderFuture;
|
Future<void> _gameLoaderFuture;
|
||||||
Future<void> get _gameLoaderFutureCache =>
|
Future<void> get _gameLoaderFutureCache =>
|
||||||
@ -102,14 +116,30 @@ class _GameWidgetState extends State<GameWidget> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
// Add the initial overlays
|
||||||
|
_initActiveOverlays();
|
||||||
|
|
||||||
addOverlaysListener(widget.game);
|
addOverlaysListener(widget.game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _initActiveOverlays() {
|
||||||
|
if (widget.initialActiveOverlays != null) {
|
||||||
|
_checkOverlays(widget.initialActiveOverlays.toSet());
|
||||||
|
widget.initialActiveOverlays.forEach((key) {
|
||||||
|
widget.game.overlays.add(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant GameWidget<Game> oldWidget) {
|
void didUpdateWidget(GameWidget<T> oldWidget) {
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
if (oldWidget.game != widget.game) {
|
if (oldWidget.game != widget.game) {
|
||||||
removeOverlaysListener(oldWidget.game);
|
removeOverlaysListener(oldWidget.game);
|
||||||
|
|
||||||
|
// Reset the overlays
|
||||||
|
_initActiveOverlays();
|
||||||
addOverlaysListener(widget.game);
|
addOverlaysListener(widget.game);
|
||||||
|
|
||||||
// Reset the loader future
|
// Reset the loader future
|
||||||
@ -124,22 +154,26 @@ class _GameWidgetState extends State<GameWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// widget overlay stuff
|
// widget overlay stuff
|
||||||
void addOverlaysListener(Game game) {
|
void addOverlaysListener(T game) {
|
||||||
widget.game.overlays.addListener(onChangeActiveOverlays);
|
widget.game.overlays.addListener(onChangeActiveOverlays);
|
||||||
activeOverlays = widget.game.overlays.value;
|
initialActiveOverlays = widget.game.overlays.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeOverlaysListener(Game game) {
|
void removeOverlaysListener(T game) {
|
||||||
game.overlays.removeListener(onChangeActiveOverlays);
|
game.overlays.removeListener(onChangeActiveOverlays);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onChangeActiveOverlays() {
|
void _checkOverlays(Set<String> overlays) {
|
||||||
widget.game.overlays.value.forEach((overlayKey) {
|
overlays.forEach((overlayKey) {
|
||||||
assert(widget.overlayBuilderMap.containsKey(overlayKey),
|
assert(widget.overlayBuilderMap.containsKey(overlayKey),
|
||||||
"A non mapped overlay has been added: $overlayKey");
|
"A non mapped overlay has been added: $overlayKey");
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void onChangeActiveOverlays() {
|
||||||
|
_checkOverlays(widget.game.overlays.value);
|
||||||
setState(() {
|
setState(() {
|
||||||
activeOverlays = widget.game.overlays.value;
|
initialActiveOverlays = widget.game.overlays.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,11 +258,11 @@ class _GameWidgetState extends State<GameWidget> {
|
|||||||
if (widget.overlayBuilderMap == null) {
|
if (widget.overlayBuilderMap == null) {
|
||||||
return stackWidgets;
|
return stackWidgets;
|
||||||
}
|
}
|
||||||
final widgets = activeOverlays.map((String overlayKey) {
|
final widgets = initialActiveOverlays.map((String overlayKey) {
|
||||||
final builder = widget.overlayBuilderMap[overlayKey];
|
final builder = widget.overlayBuilderMap[overlayKey];
|
||||||
return KeyedSubtree(
|
return KeyedSubtree(
|
||||||
key: ValueKey(overlayKey),
|
key: ValueKey(overlayKey),
|
||||||
child: builder(context),
|
child: builder(context, widget.game),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
stackWidgets.addAll(widgets);
|
stackWidgets.addAll(widgets);
|
||||||
|
|||||||
Reference in New Issue
Block a user