0 votes

Hello everyone :)

So I have a 2D top-down shooting game whose terrain is generated procedurally. I used Tilemap to ease the coding. I've managed coding the room & corridor generator, but I also wanted to generate boxes in the rooms. These boxes will act like chests, they have some items in them for players to collect. What I really want to ask is:

How can I generate those boxes without making them blocking corridors or other boxes?

I prefer the boxes to be generated in the edge of rooms, without, as mentioned, blocking corridors or hallways. Since each box has their own collision, I also want them not to block the other boxes, leaving them unreachable by players to open.

For more information, I have a Rect2 array (consisting rooms), and a dictionary (consisting corridors, with Rect2 rooms as keys and Vector2 arrays of corridor points as values) as my data after generating rooms and corridors. I hope this will make answering my question easier. :v

Is there any effective way to do this? Thanks. :)

in Engine by (61 points)
edited by

2 Answers

0 votes

Normally in games you would just use the NavMesh to check for this. Because a NavMesh has to avoid objects; remember to update the NavMesh, or maybe use 2.
Other path finding could also work.

If you don't want to use a NavMesh, then spawn the object at any point. Use avoidance behavior to move it away from objects. This takes time, so it will cause a long loading delay.

by (1,434 points)

I'm sorry but I don't get your point about how to use NavMesh XD
Do you mean detecting tiles with NavMesh and replacing them with my box tiles?

And about the avoidance behaviour, what entities should I make these boxes avoid? I want them to stick on wall edges, so it's certainly not walls right?

I'm sorry if I asked too much, I'm new in procedural generation. :)

I don't think a NavMesh is a good option here. I'm not sure though, since I've never used NavMesh. The avoidance behaviour way might fit your data better, but I think there is still a more suitable way.

0 votes

If your rooms are in a Rect2 array, you can do something like this with them:

func find_places_for_boxes(var room_rect):
var arr = []
var box_size = 32

# Move along the walls in a loop
var x = room_rect.position.x + box_size / 2
while(x <= room_rect.end.x - box_size / 2):

    # Top wall
    arr.append(Vector2(x, room_rect.position.y + box_size / 2))

    # Bottom wall
    arr.append(Vector2(x, room_rect.end.y - box_size / 2))

    x += box_size

# Same thing for left and right walls
var y = room_rect.position.y + box_size / 2.0
while(y <= room_rect.end.y - box_size / 2.0):
    arr.append(Vector2(room_rect.position.x + box_size / 2.0, y))
    arr.append(Vector2(room_rect.end.x - box_size / 2.0, y))
    y += box_size

return arr

The function takes a rooms Rect2 as a parameter and returns an array of points that are near the walls. There are overlapping box points at the corners, and they can be removed like this:

func remove_overlapping(positions, margin):
var i = positions.size() - 1
while(i > 0):
    var i2 = i - 1
    while(i2 >= 0):
        if(positions[i].distance_to(positions[i2]) < margin - 1.0):
            positions.remove(i)
            i2 = -1
        i2 -= 1
    i -= 1
return positions

If you now instance a sprite for every point, it will look something like this:
Rooms and boxes

Notice one of the rooms has badly placed boxes near the corners? Thats because the room size isn't a multiple of the the box size. That should be easy to fix though.

I'm not sure what to do about the corridors. Maybe remove box points using the Rect.has_point or Rect.intersects method.

Here's the sources for this test: roomboxtest.zip

by (148 points)

Thank you really much! I will try implementing this in my game. Maybe I'll tweak it a little bit so it will work well as I wanted. :)

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 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 webmaster@godotengine.org with your username.