Tile Engine choice dilemma

Hello friends.
I am working on a tile engine for my RPG and I am kinda in a dilemma at the moment for it.
I went through lots of thinking and calculations of how to do ceratin things right.
Right now I am using a 3 Dimentional byte array[][][].
I am using a byte array because of map size and memory. A 3 layer 500x500 map would take 750k of memory away, but since Java can’t
do unsigned bytes, which is kinda annoying, I am stuck with 127 DIffernet types of tiles for one map. I thought about going to a three dimentional short array, but that would be taking lots of memory away just for a map. (3 layers 500x500 would be 3MB.).

I have thought about splitting it in half. By having the byte layer for sprites and the short layers for tiles.

Which would be the best away to approach a tile system. And do you think it would be safe to use shorts for today machines. My target machines would be at least 32/64 MB of memory and up. (Do you think I am thinking to low for today?) For some reason I always try to get my programs to take not much memory.

32 or 64 megs total system memory?.. if thats what your saying than thats way too low I’d say… if your program is going to require more than 64-128 megs for a map, you might consider keeping the majority of it on disk and loading in pieces as the player approaches them.

An array is an object. Every object has around 20 bytes of overhead. So your “byte[500][500][1]” array will take up 5 MB, not 750k.

Btw, a short uses 16 bits, not 32 as would seem from your math. Even so the arrays would be word aligned so it would use more.

The best way would be to use a single dimensional array. Make it big enough to fit the maximum number of tiles/layers:
byte map[] = new byte[500500MAX_LAYERS];

to get the layer at (x,y,layer) you do:
int layer = map[(y*500+x)*MAX_LAYERS+layer] & 0xff;

Also, even though java bytes are signed, they can still hold 8 bits of information. You just have to encode/decode between singed and unsigned.

How to get an unsigned value from a java byte:


int usignedval = ((int)myByte)&0xff;

How to put an unsigned value into a byte


byte b = (byte)255;

Do you need the cast? I think the & operation promotes the byte to an int anyway, since 0xff doesn’t fit in a signed byte.

Your probably right, but old C habits die hard. :slight_smile:

As an old C coder I really hate to leave things to coercion as (a) its less readable and (b) I have been stung once or twice in my coding
career by coercion not doing what I expect it to.

You can use buffers (from nio.*) if you want to get a big chunk of memory without the object overheads implicit in multidimensional Java arrays.

Well a 500x500 map is huge, if you think about it. Can you recall any RPG with a map that huge? Generally they are split up into smaller segments, I’d say 150x150 is a good maximum, although I suppose all this depends on the size of your tiles.

I am making an RPG with maps no larger than 100x100 that are 50 pixels each in 800x600 resolution. A 100x100 is enough for any area, but I only use something that large for an outside area, then do things like “west woods” “center woods” east woods" etc. The maps are small enough that the only loading a player notices when going to a new one is a less than a second black screen. Right now there is also a slight jump as it loads, but that’s just because we haven’t optimized yet.

Smaller maps means they are more annoying to design (tiling maps together can be frustrating) but load faster. If they are small enough then a user might not notice a load at all.

And I think worrying about memory less than 256mb is pretty obsurd for a large-scale RPG. I have an old iMac with 256mb that is 5 years old and can run almost everything. Anything older than 5 years probably can’t run Java anyway.

I would recommend allowing the editor to generate really large maps, say 500x500.

When the editor saves the map, allow it to save in chunks, of say 50x50. So then your map is comprised of 10x10 chunks. Then whenever a player is on a chunk, have that chunk loaded, and load any chunks that the player might see next. So for instance:

(player is red dot, green tiles are tiles loaded by game)

(An alternative to this is to always keep loaded the chunk the player is on, along with the 8 border chunks, but the method below minimizes your memory footprint and does a better job of amortizing your loading.

That’s a good idea. I think I may make it so that my level editor instead allows 500x500 and then automatically splits it into pieces, as well as automatically making links between them. Good idea.

(I was on vacation since last week)
Thanks for the help all. I will do the single dimention array idea and stick with bytes. The chunk idea is a great idea, I will keep that in mind and all other peoples’ ideas.

-thanks for the help-
Epo

Another advantage of using chunks is that you can then use a byte for your tile type, and have an array of 256 shorts per chunk that map your tile type to a short. For chunks of 50x50 this saves you 45% on the size of your tile type array, for the minor cost of some indirection when drawing.