City builder. Is this possible?

ikonhero

Member
So I had this idea of a city builder. Something similar to sim city, but with a different look.
I figured I made the buildings sort of procedurally generated instead of using sprites.

Here's what I came up with so far:

Each zone draws a cube as a house. It's size represents the population capacity, and color brightness will eventually represent current population for the building.
At this point the only sprites I'm using are for the grid tiles and the roads.
As you may see in the screenshot I'm getting only 43 real FPS. So this may not be a very executable idea.
The thing is, with this system you can let the color of the buildings represent all kinds of things, for instance switch to "land value" view where all buildings would color in relation to land value.


As for my actual question. I was was wondering on how one would approach the handling of all the data for a simulation like this. I did a test where I filled up a 64x64 grid with small building zones and roads and the game froze instantly.

So, I set up a timer to update each zone's stats every 3 secons, but that only resulted in the game freezing every few seconds :).

I guess things can be optimized to run more smoothly by having the game check only the very minimum required data in every step. Right now I'm checking lots of things, like surrounding zone types. trying to find nearest subway station and storing its distance, etc.

So, do you think a game like this is possible?
Are there any ideas on how one would approach the handling of data for each zone? Could it be useful to make a massive 2d array for the map and store each zones statistic as value in that array? Or maybe a DS grid?

I would really be interested in your ideas.

Thank you!!
 
Last edited:

Yal

šŸ§ *penguin noises*
GMC Elder
First of all, a drawing call essentially takes the same time no matter if you're drawing a 40,000 polygon 3D environment or a single rasterized sprite. GPUs are optimized to draw a few, highly detailed models, not thousands of smaller ones. (The reason for this is that the CPU <--> GPU data channel is the bottleneck; once a full model has been loaded into the GPU's memory, it can be drawn with a single call). I imagine you draw each house individually, and then you need to send a LOT more data than necessary to the CPU.

Secondly, one of GML's main bottlenecks is loops. More GML loops means slower code, especially nested loops (like the one you'd make over a 2D array). This might also be related to the first point (a loop in the draw event slowing down the event execution and also overloading the CPU-GPU link).


What you wanna do to optimize your game:
  • Use GM's built-in, compiled loop structures when possible (e.g. with loops, instance_nearest etc) instead of looping in interpreted code (GML). It might actually be faster to create object instances to store city data instead of using an array (them drawing themselves might even be faster than loop-drawing! But that's a pretty shaky "might", so... you might wanna have them be invisible and draw the data elsehowly)
  • Render city data to some structure that can be drawn with fewer calls: surface, vertex buffer etc
  • Instead of looping over the entire city every second, loop over a small fraction of the city every step (spreading the load evenly instead of having bursts of MASSIVE data management once in a while). To improve response time, you could re-roll the immediate surroundings right after the player changes something even if it's not their turn yet.
  • Adding surrounding cells' data together binarily might be faster than doing 4 different branches - if you have 16 different sprites / subimages for the property you're checking against (e.g. road connectivity) you could even use this value directly!
    upload_2019-12-26_21-42-48.png
 

ikonhero

Member
Hey, thanks for your advice!
I imagine you draw each house individually, and then you need to send a LOT more data than necessary to the CPU.
Yes, at the moment I have an instance for each zone cell, meaning for every building there's an instance drawing 6 triangles in the draw event.
Render city data to some structure that can be drawn with fewer calls: surface, vertex buffer etc
I assume you mean it would be better to have a single instance do all the drawing of all buildings at once? Not sure about surface, haven't been using them much.
Instead of looping over the entire city every second, loop over a small fraction of the city every step
Very nice idea! Will try that!
 

ikonhero

Member
I tried what you suggested. It seems one of the biggest problems was the amount of instances in the room.
Now I have only a couple of instances. One of them has a bunch of ds_grids in it (one for each possible value a cell can have). I should be able to read and write every possible data for each zone cell using this single object.
Another instance handles all the drawing. I made a test where all cells of a 64x64 grid are filled with cubes and I get over 120 real fps. No freezing.
In the create event I generate all vertexes and store them in a ds grid. From the draw event those are called and submitted. It seems to work quite well. Now I have to see how it behaves when I start updating the data.

Also I changed the background grid system. Drawing 64x64 grid sprites in a double FOR loop already lowered the FPS to 300. I replaced it with the maximum sprite sized grid sprites and draw only a couple of those.
 
Top