I haven’t looked at my Global Game Jam project since the Jam ended, but I wanted to continue development and turn it into a more finished game. Over the weekend, I started.
Rushing and long hours hurt projects. (Duh.)
My intent was to refactor some things that I knew needed to be, but as I got into it, I ended up noticing more bugs that had escaped me during the Jam. Oh, how embarrassing. I’ll embarrass myself further by dishing the details here.
Bugs
- I thought I had fixed the Endian-ness of the Byte in the demo level, but as it turns out I didn’t. I fixed it in one place — the Create event — and forgot to make the same correction in the Step event — where the game spends 99.9999% of its time running. So, effectively I had it fixed only for the first 1/30th of a second of the game, and left it broken otherwise.Oops. See how code duplication can hurt you? If I’d refactored properly as I went along, the code would have existed in only one place, and fixing it the first time really would have fixed it.
- The victory condition check seemed to be broken. After I fixed the byte so that it was little-endian, I went back and played the level again, and sure enough found it easier (though it’s still difficult and largely luck-based) to get the Byte to output the ASCII character that matches the Clue. Only, something’s still not right… When I go hit the Executor switch, it’s still telling me they’re not matched. What gives?Well, it turns out the font that I picked, Joystix, renders identical glyphs for capitals and lowercase letters, making it a poor choice for my purpose. I might have noticed this if I’d been paying closer attention. The victory condition check actually does work properly, but since you have no way of discerning whether the clue is a capital or lower case letter, when you think you’ve matched it, you actually have just a 50-50 chance of being right.
- For some reason the logic switches sometimes get stuck “off”. This took the longest for me to figure out, because I kept looking in the wrong place. It turned out to be due to an improperly written switch statement which had one unhandled case that I didn’t account for.
Causes
So, these bugs really weren’t all that deep. Once found, the bugs were simple to fix. They were just mistakes that are typical of hastily written code that hasn’t been properly tested. Which isn’t to say that I didn’t do testing, just that I wasn’t able to do proper testing. I’m not sure whether to blame myself, the 48 hour structure of a Game Jam event, or Game Maker.
Well, the first two bugs were all me. They were logic errors on my part. I can blame the sleep deprivation and general rush of the Game Jam for contributing to my errors, but I really can’t have expected any tool I could have used to catch them. When I am exhausted, I make errors like this much more frequently than I normally do, and they become far harder for me to catch when I do make them.
I think this is a valid criticism of the Game Jam concept, but it’s also necessary to point out that Game Jam’s primary focus is not on producing quality code, or even quality games. So, to a certain extent, while it’s a valid point to make that building software this way isn’t the best way to do it, that doesn’t really diminish what is good about participating in a Game Jam. It’s foremost about experiencing the fun of building something cool. It’s also about showing that it’s possible to iterate very rapidly in game development. It’s about creativity and learning how to work effectively with small teams and limited resources. While code quality is important, and a development team could choose to make it a focus, it’s clearly an optional part of the weekend. Still, the better projects are more than likely going to be built with better quality code.
The third bug… well, ultimately, it was a user error with how I wrote my switch cases, but the lack of good debug tools in Game Maker do make it harder to find and fix errors. Game Maker really does not have proper testing and debugging features, apart from some very rudimentary variable tracing, and aborting and logging runtime errors, that’s all you get.
Prevention?
For the most part, the way you test in Game Maker is to run the project and try to set up the circumstances that you want to test, and watch closely as it executes and if something unexpected happens, try to infer from the behavior what is happening. If the program doesn’t crash outright when a bug is executed, it’s basically a perception check on the part of the tester to see if they bug is blatant enough to be noticed.
Subtle bugs, or rare occurrences, can be very difficult to detect. On top of that, it’s rather time consuming. And when you fix it, how you confirm that it’s fixed is more of the same trial-error process.
I’m not sure whether it’s possible to do Test Driven Development in the Game Maker environment. It might be, after a fashion. Like, there’s no way to set up a separate test suite project and rapidly have all events pass. But you could implement some functions designed to test your code, and then run them by sticking them into a special test room. It is possible to build yourself a “test room” where your test cases are set up in some defined, controlled manner and you can check each time you build to see if your latest changes to the project have broken any existing functionality. In fact, a good test room is a must with any complex game. But even then the test room will only help you to notice that a test fails, not tell you why it failed.
But even then, you’re probably not going to have total coverage. In some cases, a lot of of a game program’s behavior is actually emergent, rather than explicitly programmed, and I’m not sure how you could write a test routine for something like that.
Can bugs be good for the game development process?
Even if it is possible to reduce defects by using Test Driven Development in Game Maker, I’m not sure how feasible it is. Games are very complicated, and ultimately the real test of a game is how it plays, so to some extent all that time-consuming trial-and-error testing serves a purpose. It’s unlikely that any number of test rooms that you can build are going to be able to set up every single permutation that could possibly come to pass at runtime.
It’s easy to design certain aspects of game software, but designing “fun” into the game is not so easy. Often, what is fun is what surprises us, and what surprises us more than a program behaving in an unexpected manner? I’m sure countless times in the annals of game development, some unexpected program behavior was embraced as a feature or enhancement rather than classified as a bug and removed from the program.
Sometimes, Bug = serendipity
A good example of that from ASCIIboros is the way the player’s bit re-randomizes when you land from a stationary jump. The idea that the player even should carry a bit value around with him was something that came to me fairly late in the weekend. At some point, I realized that most of my bitwise operations required there to be some other value, since you can’t very well do Or, Xor, And, Add, or Sub with just a single value.
And where would that come from? Well, the easiest and most obvious thing to do was to make it a value that the player carries with them. I quickly implemented this, simply assigning a bit value randomly when the Player object is created.
I didn’t think about how the Player would change its bit value at first, but before it really even hit me that this would be useful and even necessary, the solution to this problem presented itself by way of a “bug” that I chose to adopt as a designed feature: When you jump vertically, upon landing the Player’s State Machine re-calls the bit assignment routine, resulting in a re-randomized value. Problem solved. Only, it was never a part of any design process.
I’m not saying that the bug was creative. But encountering this bug presented an opportunity which my creativity recognized, and found useful. Probably 99% of the bugs I fix don’t do this, but once in a while, they do, and sometimes they can be better ideas than the ones you I of deliberately. Now that I’ve adopted it and included it into my design, it’s no longer a bug.
Now, not all types of software projects want to have these kind of “accidental” design innovations come up during development. With game design, I imagine it’s much more allowable, since the game really doesn’t have to meet any specific real-world requirements; a game program’s output is the experience you have when you play the game, and as long as it’s more fun, that’s all that matters.
Of course you were writing business software, getting the output right is a lot more important, and probably needs to be defined in the designed much more carefully and precisely. It’s hard to imagine serendipity making payroll processing better, for example. Even so, if you’re too rigid with requirements and design, I think you’re closing yourself off to possibilities which are worth exploring when it comes time to muck about with code.
There are times when you can know ahead of time exactly what you want the program to do, and there are no questions that need to be answered during programming, or which you couldn’t have thought of ahead of time if you were just really, really smart. But perhaps those times are not as frequent as we might think. Particularly if “we” are Project Managers or Business Analysts.
Programmers are more than just adept at manipulating symbols to perform arcane calculations with mathematical precision. The good ones are often very creative thinkers in their own right. It’s important to recognize those types of developers and allow them freedom and to incorporate their creative process into your project management style.
And it’s not enough to include your programmers in the design phase of your development cycle (which you should be doing anyway). Sometimes design ideas present themselves during the process of building; we should be open to embracing good ideas whenever they present themselves. I’m not saying that all design innovations are going to be discovered through accidental defects in coding, either — oftentimes programmers will have good ideas come to them simply because they’re playing around with pieces of a project, and it’s a lot more stimulating to be playing with building blocks than it is to be looking at a blank design template.
If you haven’t played it yet, now’s as good a time as any to grab the ASCIIboros Demo from the Releases page and try it out. Windows only, sorry:/