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
If you want to be really fast and really scalable definitely go with a Sparse Octree.
http://en.wikipedia.org/wiki/Octree
I am not aware of any implementations in Java, but it is trivial. Just store in a single byte a bitfield for which nodes are currently linked and use a linked list to keep those references (for each Octree-node a separate list of max. 8 entries).
Trees, Quad Trees, Binary trees, red and black trees - and all other kinds of trees are USELESS for you (unless you are planning to have a map with a huge forest).
Specialized data structures have their specific uses. Unless you can come up with a good reason why your game needs a spatial index, don't build one. If your typical scenario is "iterate over the visible area, find out what tile is visible at each of the squares", then you need a structure that gives you a quick, random, access to a value stored under a specific key. Such structure is a HashMap (what PHP uses is a kind of a LinkedHashMap, but you were probably not using the "linked" part).
You need to follow xephox's advice (and give him the credit), and that is:
The best thing: if you keep using the Map interface, you will not be locked out, and you will be able to make a lot of improvements. Like wrapping the HashMap into an object that creates parts of the map using some algorithmic techniques.
I'm not an expert in game programming, but if arrays are OK, you could simply translate your coordinates from (-x, +x) to (0, 2x) (idem for the y axis).
Or if you're used to associative arrays like PHP has, the use the corresponding structure in Java, which is a Map (HashMap would be OK) : define a Coordinate
class with appropriate equals and hashCode methods, and use a HashMap<Coordinate>
. Making Coordinate immutable makes the code more robust, and allows caching the hashCode.
You probably want to use an implementation of Map. HashMap, SortedMap, etc depending on how much data you intend to store and your access patterns (Sorted Map is very good for sequential access, HashMap is better for random access).
You can either use two-dimensional Maps or munge your 2-d indeces into a key for a 1-d Map.
This is two separate questions: how to simulate negative array indicies so you can have an "infinite" map, and how to store tiles efficiently.
On the first question, one hack would be to maintain four separate matricies (matrixes?), one for each quadrant. Then all the indexes can be positive.
On the second question, you need a sparse map. One not-very-efficient way is to have a hashmap of hashmaps. In fact, that could solve the first problem as well:
HashMap<String, HashMap> x = new HashMap()
HashMap<String, Tile> y = new HashMap()
// get the tile at coordinates 1,2
Tile myTile = x.get("1").get("2");
// this would work as well
myTile = x.get("-1").get("-2");
You could do your own Map implementation that took integers as keys and was much, much more efficient.
I came to this thread with the same problem, but my solution was to use Map/HashMaps, but these are one dimensional.
To overcome this, instead of using a map within a map (which would be messy and very inefficient) I used a generic Pair class (not something that you'll find in the stock java library) although you could replace this with a Position class (virtually the same code, but not generic, instead integers or floats).
So when defining the map: Map<Pair, Tile> tiles = new HashMap<Pair, Tile>;
For placing tile objects onto the map I used tiles.put(new Pair(x, y), new GrassTile());
and for retrieving the object tiles.get(new Pair(x, y));
.
[x/y would be any coordinate you wish to place (this allows negative coordinates without any mess!), "new GrassTile()" is just an example of placing a tile of a certain type during map creation. Obviously - as previously stated - the Pair class is replacable.]
Why not ArrayLists you may ask? Because array lists are much more linear than mapping, and in my opinion are more difficult to add and retrieve tiles, especially on 2 Dimensions.
Update:
For anyone wondering why there isn't a Pair() class in Java, here's an explanation.