0 votes

Hi,

I'd like to spawn instances of my enemies at a random position, but always on the floor (2D platformer)

view

I tried to Spawn the enemy at random position, and if it does not touch the ground, kill it and respawn another one, but this is very inefficient

Would there be a solution to this?

I'd rather not add 2D position to the map and choose among them, as it would remove the "random" part and remove flexibility (if I want to make flying enemies for examples)

Godot version 3.2
in Engine by (21 points)

2 Answers

0 votes
Best answer

Well, it was tedious, but I found the solution thanks to @Inces !!
Here is the code for those who might want to do something similar (the script is in the Tileset node)

func _ready():
        if MainTerrain:
            select_tiles()
            get_ground_tiles()

    func select_tiles():
        usedTiles = get_used_cells()

    func get_ground_tiles():
        var n = 0
        while n < usedTiles.size():
            selectedTile = usedTiles[n]
            if is_ground_above(selectedTile.x,selectedTile.y):
                usedTiles.erase(n)
            n += 1
        Global.GroundTiles = usedTiles

    func is_ground_above(x,y):
        if get_cell(x,y-1) == -1:
            return true
        else:
            return false
by (21 points)
+1 vote

You can use TileMap methods to get places just above ground ( if tile.index == -1 and tile + Vector2(0,1) is solid tile ). Iterate through getusedcells() like this, and collect tiles in some array. Next You will be able to pick random element from this array, or even random position within borders of one tile.

by (7,305 points)

Thanks for the answer, that start to make sense!!

I'm pretty new to Godot so I'm not really familiar with all the functions yet

How would you check if a tile is solid?

getcell() returns index of your tile. Each index is a type of tile You designed when creating tilemap, for example - You made 4 grass tiles facing all directions and 1 sky tile. So tile indexed 0,1,2 and 3 are your grass , 4 is your sky. If getcell is any number from 0-3 it will be solid. You know best, which tiles You want to be solid :). Index -1 means there is no tile at that position.

Aaah, I see, make sense, so, in this case all tiles with a -1 tile above them are suitable for the spawn

I have trouble using PoolVector2Array tho

usedTiles = get_used_cells() gives me the list when I print it, but print(usedTiles[0]) gives me:

"Invalid get Index '0' (on base: Array)

However, var array = PoolVector2Array([Vector2(1,2)]) + print(array[0]) do print 1,2 in the console

Pool Vector array is pretty much the same as any other array, only it doesn't some specific methods, and it is passed as real value. You must get an error because your getusedcells() is empty. Getusedcells returns all tiles that are already placed on the map. Maybe You are calling it too early, before TileMap is ready ?

It seems to be the problem indeed!

The _ready function load before the TileMap is loaded somehow. I was able to see the array because I have a duplicate TileMap for background, but the "real" one is loaded after the ready function somehow, I have to find a way to avoid this

EDIT: The problem was because I had a copy of the TileMap, I just added a variable "MainTerrain" to check that.

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.