There are many ways to do this, but I can explain one.
You should be able to do this in several steps.
First, your animation needs to be tileable, so it can be repeated horizontally across the screen without seams.
This raises the question about how your animation should look like:
- Is is the same pattern repeating vertically as well?
- Or does it have two animations, one at the top (splashes) and then something repeating downwards (bubbles) ?
- Or is it an entire animated vertical strip, high enough so it can cover the screen?
Once you figured out how to make one vertical strip arranged in one of those three ways, you can save one strip as a
LavaStrip scene, then look into repeating it horizontally.
LavaRoot node under the root of your level, and put one lava strip as child. Then, duplicate it several times horizontally, so that you end up with something like this:
- LavaRoot (Node2D) <-- this one will raise slowly
You can do that in editor, or using a script by calling
duplicate() and moving the copy to the right using something like
.position += Vector2(lava_strip_width, 0).
The amount of copies required should be just enough to cover the area visible by the camera.
Then, to make it look infinite, we can translate
LavaRoot along the X axis by some amount depending on the camera X position, so that it will always be shown.
You can do this in a script on
position.x = camera_position.x
However that will make the lava follow the camera along X, which will look static. Here is a trick to make it look like it is part of the level:
position.x = stepify(camera_position.x, lava_strip_width)
This will make the X position change by increments that are the same width as the repeated strips of lava, so it will appear fixed inside the world, while in fact it keeps all strips of lava in view. Since all strips are the same, the illusion is seamless.
I wrote two variables here without explaining how to get them, to keep the logic clear.
lava_strip_width is basically the width of each of your strips, you should be able to get it from the texture you used for the animation.
camera_position can be obtained either by using
get_node(path).position with the path to your camera, or by using the following code:
var ctrans = get_canvas_transform()
var top_left = -ctrans.get_origin()
var vsize = get_viewport_rect().size
var center = (top_left + 0.5*vsize) / ctrans.get_scale()
I wrote all this by head, I haven’t tested any of this, so it’s possible that some adjustments may be needed. I know however that this approach should work well, I hope it is what you were looking for.