How to fix Pong Ball physics?

Godot Version

Godot 4.2

Question

I’m working on a Pong Game and one of the things that has bothered me is the fact that the ball goes faster when hitting the tip of the paddle, and then goes slow when hitting the middle (which also makes the ball not change direction at all during the start of the game). I want the ball to go at a consistent speed so that when I gradually change the speed of the ball during the game, it doesn’t go from slow to ultrafast based on where you hit.

Also when the ball hits the paddle (say from the left side of the wall to the right), instead of going to the right side, it goes back to the left. Here’s the code I’m using, Please tell me what I’m doing wrong here (Credits to @sven for letting me use the code and build it from there, and @pennyloafers for the notes:

func _physics_process(delta):
	# moves charbody and returns collided objects, borders or paddles
	var collision = move_and_collide(movement * delta)
		
	if collision:
		if collision.get_collider().name == "Paddle":
	  #reverses direction 
			# gets difference position  of paddle position and ball position.
			var diff = collision.get_collider().position.x - position.x
			# use difference to change up/down direction of ball movement.
			var new_movement = Vector2(-diff * 5, speed)
			# update movement 
			movement = new_movement
			if can_add_score == true:
				speed = -speed
				can_add_score = false
				score += 1
				label.text = str(score)
				%Timer.start()
				print(can_add_score)
		elif collision.get_collider().name == "Borders":
	  # collision normal is the direction the border is facing. Bounce function just reflects the movement vector at an angle between the normal and movement.
			movement = movement.bounce(collision.get_normal())
		elif collision.get_collider().name == "DeathArea":
			game_over_screen.visible = true
			get_tree().paused = true
			print("Collided")

Thanks in Advance :smiley:

Hi, nothing in the code you’ve posted makes the ball go faster when it hits the tip / middle of the paddle (assuming they are vertical paddles?) the value of speed is only made negative or positive and the absolute value is not changed. speed is also only used for the y component of movement. the x component of the movement is determined by the distance from the paddle, which should more or less be the same for each paddle since they are vertical not horizontal.

I think it’s related to this. ( Although the code is a little hard to follow )

Since diff is scaled by 5 it will make the ball 5 times faster in the x axis when the diff is larger like you stated in the post.

You need to calculate a direction, and this code sort of does this in a roundabout way. But it is also giving you a larger speed vector.

We can remove that largeness by normalizing the vector to a length of one, then extend the vector by your speed scale.

var new_movement = Vector2(-diff * 5, speed).normalized() * speed

You can now imagined this as new_direction * speed

@shatteredreality So it has something to do with the direction instead?
@pennyloafers I’m still learning to understand such concepts, but I can try your code and see if it works

@pennyloafers I tried it, but now the ball doesn’t even bounce and just stays on the paddle trying to go down. Any other solutions?

i’m guessing the reason the code doesn’t work is because speed is far greater than -diff * 5 so when it’s normalized the x component is basically zero. idk how pong works, does the ball only move in a line perpendicular to the paddles? so like it’s always the same angle?

No, the ball hits the paddle and changes from something like a 45 degree angle, so think of the path as an upside down V, I’ll change -diff * 5 and see if it works

if it’s like the wall could you just get the normal from the collider like the wall does?

No matter what value I put/change it to, (yes even negative) the Y components goes from -something, to even 0. How do I fix this/What other solution can I use?

Try using the bounce function like you do on the wall?

If @shatteredreality s suggestion doesn’t help I think I need to see more of the script. Like what is the value of speed?

And I have a vision of what pong looks like but the code doesn’t seem to fit my understanding. Could you also share a screenshot of the game or a short video? (If you know how)

@shatteredreality I’ll try it out

@pennyloafers Sure, I can send a video. will probably make it easier to see where the problem is

Here’s the screen recording:


If you look and observe closely, You can basically make a checklist of all the problems I’ve just mentioned. At least now you can see exactly what I’m talking about.

Here’s the extra code btw:

extends CharacterBody2D

var speed = 500
var movement = Vector2(0, speed)
var score = 0
var can_add_score = true
@onready var label = $"../Score"
@onready var game_over_screen = $"../GameOverScreen"
1 Like

Oh. So your paddle isn’t vertical :sob:

Let me know how using bounce function goes!

How should I apply it in the code btw?

same as you have already movement = movement.bounce(collision.get_normal())

I mean, I already have that in the code and it doesn’t make that much of a difference. What do you mean exactly? Should I put it somewhere else?

you only have it for the wall not the paddle, you should put it when it collides with the paddle as well

Alright, I’ll try it and see if it works.

Where specifically in the code can I apply it though? Because I dont see anywhere where this line of code could fit perfectly without causing any errors