Within the game I’m making, it is possible for the player to transform between two forms.
One of the forms is larger, and can jump higher, the other is smaller and falls slower.
I have made a system that allows the player to jump a ittle higher if they keep holding the jump button, but it results in a few bugs.
It is, for example, possible for the player to make a higher jump if they transform into the smaller form while in a jump that started in the larger form, and then barely reach the next row of the tileset, which they shouldn’t.
Instead, they should only be able to jump as high as the player can when they are in the larger form.
How do I fix this?
my scene tree looks like this, and has the following scripts:
On Player:
extends Node2D
# Make variables to store the current form
var current_form
var other_form
# Called when the node enters the scene tree for the first time.
func _ready():
# set the forms correctly
current_form = $Form1
other_form = $Form2
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# Transform the player when they press the transform button
if Input.is_action_just_pressed("transform"):
_switch_form()
func _switch_form():
# Disable current form
other_form.get_node("collision").disabled = false
other_form.get_node("sprites").visible = true
# Get the position of the next form the player
other_form.position = current_form.position
# Limit the vertical velocity of the player when they switch to a form with less max velocity
if (current_form.velocity.y < other_form.JUMP_VELOCITY):
other_form.velocity = Vector2(current_form.velocity.x, other_form.JUMP_VELOCITY)
else:
other_form.velocity = current_form.velocity
# Set the amount of jumpframes to the same amount as the current form
other_form.jump_frames = 0
# Eneble the new form
current_form.get_node("collision").disabled = true
current_form.get_node("sprites").visible = false
# Swap the forms in memory soswitching between them goes correctly
var store_form = current_form
current_form = other_form
other_form = store_form
On Form1:
extends CharacterBody2D
const SPEED = 600.0
const JUMP_VELOCITY = -1150.0
const COYOTE_TIME = 0.05
const GRAVITY = 6000
const MAX_GRAVITY = 2200
var jump_frames = 16
var coyote_timer = 0.0
# Delta is the amount of seconds a frame is on screen ( 0.01666~ )
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
if (velocity.y < MAX_GRAVITY):
velocity.y += GRAVITY * delta
# Jumping from ground level with coyote time implemented
if Input.is_action_just_pressed("jump") and ( is_on_floor() or coyote_timer > 0 ):
jump_frames = 16
velocity.y = JUMP_VELOCITY
# Keep going higher if you hold the jump button
elif Input.is_action_pressed("jump") and jump_frames > 0:
jump_frames = jump_frames - 1
velocity.y = JUMP_VELOCITY
# Stop the abbility to go higher if you release the jump button or toutch the ceilling
if Input.is_action_just_released("jump") or is_on_ceiling():
jump_frames = 0
# Handle coyote time increments
if is_on_floor():
coyote_timer = COYOTE_TIME
elif coyote_timer > 0:
coyote_timer -= delta
# Get the input direction and handle the movement/deceleration.
var direction = Input.get_axis("left", "right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
On Form2:
extends CharacterBody2D
const SPEED = 600.0
const JUMP_VELOCITY = -900.0
const COYOTE_TIME = 0.05
const GRAVITY = 4000
const MAX_GRAVITY = 2200
var jump_frames = 16
var coyote_timer = 0.0
# Delta is the amount of seconds a frame is on screen ( 0.01666~ )
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
if (velocity.y < MAX_GRAVITY):
velocity.y += GRAVITY * delta
# Jumping from ground level with coyote time implemented
if Input.is_action_just_pressed("jump") and ( is_on_floor() or coyote_timer > 0 ):
jump_frames = 16
velocity.y = JUMP_VELOCITY
# Keep going higher if you hold the jump button
elif Input.is_action_pressed("jump") and jump_frames > 0:
jump_frames = jump_frames - 1
velocity.y = JUMP_VELOCITY
# Stop the abbility to go higher if you release the jump button
elif Input.is_action_just_released("jump"):
jump_frames = 0
# Stop ascending when toutching a ceilling
if is_on_ceiling():
jump_frames = 0
# Handle coyote time increments
if is_on_floor():
coyote_timer = COYOTE_TIME
elif coyote_timer > 0:
coyote_timer -= delta
# Get the input direction and handle the movement/deceleration.
var direction = Input.get_axis("left", "right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
As visible, Form1 and Form2 share a lot of code, however due to them having different collisions, sprites, property differences and in the future differing abilities, I decided to put them in different scripts.
I presume that the lower gravity on form2 causes the player to jump ever so slightly higher when transforming at the peak of Form1’s velocity.
How do I fix it so that the player keeps ascending when they still have upwards momentum, yet not ascend above the limit they can reach as Form1, and still fall with the gravity of form2?
(The sprites have been set with an offset making both of their origins their bottom center, the collision is then wrapped around that base. The issue also might lie here.)