flame-engine / flame

A Flutter based game engine.
https://flame-engine.org
MIT License
9.23k stars 902 forks source link

Create withContext helper on Game #1523

Open erickzanardo opened 2 years ago

erickzanardo commented 2 years ago

What could be improved

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

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 commented 2 years ago

cc @felangel @alestiago

alestiago commented 2 years ago

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?

erickzanardo commented 2 years ago

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

st-pasha commented 2 years ago

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);
  }
}
spydon commented 2 years ago

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.

erickzanardo commented 2 years ago

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?

spydon commented 2 years ago

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