2
\$\begingroup\$

In my 2d platformer (made with Java and Slick2d), random maps are made by combining different segments together and displaying them one after the other. My problem is that I can't load too many segments or the game will run out of memory, so I want to load n number of segments at a time in chunks, then load the next chunk when the player comes near the end of one.

I've attempted to do this for a couple of hours now, but I just can't get it to work at all.

This is my chunk generation function where chunkLoad is the number of segments to load and BLOCK_WIDTH is the number of blocks/tiles each segment is across. Chunk1 and map are arrays of segments.

Random r    = new Random();
for(int i=0; i<chunkLoad; i++) {
    int id  = r.nextInt(4)+2;
    chunk1[i]   = new BlockMap("res/window/map"+id+".tmx", i*BLOCK_WIDTH);
}
map = chunk1;
chunksLoaded++;

The map is then drawn on the screen like this. tmap is a TiledMap object and each block/tile is 16 pixels wide

for(int i=0; i<chunkLoad; i++) {
    map[i].tmap.render((i * BLOCK_WIDTH * 16) + (cameraX), 0);
}

I can successfully load new chunks, but I can't display them in the correct position, nor the hitboxes.

Any suggestions? Thanks.

\$\endgroup\$
1
  • \$\begingroup\$ Is the problem really having everything in memory at the same time? Or is the problem drawing everything each refresh? Theoretically, the virtual memory manager ought to be taking care of swapping out the different segments. \$\endgroup\$ Commented Aug 25, 2012 at 6:19

3 Answers 3

0
\$\begingroup\$

Only display the squares the user will see. If your game 'map' is 100 X 100 and the user can only see 10 X 10, then there's no sense in displaying all 10000 squares. Here's some code that might answer your question or push you in the right direction:

public void draw()
{
    //Tile tiles[][] = new Tile[100][100]; // map array

    // player cords
    int playerX = 0;
    int playerY = 0;

    // display the map appropriatly

    int viewRow = 15;
    int viewColumn = 15; // 15 By 15 game board
    int tileSize = 10;

    int startX = (playerX % tileSize);
    int startY = (playerY % tileSize);

    int startRow = (playerY / tileSize) - 1; // -1 is for when the player is 'in between' tiles
    int startColumn = (playerX / tileSize) - 1;

    for(int row = 0;row < viewRow;row++)
    {
        for(int column = 0; column < viewColumn; column++)
        {
            int displayRow = row + startRow;
            int displayColumn = column + startColumn;
            // these are your row/column variables. This is where you would do your drawing.


            //ex
            //Rect rect = new Rect(row * tileSize - startX, column * tileSize - startY, ...);
            //canvas.draw(rect);

            //if you want to draw a specific tile or whatnot, you could do this:
            //canvas.draw(tiles[displayRow][displayColumn]);

        }
    }
}

That example is a little rough around the edges, but I hope it helped.

\$\endgroup\$
0
\$\begingroup\$

From your example, I assume you are making a 2D horizontal scrolling game.

If I assume your game scrolls from right to left (player moves toward the right edge of the screen), and that the CameraX value is 0 at the start of the game and increase when the player moves right, then your rendering code should be:

for(int i=0; i<chunkLoad; i++) {
    map[i].tmap.render((i * BLOCK_WIDTH * 16) - (cameraX), 0);
}

(I assume here that you're scrolling by redrawing your maps at an offset opposed to the Camera's offset).

That's a lot of assumptions, but there is a lot you're not telling about the way you handle things, so I'm just guessing.

Now about the way you dynamically load chunks of maps in a horizontal platform game: Your initial problem as far as I understand it is to not have all the maps in RAM, but only a subset, and load the new chunks when you need them. Here are a few consideration that may help:

  • You don't want your camera to move continually to the right; The trick is to have a small number of "chunk slots" and to wrap the camera back to the 0 position when you reach your last chunk-slot.

  • A commonly used trick is to render the last n-chunks (n being the number of chunks needed to fill your viewport) twice: once in the last chunk slots, and once in the first ones; This way, as soon as only those n slots are visible, you can warp the camera back to the first slots

Here is an example:

  • The viewport (part visible on screen) is the red rectangle (and you need 2 chunks to fill it)
  • We are using 5 chunk-slots (areas where a chunk can be rendered)
  • The 5 colors show where are the chunk slots, while the black number is the ID of the chunk being rendered (or in your case, its position in the list of random IDs you selected for your level)

explanation schema

Some additional considerations:

  • The minimum number of chunkslots needed is 2*n (n being the number of chunks needed for filling your viewport) but it means every single chunk will be rendered twice
  • The idea is to find the number of chunkslots which is reasonable depending of the RAM you can spare, and the number of double rendering
\$\endgroup\$
0
\$\begingroup\$

Maybe you should consider making a two dimensional array for the chunks, [0][0] being the top left chunk of the map. That way you always know which chunks are surrounding the player and if the player reaches an end, you can put the first chunks next to the last ones, if you want to make the map loop.

\$\endgroup\$

You must log in to answer this question.

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