I made code to force a ball to reset back to its original location and speed after going out of bounds but now its resetting when it touches a paddle(Its supposed to bounce of like ping pong) It does still reset like its supposed to after going out of bounds though. I put some world boundaries along the viewport and everything else is working. Can someone fix 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()
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:
middle = Vector2(screen_size.x / 2, screen_size.y / 2)
screen_size = get_viewport_rect().size
if position == Vector2(screen_size.x, screen_size.y) or Vector2(-screen_size.x, -screen_size.y):
position = middle
speed = 100
print("return")
if position == Vector2(screen_size.x, screen_size.y) or position == Vector2(-screen_size.x, -screen_size.y):
Assuming everything else works correctly, this should solve your original problem.
However, I suggest you do it slightly different to avoid the problem you’ll inevitably find yourself in. Because you’re checking if position is equal, which is dangerous with float numbers, as it’s rarely equal exactly. What you should be doing in this case is to check if the position is equal or greater (or lower) than the other value. Something like this should be safer:
if position.x >= screen_size.x _
or position.x <= -screen_size.x _
or position.y >= screen_size.y _
or position.y <= -screen_size.y:
The two big problems with this line are using == for a Vector2 will only result in true if the position is exactly equal to the screen size, and floating point values can be very sub-pixel where 1.00000 ≠ 1.00001. You probably mean to use greater than, and you will have to use it on each component.
if position.x >= screen_size.x or position.y >= screen_size.y:
The next problem is the or Vector2... as the or condition does not know you also want to compare position to the Vector2, so it evaluates that it is not equal to zero.
This is equivalent to your original line
if position == Vector2(screen_size.x, screen_size.y) or Vector2(-screen_size.x, -screen_size.y):
# v functionally the same line ^
if position == Vector2(screen_size.x, screen_size.y) or Vector2.ZERO != Vector2(-screen_size.x, -screen_size.y):
So you must also check these values against position, assuming you mean to use less than or equal.
if position.x <= -screen_size.x or position.y <= -screen_size.y:
I would combine these conditions using variables.
var high: bool = position.x >= screen_size.x or position.y >= screen_size.y
var low: bool = position.x <= -screen_size.x or position.y <= -screen_size.y
if high or low:
position = middle
speed = 100
so by assigning high and low in the class body, the value is only calculated when the game starts.
# in class body, calculated once
var high: bool = position.x >= screen_size.x or position.y >= screen_size.y
var low: bool = position.x <= -screen_size.x or position.y <= -screen_size.y
# versus...
func position_tracking() -> void:
middle = Vector2(screen_size.x / 2, screen_size.y / 2)
screen_size = get_viewport_rect().size
# in a function, calculated each call
var high: bool = position.x >= screen_size.x or position.y >= screen_size.y
var low: bool = position.x <= -screen_size.x or position.y <= -screen_size.y
if high or low:
position = middle
speed = 100
print("return")
Another note is that it will only use position_tracking() if it collides with something, which may not happen out of bounds, maybe you mean to un-indent this line?
func _physics_process(delta: float) -> void:
var collision = move_and_collide(dir * speed * delta)
if collision:
dir = dir.bounce(collision.get_normal())
position_tracking() # this line is un-indented to always check out of bounds