Infinite tile generation

I’ve recently made a simple infinite tile generator for a running project.
I think that it works decent, but it has room for improvement. I’m curious as to what improvements I can make to make it run better on older computers. The generation system does not have complex generation code yet.

You can download the generator here (it’s the Speed Farmers infinite world test, project page is very old)

The infinite generator works with a Region class. A region is similar to a chunk in Minecraft, but in 2d. It currently holds 16 x 16 tiles. Each region has a position, and a RegionManager class manages which regions need to be loaded (/unloaded).

The region manager executes the loading and unloading functions each time the camera moves, and the regions that get out of the screen boundaries are unloaded and encoded to a binary file on the drive. Regions that need to be loaded are newly generated or loaded from the drive when they already exist.

Unloaded regions are removed from memory and the tiles that are in the region are also gone, so only the regions that can be seen on the screen are drawn.

The Tile class is a child class of the ObjectInstance class. This class is the parent class for all types of objects in the game (tiles, items, …). It currently holds a position (vector2) and a GameObject (and maybe a future texture index int for autotiling). The game object has all the shared information of that type of object. This demo currently has 2 game objects: grass and a field.

Some images (v1) of the generator:

New dev menu:

New text effects (v2):

4 Likes

Sounds cool!

I assume you’re applying this same region logic to entity updates… updating everything in the current region every cycle, then queuing things in neighbouring regions according to some priority so they can still go about their business, but not hog all the processor time as things scale?

That’d be about all I could suggest.

I’ve played around with stuff like this when I was developing a QuadTree. It’s fun to have an infinite world :smiley: Nice work!

1 Like

Thank you! I will look into this.
It’s very fun indeed :smiley:

In what sense are you trying to gain performance?

If its CPU related performance your’e trying to gain, then selective updating can gain you quite a bit, meaning that you only updated things if you know that they have changed. Easy to overlook in your attempt to just get things going.
QuadTree’s are also really nice for things like these.

GPU wise you could looks at mip maps of just having low and hi res images and selecting between them as you zoom in and out, may save you some bandwidth, great for low bandwidth GPUs.

Something a little more crazy would be to render a chunk to RenderTarget2D and only then call that to render that chunk as a texture during your spriteBatch.Draw(“stuff”);. It will probably only be feasible for parts that don’t change like the actual terrain. Or if it’s smart, it only updates the region RenderTarget2D if something in that region changed or moved.
This can gain you CPU and GPU time as you waste less time telling the GPU what to do, obviously depends on implementation and exact scenario.

1 Like

Thanks for the feedback!

Do you also have tips on improving encoding data to a disk?
That’s the main problem I think. I encode the data to a binary file and each region of 16 x 16 tiles is 3kB at the moment. Not a problem, but there’s a small freeze when loading in many new regions (15+) on a big resolutions and a small scale.
Maybe using multithreading and placing the region loading on a separate thread?

Multi-threading would help with the freeze up’s as slow encoding should not hamper the game itself. Loads of pitfalls in multi-threading and I’m the wrong person to ask for help with that madness. :slight_smile:

Not sure how you are encoding to your binary file? But I’m assuming your writing to it every few seconds as the world moves? Some times it’s a game of RAM vs HDD. If you can build up a bit more data in some kind of String Builder before writing to HDD you may reduce the read write thrashing. And yes, I’m assuming you are writing but also possible reading from that same file “at the same time”, or at least shortly after in some cases. But less writing or less chunky writing(encoding). Remember the read/write head can only do one thing at a time, and an SSD is faster but simulates the same thing as far as I know.

Thanks for the reply.

I will probably keep the current state of the generator, and improve further upon it in the future. It works decent I think. The project that will be using it, isn’t going to render that much tiles at the same moment.
At this moment I’m encoding each region that goes off the screen individually to a different file. I load that data when the camera moves back to the same region.

Oh, I see.
That’s a ton of little files… 3kb you said? Each with their own name and file header etc.
If you can work out any way to write more regions in to a single file, or have larger regions per file that could gain you loads of speed. RAM > HDD any day of the week even if the HDD works overtime and weekends. Unless your developing for mobile or computers from the 90’s ram should not be a problem for a few 1000 low data size objects especially not if you use TextureID’s.

Other than your probably right, some times you just have to come back to something when its an actual problem for your program :wink:

Thank you for all your feedback :slight_smile:
I will look into this in the future.

UPDATE:

It was not the encoding that was the problem, it was the generation code for a region.
The infinite world runs very smooth without a generator. I will improve the region generation in the future.

Off topic, but I love your font rendering! How do you achieve that effect?

1 Like

I think it’s not a good practice, but it works:

I draw my font multiple times in different colors, that’s it.
Maybe I could achieve the same with a pixel shader or something like that?

Ah, it looks more complicated! Probably faster to do it the way you do, but you could use an edge detection filter in a pixel shader.

Yeah it’s the simplest method at the moment. I like how it came out!
Also added some color codes, for example: T;re;bst will write “Test” with a black ‘T’, red ‘e’ and blue ‘st’.

If you were drawing signed-distance field text you could use a 1d LUT texture to do the same thing (gradient ramp basically), though it’ll be even more bubbly than what you’ve got. What you’re doing is probably faster though (bare-bones shader), and it works.

1 Like

Thanks for the information, @AcidFaucent.

Update: Some new nice text effect.

4 Likes

While reading up on optimizations, I came across a few things that may be of interest to you or others reading this question:
Jagged Arrays, I’m assuming that you store your train data in 2D arrays or something.

Keeping IO Buffer Size Between 4KB and 8KB, is a recommendation from MSDN
Asynchronous IO Opportunities: https://msdn.microsoft.com/en-us/library/aa719596.aspx

Also look in to using Structs instead of Class for data objects when appropriate, it can gain you quite a bit of speed, even more so when the iteration list is very large. It is important to understand when to use them as they can hurt performance if used incorrectly.

1 Like

Thanks for your reply @egodamonra! I’ll definitely look into structs.
Just one quick question: How would using a jagged array improve performance over a 2D array in this situation?

The tile-generation is not bad. But that text man.
Please make a lib out of that :smiley:

1 Like