I program stuff.

Wednesday, March 08, 2006

I'm an indie game developer. In that space everyone does C++, and badly. In my day job I do enterprise applications in Java mostly, at least lately. I've done a lot of Visual Basic, ASP, SQL, and COBOL in my day. The Java we do is okay in my day job. But the game engine that we've used in C++ can be horrible OOP. Thinks like non-moving NPC object that knows how to navigate around a maze and has all the data structures for doing it in memory but never ever needing to use it because it extends from the AIPlayer class so we can get its scripting hooks. Huge objects with rotten cores, a.k.a: Undead Hulking Classes.

The game industry is hooked on C++ to a fault. I found myself longing for the days when it was all Assembly; at least people then knew better what their code was doing. Also C++ has always been a pain to write for a number of reasons. C is better but I never quite got the point of .h header files, and they are such a pain to maintain but they are pretty much necessary if you want to write a program longer than a page long. Anytime I have to write out a definition of something twice is annoying. (I know one is a definition and one is a declaration; but common, really. What am I going to declare about that function if not its definition?) Writing the .h header files feels like I'm writing a cross-reference for my code for the compiler, which the compiler is obviously already doing to my code anyway otherwise it wouldn't complain when it finds that my hand written cross-reference doesn't match its cross-reference. Don’t get me started on the unnecessary mess of pointers. Pointers to pointers, oh my!

I got interested in Lerp, Jonathan Blow’s little (still experimental) language for building games. He seemed to be referencing Perl a bit so I checked that out a bit. I was impressed by a good portion of it, until I got to the object support, which made me go, "what?!" It looks like they used the references support all by itself to sort of hold up the whole object system, which sort of put it at distance from the rest of the language (a distance you have to travel to back and forth each time you want to use an object).

At one time I looked quite a bit into Lisp. The language is lovely if not obfuscated. All the nice little parens all lining up. vim even lines up the code for me automatically based on the parens! But when I start writing something that is of small to medium complexity, getting all of those parens to line up was making my eyes spin in their sockets. It’s a beautiful and complete idea that all of the processing of every part of the program is within a cascading tree of parens within parens going up into the sky (a good number of them recursively, and up into the sky with a beautiful tail-end collapse when it’s all done). But other than that beauty the language implementation within that is difficult and confusing, pre-fix mathematical notation, for instance. And while seeing every bit of code as containing other code, while it makes sense algorithmically it is hard to conceptualize because although it makes sense that you can do that algorithmically because it implies an order, it is easier for most people to see it in a just a simple list of instructions. Perhaps I just don’t get Lisp. Every time I thought I was close to getting it there was some weird syntax like even the simple "(+ 2 (* 3 4) (- 2 (* 3 2)))" that would just take too long to read or write and I would start to get fears about trying to maintain that mountain of parens stacked up like a pile of so many needles.

I started making notes of what I would want in a language. I tried to image what I’d like to write to make the program work. I wrote up some notes in vim (for some reason vim is fascinating to me lately, probably because toolbars and drop down menus always seemed like a UI hack to me).

While I was learning Perl I heard about Ruby. I went to Why’s (poignant) guide to Ruby to check it out a bit and to take a break from Perl because I just heard about Perl’s OO hack into the language and was displeased with it for the moment. I’d probably come back to it after seeing what this Ruby is all about. Someone somewhere said it’s got a great OO system. Besides he says that this Why person is some sort of genius. I pursued a bit. First saw a bit of code that didn’t look like OO to me at first but somehow I knew exactly what it did.
5.times { print "Odelay!" }

-- (quoted from the guide.)
Interesting. Then I started reading. Because Why’s guide is somehow poignant. Then a bit later,
['toast', 'cheese', 'wine'].each { |food| print food.capitalize }
Oh my, oh my. Would you look at that? That’s a bit like something that I was wanting, the ability to pass in a group of thing so each of the things are passed into a function or something one at a time. Not the quite way I was thinking, but this seems prettier, much cleaner than the goofy first draft syntax that I was thinking of. Then he’s saying that the 5.times from the first example means that the .times is a method on the object 5. WOW! 5 is an object! 25 is an object, and so is 26, etc. It makes perfect sense. But I never would have thought of that syntax, maybe something more overt like Java? "new Integer(5).times()". But then how to get that { print "Odelay!" }part in there? Hmm, function-pointer? (yucky!). Everything is an object, even the numbers. Later in the book I noticed that the type system that is so overbearing in C and in Java is gone all of the sudden but I never am wanting to define them in such a way because it seems very apparent what everything is already. Odd but comforting.

