Procedural Generation Optimisation

How do I…

Optimise the procedural generation of my top down world to make it bigger .

What is the expected result

To be able to have a bigger world and optimised so I can have a good frame rate

What is the actual result

I have followed the tutorial on the gdevelop wiki (docs) and added my own items to it. Upon making the world bigger it drops the fps a lot which I understand because it has more items to create

Related screenshots

Can you screen shot the events you have for the procedural generation?

Here’s some screens shots of how the ground is generated then the objects

First, you’ll need to use a Tilemap instead of sprite objects. Creating objects is almost always more expensive than modifying existing objects, and Tilemaps are also more efficient to render during the game. The Colour object is a problem. You could potentially make two Tilemaps, one will be the Colour map. Or you could manually create a tile atlas that combines all the colors. Either way you’ll end up having to rethink the opacity values and whatnot because tiles don’t have individual properties like that.

Second, you have a LOT of going back over things and checking them when you shouldn’t. Just imagine this is a board game and you’re trying to do this by hand:

  • Put down a bunch of tiles
  • Check every single tile for opacity < 85 and collision with Colour
    – If so, DELETE! Why did you even place it?
  • Ok now check every single tile again, now look for opacity between 86 and 119 and collision with Colour.
    – DELETE! Haha, I love undoing my own work!
  • Check every single tile AGAIN, opacity 121 to 199 & collision with Colour
    –You guessed it, DELETE this tile that should never have existed!
  • Getting tired yet? Too bad, do it all again for opacity 215-255

(side note, you’re excluding opacity 85, 120, and 200-214)
Now on to the other objects. Uh oh, you have “repeat for each”… not a good sign. Let’s imagine there are 1000 Colour objects:

  • Repeat 1000 times:
    – Is the animation “grass”? If so, roll dice.
    – Did the dice win? If so, make Tree (side note - trigger once here is pointless)
  • Start over, Repeat 1000 times:
    – Is the animation “grass”? If so, roll dice.
    – Dice win? Who cares, do nothing
  • Start over, 1000x:
    – Is the animation “grass”? Roll dice.
    – Dice win? Cool, do nothing
  • Start over, 1000x:
    – Is the animation “grass”? Roll dice.
    – Dice win, make Sprout

And I can see that you then do the same thing for “mountain”. If you think this seems like hard work when I write it out like that, you’d be right. You’re checking the same tiles over and over again. You’re picking up the Colour object and asking if it is “grass” FOUR TIMES for every single one. If your boss asked you to do this you’d quit. Pick up that box and tell me what it says. Ok put it down. Ok now pick it up again and tell me what it says. You mean it’s still the same? Weird, put it down. Pick it up. Put it down.

They key to efficiency, both in programming and in the workplace, is to do things ONCE whenever possible. Also, always use object filtering before Repeat for Each events. It should be like this:

The animation of Colour = "grass"
     -> Repeat for each Colour
           -> Roll dice

Let’s make it even better, instead of searching for grass, mountain, etc. Just search for the one you want to exclude.

The animation of Colour NOT EQUAL TO "default"
    -> Repeat for each Colour
        -> Roll dice

Now you have a single event that grabs all Colour with any animation other than “default”.

Let’s make it even better. Remember when you did all that work placing tiles? That is the best time to be rolling dice and changing properties. The only reason to go back over the map is if you want to change something later on. If you’re making changes now, don’t waste time placing the rest of the tiles and then going back hunting for the ones you need. Combining with using Tilemaps it should look something like this:

While X > 0, Y > 0
Repeat:
                 |   Change variable NextID to some number
                 |   Change tile ID of WorldMap grid X,Y to NextID
    NextID = 1? |   Change tile ID of ColourMap  grid X,Y to something
          -> Roll dice?    |     Make tree
    NextID = 2? |   Change tile ID of ColourMap grid X,Y to something
          -> Roll dice?    |    Make Sprout

This not only combines the events into a much more compact format, it severely reduces the workload on the processor. Each time a tile is “placed” (i.e. modified), all the necessary work of setting up that specific tile is completed right then and there.

2 Likes

Wow firstly I wanna say a really big thank you to you for your help but not only help but also putting things into perspective as to actually the events I had going on and how I was putting code together, it is highly appreciated. I have rethought slot of my game code now and it has already helped optimising it heaps and make a lot of bugs redundant.

The only thing I am struggling with is figuring out something else to use other then opacity for tiles sets as like you stated above doesn’t work.

(Ps sorry for late reply)