Ball gets stuck instead of bouncing using bounce() and move_and_collide()

Godot Version 4.3

Hi everyone. I’m new to gamedev and Godot so I hope you can help me out, I’m sure it’s something easy to figure out.

I’m making a brick breaker type game, with the typical elements of a ball, a paddle, walls and bricks. Both the ball and the paddle are CharacterBody2D, while the walls and bricks are StaticBody2D.

This is the ball movement code:

@export var velocidad = 500

func process(delta):
	if velocity == Vector2.ZERO and Input.is_action_pressed("Space"):
		set_velocidad()

#This function is called every time the player presses a button to start the game or restarting after losing a life:
func set_velocidad():
	if randi() % 2 == 0:
		velocity.x = [0.1, -0.1].pick_random()
		velocity.y = -1
	else:
		velocity.x = [-0.4 , 0.4].pick_random()
		velocity.y = -1
	
	velocity *= velocidad

func _physics_process(delta):
	var colisionInfo = move_and_collide(velocity * delta)
	if colisionInfo:
        velocity = velocity.bounce(colisionInfo.get_normal())
        var checkBrick = colisionInfo.get_collider()

#Here the code continues with what happens when the ball hits a brick (scoring points, removing the brick, playing sounds, etc.). I don't put it because there is no problem with this part.

The code works fine when the ball hits a non-moving object (like a brick) but the problem comes when the ball hits one of the sides of a moving object (i.e. the paddle moved by the player, or moving obstacles in certain game levels which are also of type StaticBody2d). The ball does not bounce back but stays stuck to the object it collided with. This only happens when it hits one of the sides of the paddle, not when it hits the top, and only when the paddle is moving. The ball will bounce correctly off the paddle if it is not moving, even if it hits one of its sides.

When this problem occurs, the sound that is played when the ball hits something is played indefinitely and quickly, as if the collision were being detected over and over again, but without the rebound effect occurring.

Note: The problem only occurs when the ball and paddle are moving in opposite directions. If the ball hits one side of the paddle while it is moving, but it does so in the same direction as the ball (both in x or -x), the ball will bounce correctly.

I am not familiar with English writing, so I apologize if the post is not easy to read.

Does the paddle use move_and_collide? It sounds like the paddle is moving into the ball which will cause a deeper collision than .bounce alone can handle, it will bounce away, but still be a pixel within the wall so another collision happens thus another bounce.

Maybe you can check the dot product of the collision normal and the ball’s current velocity.

func _physics_process(delta):
	var colisionInfo := move_and_collide(velocity * delta)
	if colisionInfo:
		var normal := colisionInfo.get_normal()
		if normal.dot(velocity.normalized()) <= 0.0:
			velocity = velocity.bounce(normal)
			var checkBrick = colisionInfo.get_collider()
1 Like

Yes, the paddle uses move_and_collide(). The paddle is on layer 1 and has masks 1 and 2. The ball is on layer 2 and has mask 1.

The paddle only moves in the x-axis (I guess that’s why the bug only happens when the ball hits one of the sides)

I tried the code you suggested and it doesn’t seem to change anything :frowning:

I think the problem is that when the paddle is moving and the ball collides, the CollisionInfo variable is updated over and over again, without the bounce() effect ever being processed. If that’s the problem I honestly have no idea how to solve it.

EDIT: By activating mask 2 and making the paddle detect the ball as well, your code worked! Thanks for the help.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.