The Godot Q&A is currently undergoing maintenance!

Your ability to ask and answer questions is temporarily disabled. You can browse existing threads in read-only mode.

We are working on bringing this community platform back to its full functionality, stay tuned for updates. | Twitter

0 votes

I have a world map (rectangle 1920px, and 1280 high).
I have a player (Area2D) with a Camera2D (240px wide, 160px high) as a child node.

I want to instantiate many mobs at random positions within the world map but also I don't want them to spawn inside the Camera2D view rectangle (so the player can see enemies popping out form nowhere)

I have this code:

func _spawn_enemies(many: int) -> void:
for i in range(many):
var new_mob: = Mob.instance()
    new_mob.global_position = _get_random_spawn_position()

func _get_random_spawn_position() -> Vector2:
    var spawn_pos: = Vector2(
    rand_range(0, world.rect_size.x),
    rand_range(0, world.rect_size.y))
    return spawn_pos

The spawing seems to work just right but sometimes a mob appears exactly on top of the player, killing it instantly.

Any suggestions? I thought of while loops and hard code dimensions but I think there just might be a better way.

Thank you very much for reading!!

var me: = "happy :)"
in Engine by (28 points)

2 Answers

+1 vote
Best answer

i think that's to be expected, because if I can assume the player is somewhere inside the world (so between 0,0 and world.rect_size), that means that randomly picking a spawn position inside that range can end up picking one that just happens to coincide with the player's position.

an easy way of preventing this would be something like:

var player_pos: Vector2 = #get this somehow from the player object
const safe_range: int = #define this as the minimum distance from the player
func _get_random_spawn_position() -> Vector2:
    var spawn_pos: = Vector2(
    rand_range(0, world.rect_size.x),
    rand_range(0, world.rect_size.y))
    if abs(spawn_pos - player_pos) < safe_range: # if we are too close
      spawn_pos = _get_random_spawn_position() # just get a new one instead
    return spawn_pos
by (92 points)
selected by

Wow! thank you very much, I have not thought about the safe_range solution. Elegant, simple and effective :)

I had a problem but it seem to work just fine with (spawn_pos - player_pos).lenght() instead of abs(...)

+1 vote

This works for me

const safe_range: int = 400

func _on_SpawnTimer_timeout():
    var new_enemy = Enemy.instance()
    new_enemy.global_position = player.position + Vector2(safe_range, 0).rotated(rand_range(0, 2*PI))
by (21 points)
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.