2D infinite world - Generating terrain (chunks?)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jakeumbra

I’m trying to create an “infinite” world that, as the player moves towards a direction, the game will generate tiles in front of the player and remove the ones behind. (Note that the player can move in any direction) I’ve checked out some of the other solutions to similar problems but not exactly applicable to my issue.

What I’m trying to achieve is something like what is shown in this video:

However, this video seems to be seemingly for finite grid world, and the player position is updated instead of the world’s position.

As I am implementing “infinite” world, I don’t think I’ll be able to move the player as the player’s position will eventually accumulate to a large number and result in issues (correct me if I’m wrong). Therefore I’ll have to move the world instead of the player. However, this makes it hard to track which terrain has to be removed/added on which direction.

I’m still trying to test and figure out a possible working solution, but does anyone have any ideas or suggestions for this?

:bust_in_silhouette: Reply From: Zylann

I never tried moving the world instead of the player. I think it is a lot easier to move the player. Most obvious problem I see is physics: what is usually a static object is not supposed to move.

If you are afraid of precision issues, the solution should be to use doubles or move the world origin, but both are not straightforward to do in Godot. using doubles should be easier, and Godot has a typedef for that, but I don’t know if it really works (note that OpenGL uses floats anyways).

If it’s the first time you do this, I would not bother with precision for now. You can already go pretty far with what Godot offers by default, and if that really becomes a problem, you can look into one of the two above solutions.

If you want to move the world, I’ll be curious to see how far you get :slight_smile:

Yeah I was worried about situations such as if the player moves to the right long enough that the x position float value will eventually exceeds the available value range. Would the value range of float be large enough that it would be highly improbable for an endless runner to exceed the value limit?

Also, by moving the world origin, is it similar to moving the world?

Thank you for help, I’ll try out moving the player instead of the world.

jakeumbra | 2018-07-31 14:19

:bust_in_silhouette: Reply From: SASUPERNOVA

The solution to your problem really depends on how you want to optimize your game. Since you simply want to generate a 2D terrain, I would recommend using a Camera2D, so that the “removal” of chunks will occur as the camera changes position (that is, as the chunks are no longer being rendered). I would also recommend that you avoid moving the world, as Zylann mentioned before. Instead, you could attach the aforementioned Camera2D to your player, so that it will follow your player and load chunks accordingly.

As for the world generation, I would recommend using a Perlin/Simplex noise algorithm, which are usually used for random terrain generation, as they can create an arbitrarily (essentially “infinite”) sized “Grid” with random values. The specifics of how you render this Grid (i.e. color of chunk, items in chunk, etc) is really up to you, but you can find ready to use implementations of both algorithms. If you can build Godot from source, you could use Zylan’s module (what a pleasant coincidence!). In case you have difficulties building Godot from Source, you can also use the PerduGames function set, which is written in GDScript, and should be easier to use in your project.

Whichever approach you decide to use, I wish you the best of luck!

For the chunk removal/addition you mentioned, is it something that is done automatically by Godot or have to be programmed on my own?

Noise algorithm is something new to me, I’m glad you mentioned it. Learning something new everyday!

jakeumbra | 2018-07-31 09:04

As far as I know, Godot doesn’t do any removal of items in a project tree automatically (someone correct me if I am wrong), so you will have to call queue_free() when your chunks are no longer in the viewport of your camera. As for the addition of your chunks, you will probably have to decide on a chunk size (e.g 16x16), and calculate the next chunk with Perlin/Simplex noise when the player is close to the end of the current chunk. The tricky part here is that you will potentially have to calculate 2 chunks if the player is nearing the corner of a chunk. For instance if the player goes to the bottom right corner of the current chunk, you will have to calculate the chunks to the right and to the bottom of the current chunk, because the player could decide to go either right or down.

SASUPERNOVA | 2018-07-31 10:40

:bust_in_silhouette: Reply From: CB

Hello, I’m trying to do the same thing.

I created 3 scenes:
map1.tscn
map2.tscn
map3.tscn

I used randi:

func create_map():
randomize()
var alpha = load(“res://scenes/map” + str(randi()%3 + 1) + “.tscn”)
var alphainstance = alpha.instance()
alphainstance.position = Vector2(5400,0)
add_child(alphainstance)
$Timer.stop()

extends Node2D

onready var speed = 400

func _process(delta):

var pos_x = position.x
pos_x -= speed3 * delta
position.x = pos_x	

the problem is: in each scene created it comes faster and faster
I wanted they have the same velocity

in each scene I used a collision shape at the end .

func _on_limite_body_entered(body):

if "ninja" in body.name:
	$Timer.start()

func _on_Timer_timeout():
create_map()

func _on_VisibilityEnabler2D_screen_exited():
queue_free()

CB | 2019-02-27 23:52

:bust_in_silhouette: Reply From: MagnusS

You could solve thos with a kind of hybrid solution. As soon as your player reaches a x value high enough you decrement all relevant positions by a fixed amount. This is probably the best option that works for truely infinite worlds.