Godot Version
4.2.1
Question
I’m currently making a sokoban/box pushing game similar to Steven Sausage Roll. The player can move around and push boxes, but it can also rotate depending its orientation. To achieve this, I’m making use of the player object’s sprite.transform.y
to move in the direction the sprite is facing. I’m using the sprite, because I’d like certain objects like the raycast to not rotate along with the parent.
The way it works is that, if the player is facing upwards, and the player press up or down keys, the player will move up or down. However, if the player is facing upwards and presses for instance, the right arrow key, it will rotate to the right instead. Then if the player presses the right arrow key, it will move to the right.
For the most part this works. The problem is, because of the way radians work, I get floating point errors. This is obvious, hence I use the is_equal_approx()
function to compare the player’s sprite.transform.y
with the input the player pressed (each input has a Vector2 assigned to them). The only issue is that, sometimes, the player’s sprite.transform.y
component has a value like 0.000012 (as seen in the image). However, this value is slightly above the limits that is_equal_approx()
considers when comparing two values. It works fine when the value is something like 0.000005 (has 5 decimal zeros), but as soon as it goes above 0.000010 (has 4 decimal zeros), the is_equal_approx()
returns false.
I was wondering if there was anyway I could solve this issue? Perhaps some kind of regression? Or do I create my own function for this purpose?
Code:
extends StaticBody2D
@onready var raycast = $RayCast2D
@onready var sprite = $Sprite2D
var grid_size: int = 64
var input_dir: Dictionary = {
"up": Vector2.UP,
"down": Vector2.DOWN,
"left": Vector2.LEFT,
"right": Vector2.RIGHT,
}
func _unhandled_input(event):
for key in input_dir:
if event.is_action_pressed(key):
move(input_dir[key])
print(input_dir[key], sprite.transform.y)
func move(dir:Vector2):
raycast.target_position = dir * grid_size
raycast.force_raycast_update()
if dir.is_equal_approx(sprite.transform.y) or dir.is_equal_approx(sprite.transform.y * -1):
if not raycast.is_colliding():
position += dir * grid_size
else:
var neighbour: Object = raycast.get_collider()
if neighbour.is_in_group("wall"):
print("Collided with wall!")
elif neighbour.is_in_group("block"):
if neighbour.move(dir):
position += dir * grid_size
else:
var target_angle: float = sprite.transform.y.angle_to(dir) + PI
sprite.rotation_degrees += rad_to_deg(target_angle)
print(sprite.rotation_degrees)