Before I came to Atomic, I spent several years working in the video game industry. I left it for a number of reasons, but I wanted to still pursue game development as a side project.
When recently I started up a new game project, I went looking for a good engine. My requirements were:
- Cross-platform (PC, Mac, Android, iOS)
- Free to try
- Using a programming/scripting language I know and like (sorry, Lua fans)
I ended up picking the Unity3D engine. (Unity 4 just came out, by the way. I haven’t upgraded yet, but that’s where I’d start if you want to get into using Unity.)
Because of my work at Atomic, I’ve become a big Ruby fan. There aren’t really any viable cross-platform game engines that use Ruby — or Python for that matter — but when I saw that Boo was Python-like, I decided to try and write a game in Boo. Little did I know what was in store for me.
A Bridge Too Far?
I’m glad I decided to program in Boo, but in all honesty I wouldn’t recommend it for the Unity newbie, and definitely not for the person who is not a programming language nerd or incredibly patient. This is mostly due to two issues.
First, the language itself seems to be mostly stagnant. However, I’m trying to take some strides to change that.
Second, despite the fact that it is based on Python, duck typing is not the default. By default in Boo you must specify types, or the type defaults to
object. There’s a moderate amount of type inference, so sometimes you can omit the type, but not nearly as often as I would like. You can specify the type as
duck, and then an object will operate as a duck-typed object. Or you can implement the IQuackFu interface.
However, the sticking point here is that duck typing is extremely slow in Boo. You really don’t want to do it with anything that might run in a loop, or run every frame. If you are using the command line interface, there is a compile option to treat objects as ducks by default. But this won’t work if you are putting scripts in your Unity project, where Unity runs the compiler for you.
Waiter, there’s some TDD in my game!
Even with these drawbacks, I still thought it would be fun to give Boo a try. Additionally, I wanted to try out Test Driven Development (TDD) in games. I don’t think TDD is always a good fit for games, but for technical systems or gameplay systems with stable functionality (for example, an underlying state machine that is used by all your AI), you could make a solid case for it. I’m working on that type of underlying gameplay system in my game, so I decided to try TDD.
After looking around, I didn’t see any Boo libraries that really fit my sensibilities. UUnit was fairly close, but I prefer Behavior Driven Development (BDD) style tests. So I decided to make my own: BooSpec. It was originally intended to be similar to RSpec, but it ended up being somewhere in between that and Jasmine. You can see some examples on the github page. It runs on the command line, but it also has a few classes for plugging into Unity, so you can run your tests inside the game. This would be required for any test that uses MonoBehavior or GameObject, as you cannot instantiate those outside of a running Unity engine.
The next missing piece was a mocking library. I know mocking is a somewhat controversial practice, but I find it very useful for a number of reasons. Most importantly, without mocking, it is very difficult to do top-down TDD. This is doubly true if your editor doesn’t support hate-driven development (good luck finding one of those for Boo). However, when I tried to implement a mocking test in Boo using a C# library, I ran into a number of problems. And it irked me that I had to have the mocked type pre-defined to create a mock. So, despite the performance implications, I decided to use ducks for my types so I could make mocks. I figured that if it became an issue, I could always add those types later once they are known.
Again, not surprisingly, I could not find a mocking library in Boo that used duck-typing. So I rolled my own. It’s called BooMock, and it is based on Mocha. It’s fairly early in development, and at the moment only supports stubbing, not expectations.
But wait, there’s more!
I’ve also added a few more libraries as I’ve gotten my gameplay subsystem working.
BeadyEye (Boo Dependency Injection): The beginnings of a dependency injection framework. It defines member variables and a constructor that assigns those member variables from a Hash. You can specify the type of the members, or default to object. It will also attempt to guess the type based on the variable name.
BooYaml: I needed a YAML parser, and I wanted it to return plain Hashes and Arrays instead of the complex structures all the C# parsers returned. I wrote my own, but it was kind of a mess, so I swapped it out for a wrapper around a C# implementation. Additionally, I had to create a subclass of Hash to return because
ToString() on Hashes doesn’t show you anything useful.
The Way Forward
With these in place, I’ve been able to develop my code in the way I want. I’m sure I will continue to revisit and refine them as I go, and I’d be more than happy to take pull requests. But it’s high time I get to actually fleshing out the game. I need to have something to look at and play with before I run out of steam. I look forward to proceeding in that direction and providing an update as I interact with all the built in subsystems: graphics, physics, sound, and others.