Ball goes out of bounds when it collides with two area2D objects

Godot Version

4.2.2

Explanation

Hello everyone, I have made my version of PONG using Godot 4 as a way to learn the engine. Currently, the game is 99% complete except for one bug that I can’t figure out how to solve it.

I won’t waste your time explaining how PONG works in general but, basically, the problem I have is when there is the collision of the ball between the wall and the paddle, especially the latter when it’s near the wall, the ball just goes outside the play area.

bug

All three objects, paddles, ball and walls (top and bottom) are all Area2D nodes with a CollisionShape2D node as a child. Both the paddles and the ball have a RectangleShape2D as the shape for the collision, while the walls have a WorldBoundaryShape2D as the shape for the collision detection.

Also, those are the scripts I have written for the collision detection

  • Wall
func _on_area_entered(area):
	if area is Ball:
		# Increase the speed of ball
		area._speed += randi_range(15, 20)
		# Change direction
		area._direction.y = -area._direction.y
  • Paddle
func _on_area_entered(area):
	# If the ball is entered
	if area is Ball:
		# Increase the speed
		area._speed += randi_range(25, 50)
		# Get the difference in position of the two objects
		var pos_diff = (area.global_position - self.global_position).normalized().y
		# Change the direction
		area._direction = Vector2(-area._direction.x, pos_diff)

If you want to give a look to the source code the game is open source and can be easily downloaded without any additional stuff to add into the folder project.

If you want to check this bug, here is the link to the game

Question

How can I solve this issue? Should I change something in the code?
I know the existence of a pong demo made already in Godot but, I’ll be honest, I don’t like that if the ball goes out of bounds it simply resets.

just make the wall a bigger staticbody2d collision?

Hi. Thanks for the reply.

I don’t think the problem is the base node, either Area2D or StaticBody2D can be fine for the walls.

The problem is the collision detection that are handled through signals, specifically with the Area2D area_entered signal. It seems that when the ball goes in collision with the paddle the collision is detected but immediately after the collision with the wall either is detected but the code I wrote isn’t correct or the collision isn’t detected.

The thing is the signal area_entered is a signal that is executed only once when the object enters into an area, which are the collision shapes in this case.

I did a quick research on finding an alternate way for making the detection continuous for the wall, like the OnTriggerStay method in the Unity Engine, but I couldn’t find anything.

I might have found a possible solution to my problem.

Since the problem is the ball goes out of bound, I have tried different solutions to solve the problem (the ones with :x: means it failed, the one with :white_check_mark: means it worked):

  • Trying to change the code for the collision in the wall by forcing the direction of the ball in the y direction. Unfortunately this didn’t work for me. :x:
  • Add the VisibleOnScreenNotifier2D into the ball scene and reset the ball when it’s outside of the playground. This didn’t work either because, even if I set the dimension of the Notifier to the minimum, when the ball moves faster it could happen to get almost outside of the screen, even when it collides with the wall. The result I got was the ball gets reset 2/3 times even if it didn’t go out of bounds. :x:
  • Add two more Area2D nodes on top and bottom of the screen that executes the reset of the position of the ball when the ball goes out of bounds. This actually solved the problem because when the ball goes out of bounds it is reset and the game can continue without the issue of losing the ball. :white_check_mark:

I have also seen other people made their version of Pong with Godot and one of them made a script of the ball that extends tthe CharacterBody2D node and uses the move_and_collide method to solve the issue. This to me is kinda of an easy mode because, as I stated, the version I made of Pong doesn’t have much of the physics applied since most of the nodes are simple Area2D nodes.

Although the solution I have made might not be perfect, I hope it can be useful for someone if it is going to make Pong with Godot.