It’s looking good, particularly for your first 4k game. Graphics are always a compromise, particularly if you really need bitmaps, as there just isn’t space for decent sized sprite bitmaps. Scaling up and antialiasing might work for a soft focus look, but generally procedural graphics is a better bet.
The best gameplay strategy I found was to keep selecting and dumping sections at the edge, until I got a horizontal section. I wasn’t really getting the best use of the different sections, although that might just be me. There was one freeze up when the train tried to run off the bottom of the screen; probably some null pointer or array bound error.
Sound would be nice, but the calls to set it up eat 100’s of valuable bytes. My best Java1.4 effort is to create an AudioFormat, then a DataLine.Info for a Clip object and then use AudioSystem.getLine(Line.Info) and cast the result to a Clip. For Java1.5 there is a new AudioSystem.getClip() which gets a clip directly, although strangely that didn’t seem to save much space (I need to look at that more). Once you have a Clip, you can open it, using the AudioFormat and an array of byte data, which you can generate procedurally. Some people use a SourceDataLine rather than a clip and feed data directly into it. Trouble is, all these library calls use way too many bytes.
The Applet also provides methods to play .au & in recent JREs .wav files directly. Problem is these are really too big for 4k. I have tried creating a very small wave (a few milliseconds of sine wave) and looping it. This actually worked, but only gave me a continuous tone and still used too many bytes. I briefly wondered whether could generate a .wav procedurally, write it out to a temporary file and then read it back in using Applet’s play() method, but this requires signing the Applet, which is a pain.
There is also getToolkit.beep() which plays the default system beep; but you don’t know what this sounds like on the target system. There is also the sun.audio classes, which are still there in JRE1.6 and provided you give them 8000Hz uLaw 8bit data, work Ok in applets. The problem is they only work in the sun JVM and are not present in some Linux JVMs and including them will cause the applet to fail to load. Ok one can monkey about with the Classloader at run time, but this rather defeats the objective of saving space.