Flutter for Game Development!? - Week 2

There’s something magical about Christmas that makes you barely productive despite all the free time you have. That’s why I’m continuing with my week 2 progress update 3 weeks after the last one 😁

My big goal was to have a playable MVP done in December and I… kinda did it. It’s in a very rough prototype state, but hey, you can play it from start to finish. Let’s recap exactly what that means: 

  • Automatic sign-in (anonymous) to enable progress and stat tracking

  • Matchmaking - create or join a game using a join code

  • Round flow:

    • Everyone picks a phrase from two presented to them
    • Everyone goes in a cycle of: draw phrase/pass notebook/guess drawing/pass notebook
    • When finished, everyone presents their notebook ‘story’ to the group, one by one
    • Everyone votes for the funniest notebook
    • The host chooses whether to start another round or finish the game

Obstacles

State management turned out to be quite complex in this game, especially as this is a live multiplayer game, where other people’s actions affect your state. For example, there is a lot of ‘waiting’ for everyone else to finish drawing/guessing. That being said, I had to make some initial decisions, two of which I'm not quite happy with. 

Navigation

Usually in apps, it's the user’s actions that drive navigation. For example, you press a button to open a page. Here, however, you are led through a linear sequence of screens with transitions happening ‘automatically’ when the app detects the correct state change in Firestore. 

I initially decided to go with page-based navigation, so that each page can navigate to the next page if requirements are met. However, I am not confident this is the way to go anymore. The problems I foresee are:

  • If the user closes and reopens the app mid-game, they should be presented with the correct screen. This wouldn’t work well now, as, for example, stage 1 would have no awareness of later game stages to navigate to.
  • As there is no back-end, and all business logic is handled on the client side, there is a possibility the app will enter some kind of lock state, and without a single mastermind navigator logic, it might be difficult to recover from this.
  • Most of this game doesn’t make use of the typical application navigation stack, and each page needs to completely replace the last. That being said, it doesn’t feel ‘right’ to have a traditional navigation logic scattered in all views that get instantly disposed of.
  • It’s difficult to understand the flow of the game when it’s all defined in different files.

That being said, it would be best to introduce an underlying service that handles screen changes based on the current game state. This should make it easier to understand and debug game flow, as well as handle unexpected issues.

Firestore model structure

At first, I used one collection for all game objects and contained all data within the game documents. This was done on purpose, as it allowed me to develop really fast and focus on the actual game flow, exploring what was actually needed. Now that I have the skeleton ready though, I know I need to revisit this before the project grows.

Each game contains players and rounds. A round contains notebooks (one per player), and a notebook contains notebook entries. Notebook also has vote data which in turn populates round winners and game winners. This is a lot of data, and even viewing this in Firestore is problematic.

What I envision is something along the lines of: 

/games/{gameId}

- core game data (id, hostId, joinCode, etc.)
- currentRoundIndex
- matchMakingState
- winnerIds

/games/{gameId}/players/{playerId}

- player data

/games/{gameId}/rounds/{roundId}

- round core data
- status
- winnerIds
- words mapping

/games/{gameId}/rounds/{roundId}/notebooks/{notebookId}

- notebook core data
- votes

/games/{gameId}/rounds/{roundId}/notebooks/{notebookId}/entries/{entryId}

- entry data

Benefits:

  1. Better performance - loading only data I need
  2. Easier transactions/updates - don't need to update the entire game doc
  3. Prevents hitting Firestore document size limits (1MB)
  4. Simpler queries for specific data
  5. Easier ‘debugging’ as I will be able to view those documents in the browser

Luckily I already have separate providers and state models for each section of the app (game, round, voting, etc.) so this change should only require changes in the service layer, without affecting providers and the UI code at all.

Next steps

The things I mentioned are necessary to maintain a live app and avoid pitfalls, though they barely affect the look and feel of the game. Right now my priority remains to ship this project and what I need is polish. My next steps will be to implement a nice ‘gamey’ UI and to flesh out the phrase-generating service as it keeps serving the same 10 words over and over again. After I’ve done it, I should be able to finally test it with more people!

Image source: stickymudandbellylaughs