diff options
Diffstat (limited to 'client/player/follow_camera.gd')
| -rw-r--r-- | client/player/follow_camera.gd | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/client/player/follow_camera.gd b/client/player/follow_camera.gd new file mode 100644 index 00000000..74355688 --- /dev/null +++ b/client/player/follow_camera.gd @@ -0,0 +1,65 @@ +# Undercooked - a game about cooking +# Copyright 2024 nokoe +# Copyright 2024 metamuffin +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, version 3 of the License only. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +class_name FollowCamera +extends Camera3D + +const ROTATE_SPEED: float = 1.5 +const ROTATE_WEIGHT: float = 8.0 +const ROTATE_UP_SPEED: float = 0.7 +const ROTATE_UP_WEIGHT: float = 4.0 +const ANGLE_UP_MIN: float = 0.5 +const ANGLE_UP_MAX: float = 1.2 +const LOOK_WEIGHT: float = 8.0 +const MOVE_WEIGHT: float = 2.0 +const CAMERA_DISTANCE: float = 10 + +@export var target: Node3D + +var angle_target: float = 0 +var angle: float = 0 +var angle_up_target: float = 1 +var angle_up: float = 1 +var ground: Vector3 + +func _ready(): + if target == null: + push_warning("target is not set") + else: + ground = target.position + +func _process(delta): + if target != null: + follow(delta) + +func follow(delta): + var new_transform = transform.looking_at(target.position) + + transform.basis = Basis.from_euler(Vector3( + lerp_angle(transform.basis.get_euler().x, new_transform.basis.get_euler().x, delta * LOOK_WEIGHT), + lerp_angle(transform.basis.get_euler().y, new_transform.basis.get_euler().y, delta * LOOK_WEIGHT), + lerp_angle(transform.basis.get_euler().z, new_transform.basis.get_euler().z, delta * LOOK_WEIGHT) + )) + + angle_target += Input.get_axis("rotate_left", "rotate_right") * ROTATE_SPEED * delta + angle = lerp_angle(angle, angle_target, delta * ROTATE_WEIGHT) + + angle_up_target += Input.get_axis("rotate_down", "rotate_up") * ROTATE_UP_SPEED * delta + angle_up_target = clamp(angle_up_target, ANGLE_UP_MIN, ANGLE_UP_MAX) + angle_up = lerp_angle(angle_up, angle_up_target, delta * ROTATE_UP_WEIGHT) + + ground = ground.lerp(target.position, delta * MOVE_WEIGHT) + position = ground + Vector3(0, sin(angle_up) * CAMERA_DISTANCE, cos(angle_up) * CAMERA_DISTANCE).rotated(Vector3.UP, angle) |