I am generating 2D terrain with 2D opensimplex noise, however I am having a problem with the FPS that is low when generating the terrains in TileMap. An example of how my game generates the terrain in javascript:

function generator(map_size=0, _posWorld=[0, 0], size=[1, 48], seed=0) {
    var simplex = new SimplexNoise(seed);

    var x = 0;
    var y = 0;
    var pos_modx = 0;
    var pos_mody = 0;
    while (x < size[0]) {
        pos_modx = utilsfunctions.mod(_posWorld[0] + x, map_size);
        y = 0
        while (y < size[1]){
            pos_mody = utilsfunctions.mod(_posWorld[1] + y, map_size);
            // GENERATION NOISE
            // TEMPERATURE
            var nx = parseFloat(pos_modx)/map_size - 0.5;
            var ny = parseFloat(pos_mody)/map_size - 0.5;
            var v1 = temperature * simplex.noise2D(1 * nx, 1 * ny);
            var v2 = 0.4 * simplex.noise2D(2 * nx, 2 * ny);
            var v3 = 0.23 * simplex.noise2D(4 * nx, 2 * ny);
            var v4 = 0.134 * simplex.noise2D(8 * nx, 8 * ny);
            var e = v1 + v2 + v3 + v4;

            // HUMIDITY 
            var unx = parseFloat(pos_modx)/map_size - 0.4;
            var uny = parseFloat(pos_mody)/map_size - 0.5;
            var u1 = humidity * simplex.noise2D(1 * unx, 1 * uny);
            var u2 = 0.6 * simplex.noise2D(2 * unx, 2 * uny);
            var u3 = 0.7 * simplex.noise2D(4 * unx, 2 * uny);
            var u4 = 0.073 * simplex.noise2D(8 * unx, 8 * uny);
            var u5 = 0.09 * simplex.noise2D(16 * unx, 16 * uny);
            var u6 = 0.03 * simplex.noise2D(32 * unx, 32 * uny);
            var ue = u1 + u2 + u3 + u4 + u5 + u6;

            if (pos_modx >= 0 && pos_mody >= 0) && (pos_modx < map_size && pos_mody < map_size) {
                tile_map.set_cell(_posTileMap.x + x, _posTileMap.y + y, biomes.solos(e, ue));
            y += 1;
        x += 1;

The problem is that I am generating several layers of tilemap, one for terrain, one for relief and one for trees. That is three scripts of these, of course for the relief and trees is much less complex, and alone for example, even the two together do not interfere almost anything in the FPS. However, only generating with the above-ground script is already a big problem, and I generate only one minimum possible bit at a time, which is (1, 48) for when moving up or down, and (48, 1) when moving to the right and left, it is clear that there is the case of the diagonal movement, having to generate 48 + 48, which is the worst case. However, even only the 48 are already leaving the FPS bad, nor do I need to move diagonally to feel the FPS suffer.

I would like tips to be able to optimize this generation, and if know any way to use only one algorithm to generate everything (terrain + relief + trees), or any help that can take me to a better way.

Understand why I am generating with 3 different scripts for terrain, relief and trees:

Terrains are large areas within large areas.

enter image description here

Reliefs are crooked lines on the map.

enter image description here

Trees are only points of a dirty noise on the map.

enter image description here

  • \$\begingroup\$ Generating terrain is slow by definition. You should probably use WebWorkers to do it. Two questions though: do you generate the terrain every frame? Do you know that you could simplify the above code with for loops? \$\endgroup\$ – Bálint Dec 16 '17 at 17:27
  • \$\begingroup\$ I am generating when player changes its posWorld, the terrain does not have a fixed size, so it must be generated while walking. what I'm trying to do is to reduce calls to "simplex.noise2D" and try to keep a nice result anyway. \$\endgroup\$ – PerduGames Dec 16 '17 at 17:39
  • \$\begingroup\$ @Bálint Do you know that you could simplify the above code with for loops?: is that in the other language that is my client the "while" are faster than the "for", the javascript script is from my server nodejs. \$\endgroup\$ – PerduGames Dec 16 '17 at 17:48
  • 1
    \$\begingroup\$ The difference between a for loop and a while loop is so small, I don't think it's worth the effort you need to invest every time you want to change the roughness of the terrain. As I told you, use WebWorkers. \$\endgroup\$ – Bálint Dec 16 '17 at 17:58
  • 1
    \$\begingroup\$ @PerduGames Your going to have a better time optimizing the algorithms you use rather than things like using for or while, considering different browsers will have different performance for each. \$\endgroup\$ – opa Dec 21 '17 at 17:43

You should profile your code. Since it is in Javascript, I assume it is a browser game. Try Chrome, it has good profiler that will visualize you which functions take the longest.

If you say that it is slow even for 1x48 generation, ie the inner loop is run only 48 times, something is really wrong. Generating few random numbers and some floating point arithmetic 48 times is no big deal.

What happens in this call?

tile_map.set_cell(_posTileMap.x + x, _posTileMap.y + y, biomes.solos(e, ue));

My guess is that whatever is happening in here (any rendering?) takes the longest. You could try to first generate all the new tiles and then update the world in one transaction.

Also don't call parseFloat repeatedly if you can cache the value. Ideally don't work with strings at all, have all your hot functions take and return numbers.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.