So can we do it? Can we do TDD in game development? Is professional software engineering so different from game development?
I look at this code and I see 6 parameters in the function, pointers to pointers, optional parameters, a clear command query violation, and NULL params that have to be checked against in the implementation. I say UGH! in SE. The const rule, and no input/output parameters is probably the single most important thing, in my eyes, that separate good code from beautiful code. It makes the whole system easier to understand and easier to edit or refactor . This code was called “Exceptionally Beautiful” in kotaku magazine, because they look for different things: - const - no in/out params
What does a Software Craftsman care about, and what do Game Developers care about? What about Fail Fast? Crashing is NOT an option as a game dev!
Can I really test drive this? Isn’t this just UI? Are the rules of the game, if you’ll pardon the pun, fundamentally different.?
This is a technical talk. Please ask questions. I cannot possibly guess anybody’s familiarity with the tools I’m discussing. XNA / MonoGame cameo. Maybe a live coding session if we have time.
I am a man with two backgrounds. I am a software craftsman at 8th Light with 15 years experience in traditional software development. I’m a TDD zealot. I value SOLID principles and Clean code. I even mentor others on this. This is who I am professionally. But I am also a wanna-be Indie Game Developer. I have a master’s degree in Video Game Development. I’m participating in the One Game a Month competition, I’m beginnng an 8th Light game design book club on Friday afternoons, and I’m somebody who has wanted to make games for a very very long time. So why don’t I? Well I have two choices. 1) Quit my job and go work for a big game company. Find out that they don’t care about the code the way I do, take a pay cut, and be unhappy. Full disclosure I did that out of college. Or 2) I can go the indie game development route. I can make games in my free time. I chose the second, or did I.
Who knows this game? About two years ago I sat down and tried to write a Kaboom! port for the iPhone. Instead of using the
So I wrote OCDSpec. Crap. And somebody else made a kaboom port. Crap 2.
I wrote this in a day.
I wrote this in a year. The game is actually slower, less fun, and about 5x the code as I got lost in abstraction after abstraction. Is Eskimo crap? No probably not, but what I should have done was tweaked Boberoids until I had something fun to keep. Then made a second game. THEN took out a bunch of libraries. Describe the plot of FTQ.
Meta Fail is a movie about making movies. It’s an Agile Consulting company making a tool for Agile Development. It’s developer who tries to make a game, but keeps making development tools.
I also missed the #1 test for a game - the is it fun! I still don’t know if Feed The Quinn is fun! So I really started to doubt my approach. Maybe TDD and what I call good design don’t matter. Maybe I’m full of shit! As I was trying to go through the One Game A Month Challenge. I needed something that would solve the question of “is it fun” FAST!
Cubicle Wars is a turn based strategy game that represents the real battle we all face - the one in your companies. Hackers/Salesmen and Office “Drones” face off in a new plan to eliminate the redundancies in your organization, to the death. Is it fun? I don’t know.
http://variancetheory.com/wp-content/uploads/2009/10/Detonator102shot.jpg So I decided to start with the Unity3D game development environment, and immediately realized that one of my TDD problems was solved - I don’t have to write the view. I create a scene, I drag and drop, I import models, etc. Rather than, as I did with HTML5, test driving an audio controller only to find out it doesn’t actually work when I hear the sound, I just drag and drop the file. But how do we add behavior in Unity.
Unity has scenes. Objects are bound to scripts in scenes in Unity. If you’re familiar with Entity Component Frameworks you’ll know this is a “component” and your objects are entities. Where do we start? With testing, can I open this file?
If you double click those C# files you get a project/solution - but you can’t add to it. It is autogenerated every time.
So instead I setup a library. I assumed Unity would have data - initial values, unit names, the geometry of the scene. I also decided it would have a layer of scripts or components. Then I would have my game logic. My actual game is defined in the Game Logic, and all talk is done through interfaces. I have an assembly that has no Unity dependencies. Win! (Yes I realize I could have used NUnit for that)
Even better I can put the assembly right in the project, and the project then builds it. This means I can use any assemblies I want - provided they are built with mono on .NET 3.5. So this does mean I’ll need to build my own support libraries and can’t just grab stuff. Show a quick demo of Xamarin running your tests.
There you can get started. Now if this was all I did, I’d be okay. I could create new objects, and then I could ask the objects for their data and I’d be in an improved TDD State.
Notice this test - THERE IS NO SIGN OF UNITY!
My first pass on the view did the “simplest thing” that could work. I had unity objects implement an interface, and pass themselves to their corresponding cubicle wars unit.
A lot of stuff like this. The game logic would callback into unity - through the interface so it’s in the circle. This worked okay until you got code like this: two units need to interact, but all that Unity had access to is the Unity component.
So you ended up with something like this. The unity object implemented the same interface as the cubicle wars unit, as well as it’s “view” interface. It got clunky fast. What I really wanted was an observer.
This is in the Cubicle Wars Library - that delegate is in the State Machine interface.
Seems reasonable enough
And I was happy! Developer happiness! Bind the Unity Object to the Domain Object, retrieve the events. Unity becomes responsible for data and events. No coupling! I won!
I had a new problem. That health indicator requires a GUIText game object, and it’s a DIFFERENT object than the one attached to the stapler. How to get the health to update when the stapler has been attacked? I would need to bind more than one Unity Object to the same Cubicle Wars Unit. I considered: - Firing events when units are created - but I’d need unique ids. - Having a lookup table - same problem. I needed a way to setup the game objects, and a way to bind unity objects. And remember I don’t create the objects (although I could instantiate a pre-fab). I really needed a way to “poll” the objects.
I really needed to start handling responsibilities. Somebody creates the domain object. Somebody else sends events to the game object. Some other objects respond to domain events and/or updates the view during the update loop (polling).
Go through the Unit Setup. - Highlight where you bind to the Unit Object. - Point Out Update - Router. - Controller. - Flashing View. - Health View.
Weren’t we going to talk about how to Unit Test in Unity? Well yes. The reason we’re doing this is because Unit Testing is supposed to be FAST! To run, and to write. As such we need to write our unity code in such a way that we can unit test all the codez!
We attach this to a ‘monostate’ game object - static data - because there can be only one. All controllers may need to have access to it.
Point out the “UnityObject” for the game data.
Remove the object when it is killed.
Demo your command line thing.
So could I do it? Did I resolve the conflict? Did I find out if “it’s fun?” Did I do worthwhile TDD? Is this code good enough?
Remember there is no Assert_Pretty Port to MonoGame? Fuck the Game Ended!
Wednesday I recreated this game. The hard part is getting models in.