1
\$\begingroup\$

I have a 2D-Array representing my world. I want to divide this huge thing into smaller chunks to make collision detection easier.

I have a Chunk class that consists only of another 2D Array with a specific width and height and I want to iterate through the world, create new Chunks and add them to a list (or maybe a Map with Coordinates as the key; we'll see about that).

world = new World(8192, 1024);

Integer[][] chunkArray;

for(int a = 0; a < map.getHeight() / Chunk.chunkHeight; a++)
{
    for(int b = 0; b < map.getWidth() / Chunk.chunkWidth; b++)
    {
        Chunk chunk = new Chunk();
        chunkArray = new Integer[Chunk.chunkWidth][Chunk.chunkHeight];

        for(int x = Chunk.chunkHeight*a; x < Chunk.chunkHeight*(a+1); x++)
        {
            for(int y = Chunk.chunkWidth*b; y < Chunk.chunkWidth*(b+1); y++)
            {
                // Yes, the tileMap actually is [height][width] I'll have
                // to fix that somewhere down the line -.-
                chunkArray[y][x] = map.getTileMap()[x*a][y*b];
                // TODO:Attach to chunk
            }
        }

        chunkList.add(chunk);
    }
}

System.out.println(chunkList.size());

The two outer loops get a new chunk in a specific row and column. I do that by dividing the overall size of the map by the chunkSize.

The inner loops then fill a new chunkArray and attach it to the chunk. But somehow my maths is broken here.

Let's assume the chunkHeight = chunkWidth = 64.

For the first Array I want to start at [0][0] and go until [63][63]. For the next I want to start at [64][64] and go until [127][127] and so on. But I get an out of bounds exception and can't figure out why.

Any help appreciated!

Actually I think I know where the problem lies:

chunkArray[y][x] can't work, because y goes from 0-63 just in the first iteration. Afterwards it goes from 64-127, so sure it is out of bounds.

Still no nice solution though :/

EDIT:

if(y < Chunk.chunkWidth && x < Chunk.chunkHeight)
    chunkArray[y][x] = map.getTileMap()[y][x];

This works for the first iteration... now I need to get the commonly accepted formula.

\$\endgroup\$
10
  • \$\begingroup\$ Is Chunk.chunkWidth a const int size? If so what value have you given it? \$\endgroup\$ Aug 19, 2014 at 13:53
  • \$\begingroup\$ Both, width and height are public static final Integer = 64; Sorry, I thought that was clear from my description (non-native speaker, sorry!) \$\endgroup\$
    – Borog
    Aug 19, 2014 at 13:55
  • \$\begingroup\$ You mentioned "Lets assume the chunkHeight" but if they are static finals then they cannot change, so assumption is not necessary. \$\endgroup\$ Aug 19, 2014 at 13:57
  • \$\begingroup\$ Ya, you're right. I cannot change them at runtime, but I can change them before compiling. But what I meant was the basic maths :) \$\endgroup\$
    – Borog
    Aug 19, 2014 at 14:01
  • 4
    \$\begingroup\$ This question has an XY problem. I think we could edit it to ask "How do I do X" (with your solution as an answer) instead of "What is the bug in my implementation of X". That would yield a more generally useful question and be a lot clearer to read. Do you think that would work? \$\endgroup\$
    – Anko
    Aug 19, 2014 at 14:23

2 Answers 2

2
\$\begingroup\$

Note that even though your chunkArray instances are all supposed to cover different areas of your world, their indices still all range from 0 to Chunk.chunkWidth and 0 to Chunk.chunkHeight respectively.

Therefore, you should make sure that whenever you access chunkArray the x- and y- indices do not go out of these ranges. The easiest way to make sure they won't is to actually change the two inner-most for-loops like so:

int offsetX = b * Chunk.chunkWidth;
int offsetY = a * Chunk.chunkHeight;
Integer[][] tileMap = map.getTileMap();

for(int y = 0; y < Chunk.chunkHeight; y++)
{
    for(int x = 0; x < Chunk.chunkWidth; x++)
    {
        chunkArray[x][y] = tileMap[offsetX + x][offsetY + y];
    }
}

A faster way to achieve the same thing would be to use the built-in System.arraycopy:

int offsetX = b * Chunk.chunkWidth;
int offsetY = a * Chunk.chunkHeight;
Integer[][] tileMap = map.getTileMap();

for(int x = 0; x < Chunk.chunkWidth; x++)
{
   System.arraycopy(tileMap[offsetX + x], offsetY, chunkArray[x], 0, Chunk.chunkHeight);
}
\$\endgroup\$
0
2
\$\begingroup\$

Here is my two cents:

All the work can be found on here too so you can run it and see how it works http://ideone.com/xKWAip

Separate it into pieces and you can see how it'll work with a wee access expression after flattening the initial map array.

Here is what I used to generate your map (at the moment it's square only but as long as your width and length are divisible by your chunk size you're fine):

public static int[][] GenMap(int mapSize)
{
    int[][] arrayStuff = new int[mapSize][mapSize];
    for (int x = 0; x < mapSize; x++)
    {
        for (int y = 0; y < mapSize; y++)
        {
            arrayStuff[x][y] = y + (mapSize * x);
        }
    }
    return arrayStuff;
}

Here we Generate the chunks by flattening the map array and then using a chunk map coordinate of (i, j) and a chunk coordinate of (x, y) to then look through x and y within i and j.

Once that is looped through you can use the expression: y + (x * mapLength) + (chunkSize * i) + (chunkSize * mapLength * j) to find the index of the flattened array, providing the values you need in a [0, 1, 2, 3], [16, 17, 18, 19], [32, 33, 34, 35], [48, 49, 50, 51] format for your chunk info.

public static List<int[][]> GenChunks(int[][] map, int mapLength, int chunkSize)
{ 
    int[] inputArray = new int[map.length * map[0].length];
    for(int a = 0; a < map.length; a++)
    {
        for(int b = 0; b < map[0].length; b++)
        {
            inputArray[(a * map.length) + b] = map[a][b];
        }
    }

    List<int[][]> chunksList = new ArrayList<int[][]>();

    for (int i = 0; i < mapLength / chunkSize; i++)
    {
        for (int j = 0; j < mapLength / chunkSize; j++)
        {
            int[][] newChunk = new int[chunkSize][];

            for (int x = 0; x < chunkSize; x++)
            {
                newChunk[x] = new int[chunkSize];

                for (int y = 0; y < chunkSize; y++)
                {
                    int offset = j * chunkSize * mapLength;
                    newChunk[y][x] = inputArray[y + (x * mapLength) + (chunkSize * i) + (chunkSize * mapLength * j)];
                }
            }

            chunksList.add(newChunk);
        }
    }

    return chunksList;
}

Example usage:

public static void main (String[] args) throws java.lang.Exception
{
    int mapSize = 8;
    int chunkSize = 2;

    int[][] mapArray = GenMap(mapSize);

    System.out.println("Start chunks");

    List<int[][]> chunks;
    chunks = GenChunks(mapArray, mapSize , chunkSize);
 }
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .