I am used to coding in PHP but I am not really proficient with Java and this has been a problem for some time now. I expect it to be a fairly easy solution, however I cannot
1) Instead of an array you could use a Map<Integer, Map<Integer, Tile>>
or Map<Point, Tile>
, which would of course allow negative indexes
2) If you know the dimensions of your world from the start you could just modify your getter to allow the API to accept negatives and [linearly] transform them into positives. So for example if your world is 100x1000 tiles and you want (-5,-100), you would have WorldMap.getTile(-5,-100)
which would translate to return tileArray[x+mapWidth/2][y+mapHeight/2];
which is (45,400)
you could try a QuadTree (nice example here: http://www.mikechambers.com/blog/2011/03/21/javascript-quadtree-implementation/ )
I wrote a couple of experimental spare data structures in Java that you might be interested in.
The most interesting one was the Octreap which is what I believe is a completely novel cross between a Treap and an Octree, which had the following features:
How about dividing your map into chunks (yes, Minecraft fans, I know where this is used as well :P)? So you have two coordinate systems, both with the same origin:
x/y
coordinatesc1/c2
chunk coordinatesA chunk is always a fixed size of real world coordinate (say 128x128). Then you have a class Chunk
where you have a fixed array (128x128) with all the information for every pixel. And you store your chunks into a Map<ChunkCoordinates, Chunk>
as was already explained by others. I would recommend a HashMap
.
Whenever your player is in a certain region, the neccessary chunks are loaded from the map and then you can access the fixed size array in there. If the chunk knows, where it is placed in x/y
coordinates, you can even have some support function like Pixel Chunk#getPixel(long x, long y)
or so...
Btw: This also gives you an easy way to postpone generation of the whole world until it is really needed: At start, nothing is generated and as soon as a Chunk
is accessed in the map, that is not yet generated, you can just generate it then. Or you could fill it up at startup if that's easier for you. (filling an infinite world will take a long time though, even if it is pseudo infinite)
The hashmap style solutions are terrible for adjacency calculations, they require an iteration of the entire dataset.
Something like a quadtree or octree is perfect EXCEPT that it's not infinite, it's an arbitrary size (world of difference there).
However if you think about it, an ArrayList isn't infinite, it's just an arbitrary size that grows, right?
So a quadtree is sparce and pretty good ad adjacency calculations, except for the "infinite" provision it's perfect. Why not just use one of those sized to 100x what you think you might need (it's sparse, not really a big deal). If you ever get to the point where you are near the edge, allocate a new quadtree that is much bigger.
I believe if you are careful (you may have to implement your own quadtree) you can "upgrade" the quadtree with very little effort and no copying--it should be simply a matter of prefixing all your existing addresses with some bits (the addresses are in binary, quadtrees each bit represents dividing the existing universe in half in one dimension or the other).