Search code examples
pythongame-developmentgodotgdscript

Using get_tree to create a timer but it's not activating


I'm working on creating Pong and I have two RayCast2Ds on the left and right side of the arena. I have it so whenever one of the RayCast gets hit, the ball resets back to the middle of the arena and the opposite player gets a point. I'm trying to make it so after the ball hits the RayCast, it resets back to the middle of the arena, pauses for 3s and starts the next round. I've added the code inside the if statement for gaining a point but for some reason the timer won't start.

func _physics_process(delta):
    if $RayCast2D.is_colliding():
        if (!already_collided):
            already_collided = true
            $Ball.position.x = 575
            $Ball.position.y = 350
            Globals.p2_score += 1
            $Label2.text = str(Globals.p2_score)
            await get_tree().create_timer(3).timeout #timer
        else:
            already_collided = false
        
    if $RayCast2D2.is_colliding():
        if (!already_collided):
            already_collided = true
            $Ball.position.x = 575
            $Ball.position.y = 350
            Globals.p1_score += 1
            $Label.text = str(Globals.p1_score)
            await get_tree().create_timer(3).timeout #timer
        else:
            already_collided = false

Solution

  • I think your time is created and working. It just don't pause any other loop.

    You can verify that if you place a print in front of the timer and after it. You will see, that the second log will be printed after 3 seconds, while your game loop is running.

    Without knowing your code I can just guess, but I assume your ball just has a movement logic, which runs as soon the ball is in the scene.

    You could add an "paused" flag, which stops the ball if true:

    #Ball Script assuming the movement code sits in physics process
    var paused : bool = false    
    func _physics_process(delta):
       if paused:
          return  #do nothing as long the paused variable is set
       #your movement logic
    

    Now with that flag you could raycast logic can be extended to look like this:

    func _physics_process(delta):
        if $RayCast2D.is_colliding():
            if (!already_collided):
                already_collided = true
                $Ball.paused = true #pause ball before repositioning
                $Ball.position.x = 575
                $Ball.position.y = 350
                Globals.p2_score += 1
                $Label2.text = str(Globals.p2_score)
                await get_tree().create_timer(3).timeout #timer
                $Ball.paused = false #start movement after 3 seconds
            else:
                already_collided = false
            
        if $RayCast2D2.is_colliding():
            if (!already_collided):
                already_collided = true 
                $Ball.paused = true
                $Ball.position.x = 575
                $Ball.position.y = 350
                Globals.p1_score += 1
                $Label.text = str(Globals.p1_score)
                await get_tree().create_timer(3).timeout #timerv
                $Ball.paused = false
            else:
                already_collided = false
    

    Or just create a reset_ball function in your ball script to make your code cleaner:

    func reset_ball():
        paused = true
        position.x = 575
        position.y = 350
        await get_tree().create_timer(3).timeout #timerv
        paused = false
    

    and call this when colliding:

    func _physics_process(delta):
        if $RayCast2D.is_colliding():
            if (!already_collided):
                already_collided = true
                Globals.p2_score += 1
                $Label2.text = str(Globals.p2_score)
                $Ball.reset_ball()
            else:
                already_collided = false
    #...