Compare commits

..

5 Commits

Author SHA1 Message Date
0f90dd61f2 Fix moving platform behavior
It seems like when you pass an up_vector to move_and_slide, that handles moving platforms for you! Although not 100% correctly...

The manual implementation was added again without an up_vector and that seems to work perfectly now.
2021-06-19 01:11:16 +02:00
62956d8d7d Make MovingPlatform also use planet-only gravity
also made it a bit larger
2021-06-16 20:58:12 +02:00
78db1629b5 Lerp between planet-only and total gravity 2021-06-16 20:53:33 +02:00
596f4ddbc5 Some cleanup in Player 2021-06-16 20:41:26 +02:00
725c717446 Fix sliding while on planet by getting closest gravity 2021-06-16 20:33:24 +02:00
7 changed files with 177 additions and 98 deletions

View File

@ -3,7 +3,7 @@
[ext_resource path="res://Resources/gas_planet_flowmap.png" type="Texture" id=1] [ext_resource path="res://Resources/gas_planet_flowmap.png" type="Texture" id=1]
[ext_resource path="res://Resources/gas_planet_base.png" type="Texture" id=2] [ext_resource path="res://Resources/gas_planet_base.png" type="Texture" id=2]
[sub_resource type="Shader" id=14] [sub_resource type="Shader" id=1]
resource_local_to_scene = true resource_local_to_scene = true
code = "shader_type spatial; code = "shader_type spatial;
@ -38,7 +38,7 @@ void fragment(){
" "
[resource] [resource]
shader = SubResource( 14 ) shader = SubResource( 1 )
shader_param/color = Color( 1, 0.890196, 0.172549, 1 ) shader_param/color = Color( 1, 0.890196, 0.172549, 1 )
shader_param/flow_speed = 0.2 shader_param/flow_speed = 0.2
shader_param/flow_intensity = 0.8 shader_param/flow_intensity = 0.8

View File

@ -31,7 +31,7 @@ func _process(delta):
velocity = (translation - translation_before) / delta velocity = (translation - translation_before) / delta
# Rotate according to gravity # Rotate according to gravity
var gravity_acceleration = get_node(solar_system).get_gravitation_acceleration(global_transform.origin) var gravity_acceleration = get_node(solar_system).get_closest_gravity_acceleration(global_transform.origin)
# Rotate down vector to face center of gravity # Rotate down vector to face center of gravity
var down = gravity_acceleration var down = gravity_acceleration

View File

@ -13,7 +13,30 @@ const distance_multiplier = 318550 # thus, a radius of 20 results in an earth-
const gravity_multiplier = 10.0 const gravity_multiplier = 10.0
func get_gravitation_acceleration(position: Vector3) -> Vector3: # Return the gravity acceleration vector to the closest planet, not taking all other planets into
# account.
# This is useful for keeping something firmly on the planet while it is touching it, or for creating
# a predictable orbit.
func get_closest_gravity_acceleration(position: Vector3) -> Vector3:
var closest_planet_distance = INF
var closest_force = 0.0
for planet in get_children():
var pos_to_center = (planet.transform.origin - position)
var distance = pos_to_center.length()
if distance < closest_planet_distance:
var force = _gravity(planet.mass * mass_multiplier, distance * distance_multiplier)
force *= gravity_multiplier
closest_force = (pos_to_center / distance) * force
closest_planet_distance = distance
return closest_force
# Return the total gravity acceleration vector experienced at that position.
func get_gravity_acceleration(position: Vector3) -> Vector3:
var total_force = Vector3.ZERO var total_force = Vector3.ZERO
for planet in get_children(): for planet in get_children():

115
Player.gd
View File

@ -3,29 +3,34 @@ extends KinematicBody
const MAX_VEL = 500.0 const MAX_VEL = 500.0
var acceleration := Vector3(0.0, -9.81, 0.0) var acceleration := Vector3.ZERO
var velocity := Vector3(0.0, 0.0, 0.0) var velocity := Vector3.ZERO
var move_accel = 60.0 export var move_accel = 60.0
var rotate_speed = 2.0 export var rotate_speed = 2.0
var drag = 0.05 export var drag = 0.05
# Jumping # Jumping
var jumping := false var jumping := false
var on_ground := false
var time_since_jump_start := 0.0 var time_since_jump_start := 0.0
var initial_jump_burst = 10.0 export var initial_jump_burst = 10.0
var jump_exponent = 0.05 export var jump_exponent = 0.05
export var almost_on_ground_length = 1.0
var current_target_velocity := Vector3.ZERO var current_target_velocity := Vector3.ZERO
var has_inherited_velocity := false
export(NodePath) var solar_system export(NodePath) var solar_system
func _ready():
$GroundCheckRay.cast_to = Vector3.DOWN * almost_on_ground_length
func _input(event): func _input(event):
if event.is_action_pressed("jump") and on_ground: if event.is_action_pressed("jump") and is_on_ground():
on_ground = false
jumping = true jumping = true
time_since_jump_start = 0.0 time_since_jump_start = 0.0
elif event.is_action_released("jump"): elif event.is_action_released("jump"):
@ -45,6 +50,62 @@ func apply_acceleration(acceleration):
velocity += acceleration velocity += acceleration
func get_gravity_acceleration():
var total_gravity = get_node(solar_system).get_gravity_acceleration(transform.origin)
# If we're (almost) on the ground, accelerate only towards the planet we're on the ground of.
# Otherwise, get the total gravity of the solar system.
if $GroundCheckRay.is_colliding():
# Lerp between the planet's own gravity and the
var planet_gravity = get_node(solar_system).get_closest_gravity_acceleration(transform.origin)
var distance_to_collision = ($GroundCheckRay.get_collision_point()
- $GroundCheckRay.global_transform.origin).length()
# This factor is 0.0 if the player is exactly on the ground, and 1.0 if they're just barely
# almost grounded
var factor = inverse_lerp(0.0, almost_on_ground_length, distance_to_collision)
return lerp(planet_gravity, total_gravity, factor)
else:
# If the player is not grounded: return the whole acceleration caused by the entire solar
# system.
return total_gravity
# Returns true if the player is currently (almost) on the ground.
# Surfaces with an angle of 45° or less are considered a ground.
func is_on_ground():
if $GroundCheckRay.is_colliding():
var normal = $GroundCheckRay.get_collision_normal()
# An angle of >45° to the local up vector counts as grounded
if normal.dot(global_transform.basis.y) > 0.5:
return true
return false
# Returns true if the player is (almost) on the ground and that ground is a moving platform.
func is_on_moving_platform():
return is_on_ground() and $GroundCheckRay.get_collider().is_in_group("MovingPlatform")
# Set the current target velocity to the moving platform that is currently below the player.
# If this was the first collision frame, also inherit the platform's velocity.
func apply_moving_platform_velocity():
if not has_inherited_velocity:
velocity += $GroundCheckRay.get_collider().velocity
has_inherited_velocity = true
current_target_velocity = $GroundCheckRay.get_collider().velocity
# Reset the current target velocity and other variables relevant for moving platforms.
func reset_moving_platform_velocity():
current_target_velocity = Vector3.ZERO
has_inherited_velocity = false
# Called every frame. 'delta' is the elapsed time since the previous frame. # Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta): func _physics_process(delta):
var move_velocity := Vector3.ZERO var move_velocity := Vector3.ZERO
@ -63,14 +124,12 @@ func _physics_process(delta):
# Make movement local # Make movement local
move_acceleration = transform.basis * move_acceleration move_acceleration = transform.basis * move_acceleration
print(on_ground) # Get acceleration caused by gravity
var gravity_acceleration = get_gravity_acceleration()
# Jumping and Gravity # FIXME: Consider setting the gravity_acceleration to 0 if on ground
var gravity_acceleration = get_node(solar_system).get_gravitation_acceleration(transform.origin)
#if on_ground:
# FIXME: This breaks some things, but seems to be the right principle
#gravity_acceleration = Vector3.ZERO
# Apply both acceleration types
apply_acceleration((move_acceleration + gravity_acceleration) * delta) apply_acceleration((move_acceleration + gravity_acceleration) * delta)
# Handle jumping # Handle jumping
@ -84,26 +143,14 @@ func _physics_process(delta):
velocity += -gravity_acceleration.normalized() * e_section velocity += -gravity_acceleration.normalized() * e_section
time_since_jump_start += delta time_since_jump_start += delta
# Apply movement to position # Check for moving platforms and lerp towards that
velocity = move_and_slide(velocity, -gravity_acceleration.normalized(), true) if is_on_moving_platform():
on_ground = false apply_moving_platform_velocity()
if get_slide_count() > 0:
var collision = get_slide_collision(0)
if collision.collider.is_in_group("MovingPlatform"):
# Inherit the moving platform's velocity and apply the initial velocity
if current_target_velocity != collision.collider.velocity / 6.0:
current_target_velocity = collision.collider.velocity / 6.0
velocity = current_target_velocity
if not jumping:
# Check the collision normal and set to grounded if it's close to the player's up vector
if collision.normal.dot(global_transform.basis.y) > 0.5: # an angle of >45° counts as grounded
on_ground = true
else: else:
# We're not colliding with anything, so drag takes us towards 0 reset_moving_platform_velocity()
current_target_velocity = Vector3.ZERO
# Apply movement to position
velocity = move_and_slide(velocity)
# Clamp the velocity just to be save # Clamp the velocity just to be save
velocity.x = clamp(velocity.x, -MAX_VEL, MAX_VEL) velocity.x = clamp(velocity.x, -MAX_VEL, MAX_VEL)

38
Player.tscn Normal file

File diff suppressed because one or more lines are too long

View File

@ -26,7 +26,7 @@ func _physics_process(delta):
) )
if target: if target:
var gravity = solar_system.get_gravitation_acceleration(global_transform.origin) var gravity = solar_system.get_gravity_acceleration(global_transform.origin)
look_at(target, gravity) look_at(target, gravity)
global_transform.origin += velocity * delta global_transform.origin += velocity * delta

File diff suppressed because one or more lines are too long