Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split 1d array into chunks

Tags:

java

arrays

I am trying to not load my entire tile based map into memory to save RAM client side. The map will be huge and already is requriring 1GB client side (multi-layered map).

I have gotten some perspective on Game Dev SO. I am trying to Load zones/chunks of my game map into memory (i.e. 300x300) and then when the player moves 100 steps shift the array and load 100 new tiles depending on direction. I have tried to work on a scaled version of this and now have a generic question.


I need help when the playerX/Y coordinates are on the perimeter of the map (which causes the chunk to be outside of the map)

Here is what I have come up with so far (note: player is in center of chunk & chunk always odd number sized)... It has the following issues(when the character is on the edge of the map):

  • change characterX/Y to 0,0 and the bottom left(0,2) coordinate will incorrectly be 7

    0, 0, 0

    0, 1, 1

    7, 1, 8

  • change characterX/Y to 8,8 and the top right(2,0) coordinate of the chunk will incorrectly be 6

    1, 1, 6

    1, 1, 0

    0, 0, 0

Here is the SSCCE:

public class MapChunkLoad {

    public static void main(String[] args) {
        short[] groundLayer;
        int mapWidth = 9;
        int mapHeight = 9;
        int chunkWidth = mapWidth / 3; //3
        int chunkHeight = mapHeight / 3; //3
        int characterX = 8;
        int characterY = 8;
        String map = "1, 1, 1, 1, 1, 1, 1, 1, 7, " +
                     "1, 8, 8, 1, 1, 1, 1, 1, 1, " +
                     "1, 8, 9, 9, 1, 1, 1, 1, 1, " +
                     "1, 1, 9, 9, 1, 1, 1, 1, 1, " +
                     "1, 1, 1, 1, 1, 1, 1, 1, 1, " +
                     "1, 1, 1, 1, 1, 1, 1, 1, 1, " +
                     "1, 1, 1, 1, 1, 1, 1, 1, 1, " +
                     "1, 1, 1, 1, 1, 1, 1, 1, 1, " +
                     "6, 1, 1, 1, 1, 1, 1, 1, 1";
        String[] strArr = map.split(", ");
        groundLayer = new short[chunkWidth * chunkHeight];

        //load chunk into groundLayer
        int arrayIndex = 0;
        int count = (characterX - (chunkWidth/2)) + ((characterY - (chunkHeight/2)) * mapWidth); //top left tile within chunk

        for (int y = 0; y < chunkHeight; y++){
            for (int x = 0; x < chunkWidth; x++){
                if (count > -1 && count < strArr.length){
                    groundLayer[arrayIndex] = Short.parseShort(strArr[count]);
                    System.out.println("arrayIndex[" + arrayIndex + "] = " + strArr[count]);
                } else {
                    groundLayer[arrayIndex] = 0;
                    System.out.println("arrayIndex[" + arrayIndex + "] = " + 0);
                }

                arrayIndex++;
                count++;
            }
            count += (mapWidth - chunkWidth);
        }

        System.out.println("");
        //print map grid
        int printcount = 0;
        for (int y = 0; y < chunkHeight; y++){
            for (int x = 0; x < chunkWidth; x++){
                if (x == chunkWidth - 1){
                    System.out.println(groundLayer[printcount]);
                } else {
                    System.out.print(groundLayer[printcount] + ", ");
                }
                printcount++;
            }
        }

    }
}

Thanks so much for any assistance.

like image 624
KisnardOnline Avatar asked Dec 22 '14 22:12

KisnardOnline


People also ask

How do you split a list into evenly sized chunks?

The easiest way to split list into equal sized chunks is to use a slice operator successively and shifting initial and final position by a fixed number.

How do you split an array of arrays?

Split 2-D Array Use split() Function split() function to split an array into more than one sub-arrays vertically (row-wise). There are two ways to split the array one is row-wise and the other is column-wise. By default, the array is split in row-wise (axis=0) . You can also use numpy.

How do you divide an array into 3 parts?

An efficient solution is to first find the sum S of all array elements. Check if this sum is divisible by 3 or not. This is because if sum is not divisible then the sum cannot be split in three equal sum sets. If there are three contiguous subarrays with equal sum, then sum of each subarray is S/3.


2 Answers

So I think your logic for checking if count is outside the bounds is faulty.

I think it needs to be more complex to account for that your array represents a 2D figure. I suspect for chunks larger than 3x3 you're getting a lot more errors that are really tricky to describe. Consider this map where each square's value is its index.

0 1 2
3 4 5
6 7 8

when in the top right corner (2) your map should look like this

0 0 0
1 2 0
4 5 0

but this will fail because count will in some cases be a valid index when calculating xValue*width+yValue, but you want that to be invalid (mapped to 0). Instead you need to keep track of both the X and Y components of count and make your map display a zero when either of those are out of bounds.

int countX = characterX - (chunkWidth/2);
int countY = characterY - (chunkHeight/2);
int index = countX + (countY*mapWidth)

then later. Instead of checking:

if (count > -1 && count < strArr.length)

check:

if( countX + x >= mapWidth || countY + y >= mapHeight)

EDIT:

As you can imagine this also changes how you count. You will also need a way to break your loop. Something like

if(x == chunkWidth && y == chunkWidth) break; 

I would be more specific, but I'm having trouble loading your original post to use as reference.

I think that fixes everything. Leave a comment if you have any questions. Good luck!

like image 54
Matt Avatar answered Oct 08 '22 17:10

Matt


I'm not sure if this is what you are looking for, but commonly you'd check for bounds inside your nested for-loop that fills the groundLayer, rather than checking with a count variable. That way will be much more robust. Something like this:

for(int y = 0;y < chunkHeight;y++) {
    for(int x = 0;x < chunkWidth;x++) {
        //Get the absolute position of the cell.
        int cellX = characterX + x - chunkWidth / 2; //Please check if this is correctly lined out.
        int cellY = characterY + y - chunkHeight / 2;
        if(cellX >= 0 && cellX < mapWidth && cellY >= 0 && cellY < mapHeight) { //Within bounds.
            groundLayer[arrayIndex] = Short.parseShort(strArr[cellX + (cellY * mapWidth)]);
        } else { //Out of bounds, put down a placeholder.
            groundLayer[arrayIndex] = 0;
        }
        arrayIndex++;
    }
}

Let me know if this was what you were looking for, and whether it works!

like image 1
Ghostkeeper Avatar answered Oct 08 '22 17:10

Ghostkeeper