I have finally become a vampire. My internal clock has drifted over to the 2 PM-6 AM timeframe, so I have breakfast when everyone is about to go home for the day. It's not so bad, it just feels like it's winter instead of summer because my days last about 6 hours. My new motto -- "If you know what day it is you're not coding enough" ;-)
AWT -- Atrociously Warped Toolkit
The Java coding has been going swimmingly with one exception: the dreaded AWT. This is the most poorly implemented widget toolkit I have ever seen -- and Swing isn't much better, being partially built on top of AWT. It's like having a choice of shooting yourself with a musket, or a giant liquid-cooled computer-controlled depleted-uranium-shooting musket.
The feature I have had the most trouble with is one that is often praised: the threading model. Java just makes it too easy to throw threads around. I see novice (and sadly, not-so-novice) programmers making a thread for every single object in their program. Besides being horribly inefficient, it makes your program that much more unpredictable. Programmers should treat threads like dynamite: safe when carefully arranged and all possible problems have been accounted for, but misuse it and ... boom.
I had the "boom" scenario working with the AWT. AWT has a separate thread that slings events at you, and you have to process them. So far so good -- we love events, don't we? -- but what if you need your own "game loop" running at the same time? The obvious thing would be to create a separate thread that runs your loop, but it turns out that's not the best way.
The problem is that it's really tough to synchronize the game loop and the AWT event thread, and they stomp all over each other with unpredictable results. Sure, you can just throw the "synchronize" statement everywhere, but because the inner workings of the AWT also have their own synchronization, it's possible to get a deadlock and other nastiness. I didn't want that -- I just want my program to execute in a single thread, if possible.
Luckily I found a little trick to let me schedule my own game loop like it was just another AWT event, thus running everything serially in a single thread. The trick is to use the "EventQueue.invokeLater(Runnable)" method (great name huh?) It sticks your "Runnable" object on the end of the event queue, and when all other operations are done (repaints, keystrokes) it'll run your method -- in this case, it's an invocation of the game update loop:
But all-in-all, I'm quite happy with Java for now. The frame rate is pretty decent (PII-400 Win 98, JDK 1.2.2) considering I've made no attempt to optimize anything. Sure, right now I'm only drawing dots and lines, but there's some pretty nasty calculations going on under the hood. Which brings me to:
Floating Point And Your Quality Of Life
Quake did a lot more than kickstart the fully 3-D shooter -- it validated the use of floating point in gaming. Thanks to a bitchin' FPU in the Pentium, game designers were free to throw away all their fixed-point assembly routines, and recline in the forgiving arms of floating point numbers. No need to think anymore -- just take that cosine, square that root, divide that large number! Life is indeed good.
But that's not really the way it goes -- floating point numbers are another deceptively complicated topic. They may make some things simpler, but they introduce a world of complications. What do you have to worry about in integer math? Division by zero, multiplication overflow, addition overflow. That's about it. What snafus await you in floating-point math? NaN's, infinity, negative and positive zero, underflow, relative error, FP exceptions... and stuff that PhD's earn their stripes on.
I encourage all game programmers using floating point to read David Goldberg's paper "What Every Computer Scientist Should Know About Floating Point Arithmetic", accessible through the link below. It explains many pitfalls of using floating point numbers, the design decisions involved in the IEEE-854 standard, and more:
I will probably post some horror stories of my numerical algorithm experience in a few weeks. Physics really ain't my cup of tea, but the challenge and satisfaction of seeing algorithms in action is worth the headache.
Oh, I asked a question last week, and one guy got it right (well, I got one reply). Maybe it was too easy. Anyway the answer is of course "Rescue on Fractalus", and the alternate title was "Behind Jaggi Lines" -- a reference to the inability of consumer hardware to perform anti-aliasing in real-time.
'Til next time... the coffee is wearing off... millions of years of evolution telling me to sleep, sleep ... must code, must sleep ... zzzz ...