So I have the beginnings of a platformer.
I want the player to be able to hop into water, swim down manually, then be pushed up when they’re not swimming down. This is where the up motion comes from. It is a desired behaviour.
When the player uses this buoyant motion to exit the water, gravity takes a second to counter the buoyancy and results in rising above the water line, letting the player leave the water. This, too, is a desired behaviour.
When the player hits the water, there is no middle ground where forces are not being applied. He is either moving up when in water or down when not in water. So, when he enters the water the next physics frame he’s leaving the water, launched at full speed upwards. This means that the problem is the sudden increase to his upwards momentum the frame after entering the water.
How would you solve this issue, keeping the desired behaviours? Measure depth in seconds, and only apply an upwards force when the player has accumulated some depth by holding the descend key? A better way? I’m all ears.
func _physics_process(delta):
velocity.x = direction.x * base_walk_speed * delta
# If underwater, we're buoyant.
if(is_underwater):
# Apply bouyancy here
velocity.y += direction.y * base_walk_speed * delta
velocity.y -= buoyancy * delta * base_walk_speed
velocity.y = clamp(velocity.y,-200,100)
# If in the air, we're subject to gravity.
if(!is_on_floor() && !is_underwater):
# Apply gravity here.
velocity.y += gravity * delta
# If we're on the floor & out of water & a jump is called,
if(!is_underwater && is_on_floor() && do_jump):
# Do jump and reset the flag.
velocity.y = -jump_power
do_jump = false
func human_form_movement():
print("Human coroutine started.")
var loop = true
while(loop):
# Wait for the next frame
await on_next_frame
direction.x = Input.get_axis("move_left","move_right")
if(!is_on_floor() && !is_underwater): direction.y = 1
if(is_underwater):
if(Input.is_action_pressed("descend")):
direction.y = Input.get_axis("none","descend")
else: direction.y = -1
if(Input.is_action_just_pressed("attack")):
attack_button_pressed.emit()
if(Input.is_action_just_pressed("jump")):
jump_button_pressed.emit()
if(active_form != "human"):
print("Ending human coroutine!")
loop = false