flipCode - Tech File - Steven Hugg [an error occurred while processing this directive]
Steven Hugg
Click the name for some bio info

E-Mail: hugg@pobox.com

   04/24/2000, Nocturnal Coding

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:

   public void run()
      t2 = t1;
      t1 = System.currentTimeMillis();
      long duration = (t1-t2);
      if (duration > MIN_UPDATE_TIME) 
         duration = MIN_UPDATE_TIME;
This is the method that's called during idle time. It figures out how long it's been since the last update, and consumes that many milliseconds' worth of events from the game event queue (different from the AWT event queue -- see my Apr. 3 update). Then it repaints the game view, and puts itself on the AWT event queue to be run again when idle. The net result is that the display is surprisingly responsive, the game runs at a constant speed, and there is no need to worry about synchronization.

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.

The Answer

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 ...

  • 05/14/2001 - Finally, The Project!
  • 10/03/2000 - Whereever I May ROAM
  • 07/08/2000 - Tech File Update
  • 06/12/2000 - Good Vs Evil
  • 05/24/2000 - Ego Surfing
  • 04/24/2000 - Nocturnal Coding
  • 04/12/2000 - Exploding Thought Giblets
  • 04/03/2000 - Event-Driven Games
  • 03/31/2000 - The Housemate Experiment
  • 03/28/2000 - Introduction

  • This document may not be reproduced in any way without explicit permission from the author and flipCode. All Rights Reserved. Best viewed at a high resolution. The views expressed in this document are the views of the author and NOT neccesarily of anyone else associated with flipCode.

    [an error occurred while processing this directive]