Tuesday, July 11, 2017

2d - I can load new tiles but how do I load new chunks?


I have successfully been able to add new tiles and place random trees on a 2d map grid however I haven't used chunks. I just load a new tile when the player moves and save it to the map array. But I have had some issues with the forests. And I'm thinking chunks would solve my problem. The problem is my forest just appears on the map when the player moves left or up. But I want to focus on how to handle the chunks because I know if I get that right I'll be able to solve the other symptoms to the main problem. Here is a link to the game.


https://76295db93db3812642fa5ba984c042fa81ffc37c.googledrive.com/host/0B6H3TRExU5M9eEkyd2FreHhiNlU/



Here is how I generate new tiles. This runs every game loop and not sure if that is the best way to do it. Does this cause lag? The bottom of the function checks if the tiles need to be updated to forest graphics. I know this is probably the wrong way to do it but I maybe if I get the chunk thing figured out I won't have these issues.


map.update = function() {
for(var x = Math.floor(player.x - map.width / 2); x < Math.floor(player.x - map.width / 2) + map.width + 2; x++){
for(var y = Math.floor(player.y - map.height / 2); y < Math.floor(player.y - map.height / 2) + map.height + 2; y++){
//Surrounding tiles
var tiles = [];
//Check if tile needs to be generated
var check = function(x, y) {
if(typeof map.data[x] === 'undefined') {
map.data[x] = [];

}
if(typeof map.data[x][y] === 'undefined') {
map.data[x][y] = new Tile(x, y, map.generate.groundLayer(), map.generate.playerLayer(x, y), map.generate.aboveLayer(), map.generate.event());
}
//Add tile to collection
tiles.push(map.data[x][y]);
};
//Center
check(x, y);
//Top

check(x, y - 1);
//Top Right
check(x + 1, y - 1);
//Right
check(x + 1, y);
//Bottom Right
check(x + 1, y + 1);
//Bottom
check(x, y + 1);
//Bottom Left

check(x - 1, y + 1);
//Left
check(x - 1, y);
//Top Left
check(x - 1, y - 1);

//Check if there is a forest
/*
if(map.data[x][y].playerLayer === sprite.forest.topLeftCorner) {
tiles[3].playerLayer = sprite.forest.topRightCorner;

tiles[4].playerLayer = sprite.forest.bottomRightCorner;
tiles[5].playerLayer = sprite.forest.bottomLeftCorner;
}
*/

}
}
};

Answer



Your best bet is to not generate tiles but generate and manage chunks which contain tiles. If you think about chunks as a fundamental part of the design then the issue may go away.



I faced a similar issue in 3d with building my voxel engine.


You likely want to do something like ...


class Map { 
public Size Size { get { ... } }
public List { get; set; }
public Tile GetTileAt(int x, int y) { ... }
public Tile SetTileAt(int x, int y, Tile newValue) { ... }
}

class Chunk {

Tile[] Tiles { get; set; }
public Size Size { get { ... } }
public Tile GetTileAt(int x, int y) { ... }
public Tile SetTileAt(int x, int y, Tile newValue) { ... }
}

Then map just figures out the chunk on get and set calls and calls the same method on the chunk. The chunk looks at a subset of the map so should be faster when performing lookups on tiles. The common scenario I guess will be things like ...


Player moves over a chunk boundary so map / some parent goes and adds new chunks and fills them with tiles. This also allows you to "pick portions" of the map for rendering calls to help optimise the engine a bit more.


And by tracking the current chunk the player is stood on you can make any player interaction with the map much faster too :)


You will however need to address the problem of chunk bounds if you only look at data on a chunk by chunk basis so be aware of that.



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...