The Animation Problem
The BAWD rewrite has two underlying systems that combine to produce animations.
The first is the actual data updates, which are scheduled and queued. For simple line clears and gravity, the scheduling is unnecessary, but it enables some pretty neat visuals for abilities.
The second is a rendering layer that watches for those data updates and takes care of all the fiddly details that make the visuals progress sensibly for players.
For far too many hours, I was struggling to get player abilities to animate consistently. Once in awhile, a certain set of actions would render in a bizarre fashion. Because of the way the two systems interacted, it was quite difficult to step through in a debugger, so I ended up building a lot of small tools to expose the progression of the data in different ways.
Eventually, something pointed to the data update system as a potential source of trouble. I was surprised, because that code felt simple, and I had written something very similar for the previous iteration of BAWD.
After a week or so of trying to manually identify what was wrong in the data updates, I resigned myself to writing unit tests to simply validate every state progressed as expected. That meant a lot of additional work, because I hadn’t written the prototype code to be as testable as some would prefer. Oops! More on that below.
The unit tests were successful, and after a brief debug session I was able to correct the issue. A few more tests later and I was able to nail down what had been messing with the animation, and voila, I was free.
Prototypes and Unit Tests
Software development is an endless journey. Every issue is a new lesson, and this one I think was valuable.
I’m generally a big believer in unit/automated testing, but not a zealot. Sometimes unit tests are overkill and don’t provide a good ROI. That said, there are some pieces of code that benefit heavily from a test harness, and the BAWD data updates fit the description.
When prototyping, I think the “this needs unit tests” hurdle is much higher. My 25/100/300h system in particular demands that I minimize unnecessary work.
What I’ve learned will hopefully help me navigate these conflicting values.
My four take-aways:
- Writing testable code, within reason, should generally be a priority, even for a prototype. Even if I don’t write the unit tests, being able to quickly introduce them will allow me to make the right choice. This contrasts sharply with my reluctance to add them to BAWD, even when it became obvious they were needed.
- When a piece of code starts to require that I find inventive ways to debug it, that’s a vote in favor of adding unit tests.
- Certain kinds of code (data manipulation, especially) are often both easy and valuable to test. This is also a vote in favor of adding unit tests, even in a prototype.
- Unit tests are a great tool for countering poor focus (from sleep deprivation, stress, burnout, etc.).
I’m sure I’ll continue to refine my sense of when to add tests to prototypes and when not to, but this experience has prompted me to adjust the 25/100/300h plan: Now, as soon as a project passes the 100h hurdle (which could occur before 100h, but either way requires that it’s had a “successful” playtest), that project shifts to a quasi-TDD mode.
I won’t strictly require (yet) that the prototype be rewritten from the ground up, so it won’t be Proper TDD. But all functionality added after that milestone will be TDD, and existing code will have tests added to it as appropriate.
The point of this decision is that after passing the 100h hurdle, I make a commitment to finish and ship the game. If I am to produce low-defect games quickly, such testing seems crucial. It’s even more crucial when working on a portfolio of games simultaneously.
Anyways, here’s to lifelong learning.