Mega Man 2 Jump in Godot (Holding jump button gets higher jump, tapping is 100% same height)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By TobiasDev

So, I’ve been struggling with making a good jump function in GDScript. I used the Dynamic 2d Demo, and it works, but feels quite awful.

Does anyone have a good example of a jump that when you tap the button is a 100% the same height, and if you hold the button down, it goes higher until it reaches a set max height? Kind of like how it works in Mega Man 2.

# Variables
const VEC2GRAVITY = Vector2(0, 1400);
const VEC2FLOORNORMAL = Vector2(0, -1);
const FMININAIRTIME = 0.001;

# Gravity Function
func plGravity(d):
    #increment counters
    fInAirTime += d;

    # Apply Gravity
    if not bJumping:
        vec2LinearVelocity += d * VEC2GRAVITY;

# Jump function
func plJump():
    if Input.is_action_pressed("Jump"):
        if bOnFloor:
            bJumping = true;
    elif Input.is_action_just_released("Jump"):
        bJumping = false;
    # Process of jumping 
    if bJumping:
        vec2LinearVelocity.y -= fJumpHeight;
        if vec2LinearVelocity.y <= -fJumpMaxHeight:
            bJumping = false;
        if vec2LinearVelocity.y > 0:
            bJumping = false; # This is where we tell that the player has started to fall 

# Everything is run in this function
func _physics_process(delta):
:bust_in_silhouette: Reply From: Socrates

Never implemented this myself, but someone asked similar a few days ago: 2D Platformer: How to control jump height | Mario-like jumps - Archive - Godot Forum

:bust_in_silhouette: Reply From: rless

Hi! After struggling a little bit, I’ve found a video that helped me to create my own jump. The video is from game maker, but I applied it to godot ^^’

The main concept is:
*You have max height that you character can achieve.
*You have to check if the player is pressing the jump key, then decide if he keep with the “normal jump”
*You have to check if the player just released the jump key, then, “cut” and cancel the jump, exposing him to the gravity again

It need a little refinement, but here is my code commented:

extends KinematicBody2D

export (int) var jump_speed = -300   #speed of the jump
export (int) var gravity = 800  #gravity
var jump_pressed #variable that check if the jump key is keep pressed
var jump  #variable that check if the jump key is just pressed
var jump_cut # variable that check if jump button is just released

#direction states
var right
var left

#velocity vector
var velocity = Vector2()

func get_input():
	velocity.x = 0
	right = Input.is_action_pressed('ui_right')
	left = Input.is_action_pressed('ui_left')
jump_pressed = Input.is_action_pressed('ui_select') #jump button is keep pressed
	jump_cut = Input.is_action_just_released('ui_select')  #jump button just released
	jump = Input.is_action_just_pressed('ui_select')   #jump button is just pressed

	if jump && is_on_floor():  # check if the jump button is just pressed and if the player is on the floor
		jump() # call jump method
	if velocity.y < 0 && !jump_pressed: # here is the deal: if the jump button is not keep pressed anymore, the y velocity is set to 0 and the player don't go up anymore
		velocity.y = 0

	if right:
		velocity.x += run_speed
	if left:
		velocity.x -= run_speed
func jump():
	velocity.y = jump_speed

#func change_direction_sprite():
#	if right:
#		$Sprite.flip_h = false
#	elif left:
#		$Sprite.flip_h = true

func _physics_process(delta):
	velocity.y += gravity * delta # gravity 
	velocity = move_and_slide(velocity, Vector2(0, -1))

I hope it helps! My jump works just fine :smiley:

:bust_in_silhouette: Reply From: BlumiDev

So I made this mario-like jump, but I can see it will work with your idea. I know it’s old post but other people may find it useful. Just change variables in code to see what works for you. If you want to set jump to 100% value just edit var jumpVelocity and fiddle around with lowJumpMultiplier.

extends KinematicBody2D

export var fallMultiplier = 2 
export var lowJumpMultiplier = 10 
export var jumpVelocity = 400 #Jump height

var velocity = Vector2()
export var gravity = 8

func _physics_process(delta):

	#Applying gravity to player
	velocity.y += gravity 
	#Jump Physics
	if velocity.y > 0: #Player is falling
		velocity += Vector2.UP * (-9.81) * (fallMultiplier) #Falling action is faster than jumping action | Like in mario

	elif velocity.y < 0 && Input.is_action_just_released("ui_accept"): #Player is jumping 
		velocity += Vector2.UP * (-9.81) * (lowJumpMultiplier) #Jump Height depends on how long you will hold key

	if is_on_floor():
		if Input.is_action_just_pressed("ui_accept"): 
			velocity = Vector2.UP * jumpVelocity #Normal Jump action
	velocity = move_and_slide(velocity, Vector2(0,-1))	

I’m also adding download for the project so u can see how it works in my case of use. better Jump.rar - Google Drive

BlumiDev | 2019-06-07 14:44

Say, thanks for contributing. This may come in handy one of these days.

Ertain | 2019-06-07 20:31

:bust_in_silhouette: Reply From: ff7rule

Hello. Godot newbie here.

Not exactly like what you asked (you wanted a maximum height). But I added these lines and it seems to work fine as far as holding it to give it more power is concerned

var hold_jump_power = 3

and then inside _physics_process(delta), add:

if Input.is_action_pressed("Jump") and velocity.y < 0 :
	velocity.y -= hold_jump_power

That just says if you’re holding the jump button and you’re going up, it adds a little more acceleration going up. You’ll have to tweak it a little so that you can’t let the button go and hold it again. You need the “and velocity.y < 0” to prevent slowing your fall. But if you ever need some sort of glide mechanic when you fall, that’s an idea.

Adjust hold_jump_power to your liking, but if it’s too high compared to gravity, you’ll go up forever and ever with the button held down.

This is actually a very good answer, and since it is the simplest, I personally feel it should be the top answer. It also gives a nice slow-fall effect that I quite like that the other solutions do not.

Kyllingene | 2021-05-11 01:19

:bust_in_silhouette: Reply From: k3nzngtn

For me this comes pretty close to the jump in Mega Man 9:

export (int) var jump_speed = -400
export (int) var gravity = 1200

var jumping = false

func _physics_process(delta):
    if Input.is_action_just_pressed('jump') and is_on_floor():
        jumping = true
        velocity.y = jump_speed

    if jumping and Input.is_action_just_released("jump"):
        if velocity.y < -50:
        velocity.y = -50

    velocity.y += gravity * delta

    velocity = move_and_slide(velocity, Vector2.UP)

    if jumping and is_on_floor():
        jumping = false

Thanks for this answer! I was just looking at this again, and this one feels really nice!

TobiasDev | 2020-07-31 09:06