flame icon indicating copy to clipboard operation
flame copied to clipboard

Create withContext helper on Game

Open erickzanardo opened this issue 3 years ago • 7 comments

What could be improved

Dealing with BuildContext in a Flame Game can be challenging because:

  • The GameWidget is who own it
  • It only becomes available on Game after it is attached to the GameWidget, so it is no ready on onLoad or onMount as one could expect

Why should this be improved

Having an easy access to the BuildContext opens many possibilities to the users, like readying ThemeData, a Bloc, l10n, etc.

Any risks?

None come to mind.

More information

A suggestion that I can think of, is an idea kind in line with how the Builder widget works for Flutter.

Idea 1:

gameRef.withContext((context) {
  // ...
});

The closure passed will be executed right way if the game is already attached, and if not, it will be queued for execution once the attachment happens.

Idea 2:

For this idea we would need #1522 to be working.

add(
  BuildContextComponent(
    children: [
      MyComponent(),
    ],
  );
);

That component would hook itself somehow on the game attachment and once the game is attached, it will add the components to the component three.

We probably don't really need #1522 for this to already have some value, but I it really shinning with we get that declarative API working.

Also I don't think one idea excludes the other, both could live together so the user could choose whatever makes more sense for their context.

erickzanardo avatar Apr 08 '22 23:04 erickzanardo

cc @felangel @alestiago

erickzanardo avatar Apr 08 '22 23:04 erickzanardo

I really need to have a deep dive into the code implementation.

My naive first question is: why shouldn't all Components behave like a BuildContextComponent. Is this because of performance?

alestiago avatar Apr 08 '22 23:04 alestiago

I really need to have a deep dive into the code implementation.

My naive first question is: why shouldn't all Components act like a BuildContextComponent. Is this because of performance?

Because of the lifecycle I explained above, it is only available after the game is attached.

So it will not be available during the first onLoad and onMount

erickzanardo avatar Apr 08 '22 23:04 erickzanardo

Idea 3: Use the game.mounted future to wait for the time when the game becomes fully mounted:

class MyGame extends Game {
  Future<void> onLoad() async {
    ...
    mounted.then(() {
      // buildContext is available here
    });
  }
}

Idea 4: Since all components are mounted to the game which is already mounted, the logic that needs to deal with buildcontext can be deferred to such a component that you add to the game:

class MyComponent extends Component {
  void onMount() {
    final game = parent as FlameGame;
    assert(game.buildContext != null);
  }
}

st-pasha avatar Apr 08 '22 23:04 st-pasha

It only becomes available on Game after it is attached to the GameWidget, so it is no ready on onLoad or onMount as one could expect

Since onMount is not run until the game is attached to the widget, the build context should already be available there today if you have a gameRef.

spydon avatar Apr 08 '22 23:04 spydon

Interesting, I was sure that onMount was before the attachment.

So, we could simply document that build context is not available on onLoad but it is on onMount?

erickzanardo avatar Apr 08 '22 23:04 erickzanardo

Interesting, I was sure that onMount was before the attachment.

So, we could simply document that build context is not available on onLoad but it is on onMount?

I think I was wrong, it seems like it is called directly after onLoad and before attach, I thought that it was called after attach (wouldn't that make more sense?). https://github.com/flame-engine/flame/blob/main/packages/flame/lib/src/game/game_widget/game_widget.dart#L147

spydon avatar Apr 09 '22 00:04 spydon