class_name ControllablePlayer extends Player @export var map: Node3D @export var camera: FollowCamera var facing = Vector2(1, 0) var velocity = Vector2(0, 0) func _ready(): var timer = Timer.new() timer.one_shot = false timer.wait_time = 1. / 25. add_child(timer) timer.start() timer.connect("timeout", func(): Multiplayer.send_position(Vector2(position.x, position.z), -rotation.y + .5 * PI) ) func _process(delta): var input = Vector2(Input.get_axis("left", "right"), Input.get_axis("forward", "backwards")).normalized() input = input.rotated(-camera.angle_target) if input.length() > 0.1: facing = lerp_vector2_exp(facing, input, delta * 10.) self.rotation.y = facing.angle() velocity.x += input.x * delta * SPEED velocity.y += input.y * delta * SPEED position = Vector3( position.x + (velocity.x * delta), 0, position.z + (velocity.y * delta) ) # collide collide(delta) velocity = lerp_vector2_exp(velocity, Vector2(0, 0), delta * 5.) func collide(_delta: float): for i in map.get_children(): if is_instance_of(i, FullTile): var tile: FullTile = i var d = aabb_circle_distance( tile.position.x, tile.position.z, tile.position.x + 1, tile.position.z + 1, position.x, position.z ) if d > PLAYER_SIZE: continue var h = 0.01 var d_sample_x = aabb_circle_distance( tile.position.x, tile.position.z, tile.position.x + 1, tile.position.z + 1, position.x + h, position.z ) var d_sample_y = aabb_circle_distance( tile.position.x, tile.position.z, tile.position.x + 1, tile.position.z + 1, position.x, position.z + h ) var grad_x = (d_sample_x - d) / h var grad_y = (d_sample_y - d) / h position.x += (PLAYER_SIZE - d) * grad_x position.z += (PLAYER_SIZE - d) * grad_y var vdotn = (grad_x * velocity.x) + (grad_y * velocity.y) velocity.x -= grad_x * vdotn velocity.y -= grad_y * vdotn # TODO: Player collisions func lerp_vector2_exp(current: Vector2, target: Vector2, delta: float) -> Vector2: return Vector2( target.x + (current.x - target.x) * exp( - delta), target.y + (current.y - target.y) * exp( - delta) ) func aabb_circle_distance( min_x: float, min_y: float, max_x: float, max_y: float, px: float, py: float ) -> float: var dx = px - max(min_x, min(max_x, px)) var dy = py - max(min_y, min(max_y, py)) return sqrt(dx * dx + dy * dy) func update_position(_new_position: Vector2, _new_rotation: float): pass