0
\$\begingroup\$

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;
            }
            */

        }
    }
};
\$\endgroup\$
2
  • 1
    \$\begingroup\$ What do you mean by chunks? (Are they contiguous rectangular areas of map? What size are they? Why are you using them?) Why do you think your code might "cause lag"? \$\endgroup\$
    – Anko
    Commented Sep 13, 2014 at 18:54
  • \$\begingroup\$ The map is made up of chunks and the chunks are made up of tiles. The chunks are saved to a 2d array like this chunks[x][y]. Based on the player coordinates it knows how to determine the chunk then loops through those tiles and surrounding chunk tiles. Without the chunks I am checking each tile vs each chunk. That is where the bottle neck is. \$\endgroup\$
    – zachdyer
    Commented Sep 15, 2014 at 19:25

1 Answer 1

2
\$\begingroup\$

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<Chunk> { 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.

\$\endgroup\$
4
  • \$\begingroup\$ Is it okay if I load the chunk the player is at and the surrounding chunks for a simple solution? \$\endgroup\$
    – zachdyer
    Commented Sep 15, 2014 at 16:19
  • \$\begingroup\$ Its your solution, you need to decide that, in my case I do this with voxel chunks, to load so few wouldn't get me a lot, in your case however working in just 2 dimensions with your tiles you may be able to load a lot more data which will likely mean either bigger chunks or more chunks. Your chunk size will need to be small enough that when you build new ones the app doesn't lag but big enough that you aren't constantly loading and unloading them. Experiment a bit with it. \$\endgroup\$
    – War
    Commented Sep 16, 2014 at 8:26
  • \$\begingroup\$ I plan on using 16 tile chunks also Perl noise for the terrain generation. I haven't figured out how to do the Perl noise but I've seen a lot of stuff on the net about it. \$\endgroup\$
    – zachdyer
    Commented Sep 16, 2014 at 14:30
  • \$\begingroup\$ Exactly how I do it ... tip: you may find using perlins "simplex noise" a bit faster but being in 2d you may not need it. Most decent game engines these days offer some sort of perlin function built in if you dig deep enough failing that add me on skype and i'll throw you mine ... paul.ward at ccoder.co.uk should give you 2 results add both to save on confusion (they are both the same account essentially and both me) \$\endgroup\$
    – War
    Commented Sep 16, 2014 at 15:38

You must log in to answer this question.

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