godotpong

Godot Pong Replay After Every Game


I'm currently working on my Pong game project using Godot.

Everything is working well but there's only one problem.

After one side gets scored, the ball is stuck in the middle and not working.

What should I add? Here is my code:

# Declare member variables here.
var ball
var player
var computer
var player_score = 0
var computer_score = 0
var winning_score = 5
var initial_velocity_x = 250
var initial_velocity_y = 10

# Called when the node enters the scene tree for the first time.
func _ready():
    player = get_node('player')
    computer = get_node('computer')
    ball = get_node('ball')


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    player.position.y = get_viewport().get_mouse_position().y
    computer.position.y = ball.position.y
    
    if ball.position.x > 1024:
        reset_position()
        ball.linear_velocity.x = initial_velocity_x
        ball.linear_velocity.y = initial_velocity_y
        computer_score += 1
        
    if ball.position.x < 0:
        reset_position()
        ball.linear_velocity.x = -initial_velocity_x
        ball.linear_velocity.y = initial_velocity_y
        player_score += 1
    
    if player_score >= winning_score or computer_score >= winning_score:
        player_score = 0
        computer_score = 0
    
func reset_position():
    ball.position.x = 512
    ball.position.y = 300

Solution

  • I'm guessing the ball is a RigidBody2D.

    They are intended to be moved by the physics engine, and moving them directly (e.g. setting position) can cause problems. This one of the reason I often recommend beginners to use KinematicBody(2D), so they are not "fighting" the physics engine.

    Anyway, that is a cop-out answer. You want to teleport a RigidBody2D, let us see how to do it.


    The following is - in my opinion - the elusive proper way to teleport a RigidBody2D:

    func reset_position():
        Physics2DServer.body_set_state(
            ball.get_rid(),
            Physics2DServer.BODY_STATE_TRANSFORM,
            Transform2D.IDENTITY.translated(Vector2(512, 300))
        )
    

    You are basically saying: "Hey, Physics Engine! Yes, you. I want you to place the body at this position." And the Physics Engines goes: "OK".

    The Physics2DServer API is intended for advanced use, when using nodes won't do. And as such, not beginner friendly.


    Instead, the most common solution to teleport a RigidBody2D involves adding an script to it. It looks like this:

    extends RigidBody2D
    
    
    var _teleport_target:Vector2
    var _teleporting:bool
    
    
    func _integrate_forces(state: Physics2DDirectBodyState) -> void:
        if _teleporting:
            state.transform.origin = _teleport_target
            _teleporting = false
    
    
    func teleport(position:Vector2) -> void:
        _teleporting = true
        _teleport_target = position
    

    And then you use it like this:

    func reset_position():
        ball.teleport(Vector2(512, 300))
    

    Here you have told the Physics Engine to ask you every time if you want to change something (it will call _integrate_forces if you define it). And occasionally you answer by telling it to move the body.