Started coding a tile/sprite engine. Figuring memory/GC performance
will be important, so a lot of the objects, though serializable, hold
references to one another as a) indices, names, or other things and b)
"transient" object references that need to be initialized by calling a
load() method on the deserialized object. That way, loading one segment
of one level won't load all of the game data recursively into ram.
Loaded resources are cached with SoftReferences and retrieved with a
factory object that retrieves the cached object if possible, and if
null (either never loaded this session, or GC'd) goes to the hdd for
the files. Likewise, actual image data (png files) are loaded only
later, into BufferedImage objects. (java.awt.Image objects are
reportedly not portable across hardware architectures anyway -- never
mind PC to Mac, even PC to PC may corrupt if the video hardware differs
it seems); besides, I want to create art in a proper paint app, not
write a paint app as part of making the level editor.
I'll post performance results here once I have any. So far I have some
infrastructure and that's it.
Murphy's Laws of java programming:
1. There's always an exception to every rule, especially the
conventions about name
capitalization:
* All methods and member variables in the Java API begin with
lowercase letters.
* Likewise, class names and constants begin with uppercase ones.
* All use capitalization where a new word begins e.g -
getDoubleValue().
* Except, of course, for Character.isWhitespace (not isWhiteSpace).
2. There's always an exception you didn't think to catch.
3. After all the debugging and recompiling, there's always a
RuntimeException you
didn't think to catch.
4. And another. And another... And the API docs don't even declare
most of them.
(Some of the URL and URLConnection methods throw
StringIndexOutOfBoundsExceptions -- why?! Who knows!!)
5. The surest way to ensure a line of code is reached early in program
execution on
the first run attempt is to preface it with "// Can't happen."
6. Usually it's "throw new Error();" of course.
7. Whatever the participants in the ongoing debate about reference
size may think,
the actual empirically-determined size of a Java reference is about
3 megabytes.
8. If the process size is under 50MB, something has gone horribly
wrong with your
program and it actually isn't loading any data or doing anything.
9. If the app seems to have hung and you're sure it's an infinite loop
it will turn out just
to be slow. If you think it's merely slow and leave it running
overnight, it will be dead
by morning and the debugger used on a subsequent run will show you
two
suspended threads, surely in a deadlock. If on the other hand you
suspect
deadlocking and implement a very involved system of deterministic
symmetry-breaking in determining resource locking order, complete
with more
debugging, it will turn out that a loop in a completely unrelated
part of the program
never met its termination condition.
10. And, of course, it is probably a while (true) loop in which you
simply forgot to insert
a break, throw, or return statement, rather than some complex
situation involving
circular object graphs that even a reasonably intelligent
programmer might be
expected to miss.
(Speaking of deterministic symmetry breaking, it would be nice if Java
had a "synchronized(x, y, z, ...) { foo }" syntax that locked the
listed resources in a fixed order -- unspecified and legally considered
"JVM implementation dependent" but almost invariably simply in
ascending order of their machine address pointers, compared as
integers...)