Spawner - How to stop it and activated a new one?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Plaz_GD

Hello everyone.

Currently, I’ve been trying to make a functional script to spawn enemies (which is a falling meteor in my game).

Here’s my current script:

extends Node

const meteors = [
   preload("res://scenes/meteor.tscn")
]

func _ready():
   yield(utils.create_timer(1.2), "timeout")
   spawn()
   pass

func spawn():
   while true:
	   randomize()
	   var m = utils.choose(meteors).instance()
	   var p = Vector2()
	   p.x   = rand_range(0+16, utils.view_size.x-16)
	   p.y   = 0-16
	   m.position = p
	   $container.add_child(m)
	   yield(utils.create_timer(rand_range(0.5, 1.25)), "timeout")
   pass

And so far it works, here’s how it looks: (screenshot link below…)

But my question is how to stop the spawner at the specific time? and then activate another spawner afterwards?

My idea for this is for example:

After the player managed to survive the falling meteor shower for 30 seconds, the spawner of this type of meteor (which I regard as the first spawner) would stop spawning meteors. Then the next spawner (that features a new and faster meteor sprite, which I regard as the second spawner) would start active.

I had found various tutorials online (like in youtube) on how to make a spawner in godot. But so far, none of them had ever described how to stop it at a specific time.

Is this had to do with how the timer works? I’m curious to know. If someone could write a specific explanation in detail, that would be appreciated.

~ Regards

:bust_in_silhouette: Reply From: njamster

Here you go:

extends Node

const meteors = [
    preload("res://scenes/meteor.tscn")
]

var meteor_shower = false

func _ready():
    yield(utils.create_timer(1.2), "timeout")
    spawn()
    yield(utils.create_timer(30.0), "timeout")
    meteor_shower = false

func spawn():
    meteor_shower = true
    while meteor_shower:
        randomize()
        var m = utils.choose(meteors).instance()
        var p = Vector2()
        p.x   = rand_range(0+16, utils.view_size.x-16)
        p.y   = 0-16
        m.position = p
       $container.add_child(m)
       yield(utils.create_timer(rand_range(0.5, 1.25)), "timeout")

I only introduced a new variable, a boolean called meteor_shower defaulting to false. When spawn() is called, it’s set to true before the while-loop starts, that will run for as long as meteor_shower is true. So far that will behave exactly the same as your code. However, after calling spawn() in _ready() I call another timer (of 30 seconds) after which meteor_shower is reset to false - y voilla, the while-loop will stop!


For future questions I recommend that you provide your utils-script as well, if you’re using it. I remembered your last post, but you cannot expect everyone to do so. Also I allowed myself to remove the pass-keywords from both _ready() and spawn() - they don’t do anything. Use them where GDscript expects a line of code and you’re not ready to add this line, e.g. after a function-definition or an if- or else-case.

  • Great, it stops the spawner in exactly 30 seconds (I’ve decided of making it longer up to 1 minute). Now how to make the second spawner active after the first spawner had stopped?

  • Understandable, I shall follow your recommendations on future questions.

  • Regarding the pass keyword, I always thought that we need to add that keyword at every end of each function (Currently, each function in my code always had that keyword in the end). Thanks for your info.

Plaz_GD | 2020-05-27 01:12

Now how to make the second spawner active after the first spawner had stopped?

The logic is always the same: you wait a certain amount of time, then you spawn the meteor shower, wait more and then deactivate it again by setting meteor_shower to false. Here’s an endless loop of spawning meteors in random intervals:

func _ready():
    randomize()

    while true:
        var wait_time = rand_range(1.0, 5.0)
        yield(utils.create_timer(wait_time), "timeout")
        spawn()
        wait_time = rand_range(10.0, 30.0)
        yield(utils.create_timer(wait_time), "timeout")
        meteor_shower = false

njamster | 2020-05-28 12:01