views:

415

answers:

4

Hello,

I'm working on an isometric game for fast browsers that support <canvas>, which is great fun. To save information of each tile, I use a two-dimensional array which contains numbers representing tile IDs, like:

var level = [[1, 1, 1, 2, 1, 0],
             [0, 1, 1, 2, 0, 1],
             [0, 1, 1, 2, 1, 1]];

var tiles = [
    {name: 'grass',  color: 'green'},
    {name: 'water',  color: 'blue'},
    {name: 'forest', color: 'ForestGreen'}
];

So far it works great, but now I want to work with heights and slopes like in this picture: alt text

For each tile I need to save it's tile ID, height and information about which corners are turned upward.

I came up with a simple idea about a bitwise representation of all four corners, like this:

1011 // top, bottom and left corner turned up

My question is: what is the most efficient way to save these three values for each cell? Is it possible to save these three values as one integer?

+10  A: 

If you are trying to do something like the picture you don't need to store which corners are up/down as it can be deduced from the surrounding tiles.

For example if the current tile is height n and the height of the tile one up from the current tile is height n+1 then the current tile must have "top corner up"

Great! Thank you! I'll try to implement this. One more thought to complete your answer: is it possible to store height and tile ID as an integer?

Yes. You will need to use Bitwise Operations.

If you divided the integer equally between height and id using the first 16 bits for height and the rest of id

var id = tile & 0x0000FFFF; //mask the first 16 bits
var height = tile >>> 16; //shift the first 16 bits to the right

Setting can be done in a similar mannar

tile &= 0xFFFF0000; //remove id bits
tile |= id; //set new id

tile &= 0x0000FFFF; //remove height bits
tile |= (height << 16);
Yacoby
+1, but store corner heights rather than cell heights, to avoid ambiguity.
Marcelo Cantos
Great! Thank you! I'll try to implement this. One more thought to complete your answer: is it possible to store `height` and `tile ID` as an integer?
Harmen
Great solution. Though, more CPU expensive than storing the heights of each corner. (To determine height of all corners, it should do 9 height-lookups, with their bit shifts.)
Pindatjuh
@Pindatjuh Depending on the landscape allowed, it is quite probable that only 4 lookups would be required. The example above would only use require 4 which would give it a space advantage over storing the height of each vertex
Yacoby
A: 

If the height is in the [0, 255] range you can save 4 heights in a single integer using bit manipulation. In hex:

0xAABBCCDD, AA = first height, BB = second, etc..

To get the left-most height you would do ((0xAABBCCDD & 0xFF000000) >> 24) & 0xFF, which returns 170 (0xAA).

To set it: integer &= (0x00FFFFFF); /* Clear the value */ integer |= (height << 24);

Andreas Bonini
You can certainly do that, but remember that Javascript uses floating point for all numbers, so the efficiency you'd get in C++ or whatever really wouldn't apply.
Pointy
+1  A: 

Yes, you can:

var corners = 11; // binary 1011;
var topCornerUp = corners & 0x8;
var bottomCornerUp = corners & 0x2;

If you want to optimize it, though, consider what Yacoby said - you could store an array of the corners instead of saving them separately for each tile.

Alexander Gyoshev
A: 

Is the area rectangular? If it is you could simply store width and height of the area, tile length and an array of integers representing the vertex heights.

mdresser