Le Cube ◇ Mass Psychosis

The Blog

FMOD
ReaScripts for Cockos REAPER
Test-Focused Development
TDD-ing Avatar Health in C# and C++
Part 1&2 - The Avatar Health assignment
Part 3 - Implementation begins - C#
Part 3 - Implementation begins - C++
Part 4 - Taking Damage
Part 5 - The Dying part
Part 6 - The Replenishing part
Part 7 - The Increasing and Max part
Part 8 - Adding the Config
TDD-ing Chess in C#
Lifting

TDD-ing Avatar Health in C# and C++

Part 1&2 - The Avatar Health assignment

by Egill Antonsson
published on 2021 Dec 30
updated on 2023 Nov 13

Preparing the assignment

My TDD workshop

I did a workshop about TDD at work and for preparation I browsed the internet looking for a fitting assignment, and I came across TDD in Unity - Part 1 by Charles Amat, where he sets up his assignment: implementing the Life Gauge from Zelda: Breath of the Wild game.

I thought this assignment was fitting for the workshop, thus I read the Life Gauge page on the Zelda wiki (which was linked in the 'Part 1' post), and also played the game a bit, focusing on the Life Gauge behavior. But I did not go through the 'TDD in Unity' series, as I was running out of preparation time.

My focus and task order in both my preparations and workshop were:

  1. Write down the Life Gauge behavior from the user perspective (based on the wiki, and to a lesser degree my experience, as I'm not so good in Zelda: Breath of the Wild).
  2. Focus first on the (non visual) domain logic and implement all the requirements it should fulfill, as TDD is fully effective and effortless in the domain model.
  3. Afterwards, if there still was time, the focus would shift to the visual GUI, where the value of TDD likely would diminish the closer I got to the physical boundary of the screen, ending with just manually testing with my eyes. (More info in the Boundary layer section).

I only had time prepare the first couple of domain logic requirements and during the workshop we collaboratively completed those together before the time was up.

Comparing approaches on the assignment

After the workshop I was curious how Charles Amat solved it, thus I watched the whole TDD in Unity series. I both enjoyed and learned from watching Charles Amat live coding and implementing the Life Gauge and his end result solution is good and sound, and I thank Charles for his contribution. But I noticed that his focus and task order quite differed from mine, as he:

  1. Starts planning how to create the heart container in Unity from a GUI perspective.
  2. Then starts TDD-ing logic close to the GUI.
  3. Ends with TDD-ing the domain logic (Part 7 and Part 8) and simplifies the domain requirements from the Breath of the Wild.

Same assignment, but with a different focus

This is why I think it's worth doing another series with the same assignment, but with my focus, task order, and format.

My format will be blog posts focused on the TDD cycles displaying the appropriate code for each step. I'll demonstrate how the requirements and the cycles guide and shape the code and my reasoning, that will read like poetry of rhythmic RED GREEN REFACTOR loops (at least that's my ambition).

The Life Gauge behavior

The below list is user perspective behaviour summary from the Life Gauge page on the Zelda Wiki for the Breath of the Wild game. I've simplified some requirements to keep the scope within a sensible limit. I've also provided more detail where needed by playing and observing the game. (In real 'gameplay in development' scenario it's important to get the needed details of the requirements as early as possible from the game designer).

  • Definition and Start State
  • The Life Gauge measures Link's (the avatar) current amount of health.
  • Health is visually represented in the form of Hearts, and they are in fractions of 4.
  • The Life Gauge starts with 3 Hearts.

  • Taking Damage and Dying
  • Whenever Link takes damage he will lose a certain amount of Heart fractions equal to the damage points taken (always losing at least 1 fraction)
  • When Link loses all of his Hearts the game ends.
  • Link is protected from any damage that would instantly kill him as long as his Life Gauge is full and will instead be left alive with Hearth 1 fraction remaining.
    • However, if the damage is more than 5 Hearts in addition to his full Life Gauge, he will still die.

  • Replenish and Increase
  • The Life Gauge can be replenished by consuming certain items.
  • The Life Gauge can be increased by 1 Heart at a time.
    • Link's health will become full with the increase.
  • The maximum of Hearts is 30.

Model / View mapping of Life Gauge

Domain ModelView / GUI
(Avatar) Health Life Gauge
TBD later Heart (holds 4 Fractions)
Points Heart Fractions

This mapping is good to start on early: The Heart Container (with its Hearts and fractions) is a specific view representation of the Avatar Health, the domain model. This is a good start of separating the concerns and I'll break them further down below.

I'll apply the approach in the Boundary layer section, making sure that the code dependency is minimal and one-way:

  • the view can depend in minimal way on the model, but not vice-versa.
  • all the domain logic should be in the model.
  • the view should be thin and humble.

Thus when future change requests on the GUI arrive (which is likely in a real scenario) it will be effortless to handle as both the domain and its logic, and the model naming and terms, will remain unaffected. This also makes it effortless to display simultaneously more than one GUI representations
of the same model (which is quite common in game UI).