MagicNStuff/source/components/characters/character_base.gd
2025-02-25 22:07:11 +01:00

87 lines
2.8 KiB
GDScript

class_name CharacterBase3D
extends CharacterBody3D
@export var movement: CharacterMovementBase
var speed: float = 0.0
var movement_direction: Vector3
var ground_control: float = 1.0
var air_control: float = 1.0
# If [code]true[/code], [member air_control] won't be reset to [code]1.0[/code] when touching the ground.
var freeze_air_control: bool = false
var last_platform_velocity := Vector3.ZERO
var _was_on_floor: bool = false
func move(direction: Vector3, delta: float) -> void:
direction *= speed
var on_floor: bool = is_on_floor()
if on_floor:
last_platform_velocity = get_platform_velocity()
# Remove platform velocity when landing.
if not _was_on_floor:
velocity -= get_platform_velocity() # TODO: Test if last_platform_velocity is desired.
else:
direction += last_platform_velocity
_was_on_floor = on_floor
var acceleration: float = movement.max_acceleration if on_floor else movement.max_air_acceleration
var deceleration: float = movement.max_friction if on_floor else movement.max_air_friction
var turning_speed: float = movement.max_turning_speed if on_floor else movement.max_air_turning_speed
var speed_change: float = acceleration
if direction.is_zero_approx():
speed_change = deceleration
else:
var flat_velocity: Vector3 = velocity * Utils.VEC3_HOR
if direction.sign() != flat_velocity.sign():
speed_change = turning_speed
#DebugDraw3D.draw_arrow(global_position, global_position + direction, Color.ORANGE, 0.5, true)
direction.y = velocity.y
speed_change *= ground_control if on_floor else air_control
if on_floor and not freeze_air_control:
air_control = 1.0
velocity = velocity.move_toward(direction, speed_change * delta)
#DebugDraw3D.draw_arrow(global_position, global_position + velocity, Color.BLUE, 0.5, true)
#Logger.print_msg("%s Velocity: %s" %[self , velocity], 0.02)
## @tutorial: https://gmtk.itch.io/platformer-toolkit/devlog/395523/behind-the-code
func apply_gravity(delta: float) -> void:
var margin: float = movement.gravity_check_margin
var gravity_multiplier: float = 1.0
if velocity.y < -margin:
#Logger.print_msg("Falling\n%s" %velocity.y, 0.02)
gravity_multiplier = movement.fall_gravity_multiplier
elif velocity.y > margin:
#Logger.print_msg("Rising\n%s" %velocity.y, 0.02)
gravity_multiplier = movement.rise_gravity_multiplier
else:
#Logger.print_msg("Peaking\n%s" %velocity.y, 0.02)
gravity_multiplier = movement.peak_gravity_multiplier
velocity.y -= (movement.get_gravity() * gravity_multiplier) * delta
## @tutorial: https://gmtk.itch.io/platformer-toolkit/devlog/395523/behind-the-code
func jump() -> void:
var jump_strength: float = sqrt(-2.0 * -movement.get_gravity() * movement.jump_height)
if velocity.y > 0.0:
jump_strength = maxf(jump_strength - velocity.y, 0.0)
elif velocity.y < 0.0:
jump_strength += absf(velocity.y)
velocity.y += jump_strength