+1 vote

In Godot 3.3.2. I'm attempting to make a Worms-like game. I found this tutorial by OptionalDev on youtube.

In this, terrain is generated by cutting the top portion of a sprite off following a random noise pattern. The collision is custom-built to say anything above that line is air, and anything below it is solid.

However, I want to make a tunnel map. I can generate maps that I like, with about 30% of the map covered in ground and 10% covered in roof and open air in between.

enter image description here

However, the collision becomes a problem. Following this tutorial - the roof would have no collision, which I obviously don't want. You also don't get the benefits of Godot's native collision objects.

The tutorials I've seen of MeshInstance2D all suppose a Sprite that hasn't been programmatically modified, and I'm not sure it is what I want anyway. As this is one sprite, and not several blocks, CollisionShape2D doesn't seem like a good choice.

Of course, the goal of this will be destructible terrain.
Any guidance on where I should look next would be much appreciated.

.
EDIT:
I have managed to recreate the tutorial's collisions on the roof as well, but I'm still wondering if there is a way to programmatically make Godot generate CollisionShape2Ds that cover the visible portions of the image.

I should also point out that the image isn't actually cut or removed at all - merely the "open" portion is set to Color(0,0,0,0) - the Alpha being 0 is the most important part.
.

I'm using the following code - only one modification from the tutorial's code, which is better commented.

onready var FG = $Foreground

const CLEAR = Color(0, 0, 0, 0)
var line = []

func _ready() -> void:
    randomize()
    _generate_map()

func _generate_map():
    var fg_data = FG.texture.get_data()
    fg_data.lock()

    var noise = OpenSimplexNoise.new()
    noise.seed = randi()
    noise.octaves = 2
    noise.period = 180
    noise.persistence = 0.8

    for x in range(fg_data.get_width()):
        var high = ((noise.get_noise_1d(x) + 1) * fg_data.get_height() * 0.3) + fg_data.get_height() * 0.08
        line.append(high)
        for y in range(high):
            fg_data.set_pixelv(Vector2(x, y + (high*0.3)), CLEAR)
    fg_data.unlock()
    FG.texture.set_data(fg_data)
Godot version 3.3.2
in Engine by (13 points)
edited by

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.