phs-galaxy/Player.gd

113 lines
3.3 KiB
GDScript3
Raw Normal View History

2021-03-25 21:36:04 +01:00
extends KinematicBody
2021-04-22 23:40:01 +02:00
const MAX_VEL = 500.0
2021-03-25 21:36:04 +01:00
var acceleration := Vector3(0.0, -9.81, 0.0)
var velocity := Vector3(0.0, 0.0, 0.0)
2021-04-22 23:40:01 +02:00
var move_accel = 60.0
var rotate_speed = 2.0
2021-04-22 23:40:01 +02:00
var drag = 0.05
# Jumping
var jumping := false
var on_ground := false
var time_since_jump_start := 0.0
var initial_jump_burst = 10.0
var jump_exponent = 0.05
2021-03-25 21:36:04 +01:00
var current_target_velocity := Vector3.ZERO
2021-03-25 21:36:04 +01:00
export(NodePath) var solar_system
2021-04-22 23:40:01 +02:00
func _input(event):
if event.is_action_pressed("jump") and on_ground:
on_ground = false
jumping = true
time_since_jump_start = 0.0
elif event.is_action_released("jump"):
jumping = false
func get_center():
return global_transform.origin + global_transform.basis.y
2021-04-22 23:40:01 +02:00
func apply_acceleration(acceleration):
# First drag, then add the new acceleration
# For drag: Lerp towards the target velocity
# This is usually 0, unless we're on something that's moving, in which case it is that object's
# velocity
velocity = lerp(velocity, current_target_velocity, drag)
2021-04-22 23:40:01 +02:00
velocity += acceleration
2021-03-25 21:36:04 +01:00
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
var move_velocity := Vector3.ZERO
var move_acceleration := Vector3.ZERO
# Movement and rotation
2021-04-22 23:40:01 +02:00
if Input.is_action_pressed("move_up"):
move_acceleration.z -= move_accel
if Input.is_action_pressed("move_down"):
move_acceleration.z += move_accel
if Input.is_action_pressed("move_left"):
rotate(transform.basis.y, delta * rotate_speed)
2021-04-22 23:40:01 +02:00
if Input.is_action_pressed("move_right"):
rotate(transform.basis.y, -delta * rotate_speed)
2021-03-25 21:36:04 +01:00
# Make movement local
2021-04-22 23:40:01 +02:00
move_acceleration = transform.basis * move_acceleration
2021-03-25 21:36:04 +01:00
# Jumping and Gravity
var gravity_acceleration = get_node(solar_system).get_gravitation_acceleration(transform.origin)
2021-04-22 23:40:01 +02:00
apply_acceleration((move_acceleration + gravity_acceleration) * delta)
2021-03-25 21:36:04 +01:00
2021-04-22 23:40:01 +02:00
# Handle jumping
if jumping:
# Continuously apply an impulse by adding velocity: a lot at first, then less until it's 0
# Use max() to avoid NaN from being applied once no more impulse should be added
var e_section = max(
exp(log(initial_jump_burst - 1 / jump_exponent * time_since_jump_start)),
0.0
)
2021-04-22 23:40:01 +02:00
velocity += -gravity_acceleration.normalized() * e_section
time_since_jump_start += delta
2021-03-25 21:36:04 +01:00
# Apply movement to position
2021-04-22 23:40:01 +02:00
# FIXME: move_and_slide might make more sense, but couldn't quite get that to work...
#move_and_slide(velocity, -gravity_acceleration.normalized(), true)
var collision = move_and_collide(velocity * delta)
if collision:
if collision.collider.is_in_group("MovingPlatform"):
# Inherit the moving platform's velocity
current_target_velocity = collision.collider.velocity
velocity = current_target_velocity
if not jumping:
on_ground = true
else:
# We're not colliding with anything, so drag takes us towards 0
current_target_velocity = Vector3.ZERO
2021-03-25 21:36:04 +01:00
2021-04-22 23:40:01 +02:00
# Clamp the velocity just to be save
velocity.x = clamp(velocity.x, -MAX_VEL, MAX_VEL)
velocity.y = clamp(velocity.y, -MAX_VEL, MAX_VEL)
velocity.z = clamp(velocity.z, -MAX_VEL, MAX_VEL)
2021-03-25 21:36:04 +01:00
# Rotate down vector to face center of gravity
var down = gravity_acceleration
var local_down = transform.basis * Vector3.DOWN
var angle = local_down.angle_to(down)
var axis = local_down.cross(down).normalized()
# An axis of 0 happens if we're perfectly aligned already (local_down and down are equal)
if axis != Vector3.ZERO:
2021-03-25 21:36:04 +01:00
rotate(axis, angle)