Ball keeps bugging out in my ping pong game

The code for the ball is this:

extends CharacterBody2D

@onready var speed_timer: Timer = $speed_timer
var screen_size: Vector2
var dir = get_ran_dir()
var speed = 100
var out_bounds: bool = false
var middle = Vector2()
var high: bool
var low: bool


func _ready() -> void:
	screen_size = get_viewport_rect().size
	position = Vector2(screen_size.x / 2, screen_size.y / 2)
	speed_timer.start()
	speed_timer.timeout.connect(_speed_change)
	
	
func _physics_process(delta: float) -> void:
	var collision = move_and_collide(dir * speed * delta)
	if collision:
		dir = dir.bounce(collision.get_normal())
	position_tracking()
	
func _speed_change() -> void:
		speed = speed * 1.5 

func get_ran_dir() -> Vector2:
	var new_dir = Vector2()
	new_dir.x = [1,-1].pick_random()
	new_dir.y = [1,-1].pick_random()
	return new_dir.normalized()

func position_tracking() -> void:
	high = position.x >= screen_size.x or position.y >= screen_size.y
	low = position.x <= -screen_size.x or position.y <= -screen_size.y
	middle = Vector2(screen_size.x / 2, screen_size.y / 2)
	screen_size = get_viewport_rect().size
	if high or low:
		position = middle
		speed = 100
		print("return")

This is a local online ping pong game and I have a multiplayer synchronizer that synced to the root node, which is a character2d node and is the node that contains the code. My issue is that whenever I start the game the ball looks like its teleporting rapidly between 2 places while its moving and it gets worse as it gets faster.

How come you’re using a CharacterBody2D instead of a RigidBody2D?

rigid body does something weird. It has the same problem as characterbody2d but it also stays on the ground.

Oh well you are passing delta to move_and_collide(). That’s your problem. move_and_collide() and move_and_slide() already use delta in their calculations.

If I remove delta from the move_and_collide parameters the ball goes crazy and moves extremely fast.

KinematicCollision2D move_and_collide(motion: Vector2, test_only: bool = false, safe_margin: float = 0.08, recovery_as_collision: bool = false)
Moves the body along the vector motion. In order to be frame rate independent in Node._physics_process() or Node._process(), motion should be computed using delta.

No, move_and_collide() does not use delta on its own.

1 Like

Oops, I was wrong. You need delta in move_and_collide(), not move_and_slide().

What happens if you lower the speed?

Would increase the framerate fix the problem. and the same issue happens when its slower.
Update: I tested it offline and it doesnt have the teleportation problem offline. The teleportation problem is probably because of the multiplayer synchronizer.

1 Like

What properties are you synchronizing?

just the position of the root(Characterbody2d) node. I did the same for the player paddles and they work fine. For reference here is the code for the player paddle. I also synced a multiplayer synchronizer to the rotation of the root node for the paddle if that matters.

extends CharacterBody2D

const SPEED = 300.0
@export var rotation_speed = 3.0 # Speed of rotation
@export var speed = 400.0 # Movement speed

func _ready() -> void:
	set_multiplayer_authority(name.to_int())

func _physics_process(delta: float) -> void:
	if !is_multiplayer_authority(): return
	
	var direction := Input.get_axis("Left", "Right")
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()
	
	var direction_hor := Input.get_axis("up", "down")
	if direction_hor:
		velocity.y = direction_hor * SPEED
	else:
		velocity.y = move_toward(velocity.y, 0, SPEED)

	move_and_slide()
	
	if Input.is_action_pressed("Rotate clockwise"):
		rotation -= rotation_speed * delta
	elif Input.is_action_pressed("Rotate counter clockwise"):
		rotation += rotation_speed * delta

I’ve changed the paddle since my last post so all the code from the physics and sprite nodes was moved to the root node.

@pennyloafers Got any ideas?

I figured it out. I used authority checks and it works:

extends CharacterBody2D


@onready var speed_timer: Timer = $speed_timer
var screen_size: Vector2
var dir = get_ran_dir()
var speed = 100
var out_bounds: bool = false
var middle = Vector2()
var high: bool
var low: bool

func _ready() -> void:
	screen_size = get_viewport_rect().size
	position = Vector2(screen_size.x / 2, screen_size.y / 2)
	set_multiplayer_authority(multiplayer.get_unique_id())

func _physics_process(delta: float) -> void:
	var collision = move_and_collide(dir * speed * delta)
	if collision:
		dir = dir.bounce(collision.get_normal())
	position_tracking()

func get_ran_dir() -> Vector2:
	var new_dir = Vector2()
	new_dir.x = [1,-1].pick_random()
	new_dir.y = [1,-1].pick_random()
	return new_dir.normalized()

func position_tracking() -> void:
	if !is_multiplayer_authority(): return
	high = position.x >= screen_size.x / 1.01 or position.y >= screen_size.y 
	low = position.x <= -screen_size.x / 1.01 or position.y <= -screen_size.y 
	middle = Vector2(screen_size.x / 2, screen_size.y / 2)
	screen_size = get_viewport_rect().size
	if high or low:
		position = middle
		speed = 100
		print("return")

1 Like

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