Then I found out that things like "answer = 5 * 6" is really syntactic sugar for "answer = 5.*(6)", or if you wanted "answer = 5.* 6", stunning, simply beautiful. Even "if ( things == 5 )" is actually "if ( things.==(5) )". Then I find out you can use full introspection on the objects like "p 5.methods" and see all of the methods available. Mind blowing. So this is what people mean by full object-orientedness? Aaaaaand you can modify those methods, or add new ones, even add methods the main class of everything, then there are these mixins (wow!), which looks like it would fix the whole Undead Hulking Class thing that plagues game programming lately. There are modules you can download to allow you to play with cool things. Oh there is one for OpenGL, and even SDL, or you can build your own, nice.

At this point I totally forgot about Perl, but I was reminded when I saw that Ruby has regular expression support as well. The one thing that it might not have that I had in mind was a modified reg-exp for querying against sets of objects rather than strings, but I’m pretty sure if it doesn’t have it I thing I could extend the base objects a bit to do what I’m looking for. Then my head is really spinning; not spinning as in spinning, but spinning as in flying. (I think why has somehow infected me.) I can’t believe this, I could extend the languages base objects a bit, and that is not even intimidating for me, I feel like the language is not treating me as a second class citizen. I’m on equal footing with the language and we are here to help each other.

What? Am I imaging all of this? That’s too good to be true. Usually I’m used to people like Gosling saying "No, no, no, you can’t do that with the language. That just doesn’t make since. Why would you want to do things like that anyway? How does that fit into the My Design Of Java? You need to do it this way, or this way. See how that fits nicely into my language. Oh the beauty of my design! You’ll just need to rearrange your programs logic structure a bit here, here, here, and there a bit, but only a bit." It’s as if Ruby’s Matz is saying, "Hmmm. That could work. I see what you mean. Not what I ever intended, but it could work nicely in your program. Let’s try just adding a few things to my base Object here and here and here a bit. Let me know if that’s helpful."

A language as a partner; that’s what it feels like, and I’m just starting to learn this language.

Then there was another thought that struck me. These days, maybe people only work in languages because its fun for them to work in that language. Truthfully, I don’t think here’s anything wrong with that at all. People usually pick some language for some reason or another but once the project gets to a certain point the language starts to get in the way somehow, or their design gets in the way and they have to do some ugly hack here and there to get it working. People sort of wince when they do it and posture around it; like, "I wouldn’t do it that way normally" or, "there just is no other way to boot strap it here", and accompanied by a large portion of self-flagellating don’t-do-as-I-have-done comments in the code. I think that this is inevitable in any program in any language and it needs to be welcomed rather than scoffed at. I think Gödel may have much to say here that would put those poor programmer’s minds at ease.

Maybe I should just use Ruby because it’s turning out to be fun to play with. Forget about any other goofy parameter like stability, or performance, or maintainability, what have you because all of those things are going to be a problem anyway in any language I choose, no question there. The only parameter that I can think of right now that is hard for me in a language is, will it run on the platforms I want? Ruby has that down (like just about any other language out there anyway). I have confidence that any parameter that comes threatening to stand in our way, Ruby and I will be able to face it. And maybe that is the true reason that people use the languages that they use; confidence in themselves with the language.

People always say use the right tools for the job, meaning use the right language for what you are doing. But for game programming it’s not a even a question, it’s a mandate; use C++. People all say there is really only one language for game programming right now. This always seemed a weird thing to say, since C++ is not geared toward game programming at all, as a language. They never had that in mind when it was developed. "Hey, Stroustrup, can I write games with C++?" "Um, sure I guess so." But for some reason that’s all anyone seems to write games in. I guess that’s why C++ is usually so abused in game programming because it just doesn’t fit quite right for the problem domain. But then again, not too many years ago the answer would usually be, use Assembler or maybe C, or a mix of both. So things will probably be different in the next few years. We’ll all be writing games in Lisp or something.