Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Improve documentation at Klondike Tutorial Step 5 #3078

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
76 changes: 47 additions & 29 deletions doc/tutorials/klondike/step5.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,41 @@ FlameGame. The new world contains (almost) everything we need to play the game a
re-created during each of the above actions.


### A stripped-down KlondikeGame class
### KlondikeWorld Class

Here is the new code for the KlondikeGame class (what is left of it).

#### Introduction to `World` in Flame

In Flame, `World` is a special type of `Component` that can contain other `Components`,
such as Piles in the Klondike game. Think of `World` as the playground where everything
happens—dealing cards, arranging them, and player actions.

You can learn more about `World` in game programming here:

- An introduction to `World` in game programming: [Ecampus](https://ecampusontario.pressbooks.pub/gamedesigndevelopmenttextbook/chapter/what-is-a-game-world/)
- The concept of `World` in Flame: [Flame Docs](https://docs.flame-engine.org/latest/flame/camera_component.html#world)

We won’t go too deep here; just understand that `World` is where everything is managed in the game.


#### Creating `KlondikeWorld`

Let’s dive in! When the game starts, we’ll create a new “World” called `KlondikeWorld` to hold
all the components of the game. Each new game round will create a new `World`—like resetting the playing
field every time a new game starts. This ensures that everything is set up from
scratch, keeping the game fresh.


### Transitioning from `KlondikeGame` to `KlondikeWorld`


Previously, `KlondikeGame` managed all `Piles` and `Cards`. However, in step 5, we move this responsibility to
`KlondikeWorld` for better separation of concerns and cleaner code organization. This change improves the
structure by adhering to object-oriented programming principles, allowing for more modular and maintainable code.

#### Updating the `KlondikeGame` Class

Now, we modify the `KlondikeGame` class to utilize `KlondikeWorld` instead of Flame's default `World`. Here’s the new structure:

```dart
enum Action { newDeal, sameDeal, changeDraw, haveFun }
Expand All @@ -435,27 +467,28 @@ class KlondikeGame extends FlameGame<KlondikeWorld> {
);

// Constant used when creating Random seed.
static const int maxInt = 0xFFFFFFFE; // = (2 to the power 32) - 1
static const int maxInt = 0xFFFFFFFE;

// This KlondikeGame constructor also initiates the first KlondikeWorld.
// Constructor initiates the first KlondikeWorld.
KlondikeGame() : super(world: KlondikeWorld());

// These three values persist between games and are starting conditions
// for the next game to be played in KlondikeWorld. The actual seed is
// computed in KlondikeWorld but is held here in case the player chooses
// to replay a game by selecting Action.sameDeal.
// These values persist between games and are used as starting conditions
// for the next game in KlondikeWorld.
int klondikeDraw = 1;
int seed = 1;
Action action = Action.newDeal;
}
```

Huh! What happened to the `onLoad()` method? And what's this `seed` thing? And how does
KlondikeWorld get into the act? Well, everything that used to be in the `onLoad()` method is now
in the `onLoad()` method of KlondikeWorld, which is an extension of the `World` class and is a type
of `Component`, so it can have an `onLoad()` method, as can any `Component` type. The content of
the method is much the same as before, except that `world.add(` becomes just `add(`. It also brings
in some `addButton()` references, but more on these later.
#### Explanation of Changes

Ohhh, so what happened to the `onLoad()` method? Well, previously, `KlondikeGame` handled everything in the `onLoad()` method, managing all the game components like `Piles` and `Cards`. But now, to make things cleaner and more organized, we’ve moved that responsibility over to `KlondikeWorld`.

Everything that used to be inside the `onLoad()` method of `KlondikeGame` is now in `KlondikeWorld`'s `onLoad()` method. This keeps the code more modular, meaning it's easier to maintain and update. Instead of `KlondikeGame` getting messy with too many tasks, we let `KlondikeWorld` handle the game setup and logic.

And what’s this `seed` thing? Ah, good question! So, the `seed` attribute is like a magic key. It lets you replay the same game configuration by selecting `Action.sameDeal`. This is super useful when you want to give players the option to retry the exact same game setup. The `seed` ensures that the randomness in the game (like card shuffling) can be repeated exactly the same way. Think of it as a way to recreate the same starting point in a game.

So, with the `seed` safely stored in `KlondikeGame`, the `KlondikeWorld` can use it to keep everything consistent between rounds. If you choose `Action.sameDeal`, it will load the same shuffled deck and game state, letting you replay that round with the same starting conditions. Pretty cool, right?


### Using a Random Number Generator seed
Expand All @@ -466,21 +499,6 @@ reproducible behavior when you are in the development and testing stage. Here it
provide exactly the same deal of the Klondike cards when the player requests `Same deal`.


### Introducing the new KlondikeWorld class

The `class KlondikeGame` declaration specifies that this extension of the FlameGame class must
have a world of type KlondikeWorld (i.e. `FlameGame<KlondikeWorld>`). Didn't know we could do
that for a game, did we? So how does the first instance of KlondikeWorld get created? It's all in
the KlondikeGame constructor code:

```dart
KlondikeGame() : super(world: KlondikeWorld());
```

The constructor itself is a default constructor, but the colon `:` begins a constructor
initialization sequence which creates our world for the first time.


### Buttons

We are going to use some buttons to activate the various ways of restarting the Klondike Game. First
Expand Down
Loading