I'm working on a 2d adventure game where the player can explore a random generated map. It's working perfectly if I set it to be about 3000x1000 blocks, but this is too small. When I want to make a bigger map it trows an OutOfMemory error.
I store my map in a 3d float array where the matrix is the position on the world plus I need 2 more data for each block the type (int blockID) and the stored last update time (float elapsedTime).
This 3d array is the one what is too big and trows OutOfMemory error. The blocks that have made Objects are the ones that can be seen(~32x14 block) the other are just two number ID and elapsedTime.
How should I store the map data?
You have a three dimensional float array of the size [3000,1000]? Well thats two dimensions?
Ignoring that: that are 3 million floats with 8 bytes each (there seems additional overhead if you use Float insead of float) = 24 million bytes = 24 mega byte. Seems not too much for a usual memory in a pc.
May tunning the memory settings will help you temporarily: Java memory settings
To calculate the actual size you store may that SO question will help you.
From my experiences with tilemaps: yes, they can become large in memory even if you trim down every single byte possible. (think I was up to 8 - 12 GB ram in my experiments for the tile map array only.)
But in fact you most likely do not need all the data in memory all the time. Since you generate a map may try to store that created map in a file and load (and update on demand) only the area near the player. So you can limit your memory demand.
Possible improvements of the data structure of the tilemap
If you have a 3 dimensional map where the third dimension are tiles stacked up you still could use a short or integer array (depending on the needed amount of tiles) instead of a float array saving some bytes. The short/int indicates the tile type.
The tiles themselves can be stored in a seconds structure like an array which holds all the data needed for this specific tile type.
I have to guess but I think you used the float "as drawing position"? Iterating over the array while drawing gives you the x,y,z tile indizes and you could calculate the drawing position out ouf the tile index you already have at this point. Which makes it unnecessary to store them.
When your game has a map which is too large to fit into memory, then the default solution to the problem is to use chunks.
Divide your map into rectangular chunks which are about as large as the screen. Only load the chunk the player is in and the adjacent chunks into memory. When the player moves to a different chunk, persist the no longer needed chunks to the hard drive and unload them (which you do in Java by making sure that there are no variables anymore which point to them). When the player returns, load the chunks from the hard drive back into memory.
When your map is randomly-generated, then you can use the fact that the Java
Random class can be initialized with a seed value. When you call
new Random(seed) with the same seed, you get the same sequence of random numbers from it. So when you use a new Random object for each chunk you generate, then all you need to save about a chunk is the seed value and any changes to the chunk which happened over the course of the game.