0 votes

I'm designing an oldschool Spectrum-like platformer where I need several jump tweaks I can't quite figure out.
SpeccyPlatformer

Two problems with the player code below:
1. The player jumps only with

if Input.is_action_pressed("player_jump"):

Problem with the jump sound is that it retriggers every frame, whereas I need it only to play once. Which happens if I set it to

if Input.is_action_just_pressed("player_jump"):

- but then the player will jump only very low. How can I fix this? Should I use justpressed?

2. I need to set the maximum jump height after which the velocity.y will lerp to gravity pull. There will be tiles in the game that let the player jump higher (temporarily. How should I do that better?

Here's the code:

extends KinematicBody2D

var airborne
var movingright
var velocity = Vector2()
var walkspeed = 400
var gravityscale = 600
var jumpvelocity = 1300

func _ready():
    movingright = true

func teleport_to(target_pos):
    position = target_pos

func get_input():
    if Input.is_action_pressed("ui_right"):
        movingright = true
        airborne = false
        $SnoozyAnim.play("walk")
        velocity.x = walkspeed 
    elif Input.is_action_pressed("ui_left"):
        movingright = false
        airborne = false
        $SnoozyAnim.play("walk")
        velocity.x = - walkspeed
    else: 
        $SnoozyAnim.play("idle") 
        airborne = false
        velocity.x = lerp(velocity.x, 0, 0.2)

    if not movingright: 
        $SnoozyAnim.set_flip_h(false)
    else:
        $SnoozyAnim.set_flip_h(true)

    if Input.is_action_pressed("player_jump"):
        velocity.y -= jumpvelocity
        airborne = true
        $SnoozyAnim.play("jump")
        $JumpSound.play()


func _physics_process(delta):
    velocity.y = gravityscale
    get_input()
    move_and_slide(velocity)
asked Jan 10 in Engine by verbaloid (47 points)
edited Jan 10 by verbaloid

I think its better to do one thing until you are confortable with the result and then start the next stuff. Try to do the character movement works well, then add the animations, e after that the sound. It becomes easier when you break all the game in small goals.

1 Answer

0 votes

You need to declare where is the floor and what is the gravity. By doing it you can tell if the kinematic body is on ground or not. If it isnt you cant keep adding the velocity.y. And the gravity will start slowing the velocity.y force until it becomes positive and the body is atracted to the floor again.

extends KinematicBody2D

const FLOOR = Vector2(0, -1) #first you need to declare where the floor is in order to check if you are already jumping. the floor in 2d is Vector2(0, -1) 
const GRAVITY = 10 #then you set a constant for gravity that you will add to your velocity.y, it will pull you KinematicBody2D back to the ground

var airborne
var movingright
var velocity = Vector2()
var walkspeed = 400
var gravityscale = 600
var jumpvelocity = 1300

func _ready():
    movingright = true

func teleport_to(target_pos):
    position = target_pos

func get_input():
    if Input.is_action_pressed("ui_right"):
        movingright = true
        airborne = false
        $SnoozyAnim.play("walk")
        velocity.x = walkspeed 
    elif Input.is_action_pressed("ui_left"):
        movingright = false
        airborne = false
        $SnoozyAnim.play("walk")
        velocity.x = - walkspeed
    else: 
        $SnoozyAnim.play("idle") 
        airborne = false
        velocity.x = lerp(velocity.x, 0, 0.2)

    if not movingright: 
        $SnoozyAnim.set_flip_h(false)
    else:
        $SnoozyAnim.set_flip_h(true)

    #if Input.is_action_pressed("player_jump"):
    if Input.is_action_pressed("player_jump") && on_ground: #only jumps if you are on the floor
        velocity.y -= jumpvelocity
        on_ground = false #set that you arent on ground 
        airborne = true
        $SnoozyAnim.play("jump")
        $JumpSound.play()


func _physics_process(delta):

#func _physics._process(delta):
    velocity.y += GRAVITY #here is where your gravity force pulls the kinematic body to the ground
    get_input()
    #move_and_slide(velocity)
    velocity = move_and_slide(velocity, FLOOR)

    if is_on_floor():   #here you are telling if you are on ground or jumping
        on_ground = true 
    else: 
        on_ground = false
answered Jan 10 by JVStorck (16 points)

Thank you! It works, but the only parameter now it seems to react to is jumpvelocity, regardless of what I set gravityscale to. What I need is while he is airborne, I need it to fall faster, so that he doesn't hang in the air so long. I try different gravityscale but no difference. What am I missing?

Thank you again for your help!

Sorry, I missed that we now have GRAVITY const. Yes, it works.

One last question on that: later I want special tiles that serve as spring boards, to allow player jump higher. Do those tiles have to adjust jump height temporarily like a time loop?

I guess, I will have to make other nodes change Player's on_ground variable. Does that mean I have to export this variable in Player script?

you can make a different ground tile with a second collision shape above the ground so you can do something like that:

func _on_SpringBoard_body_entered(body): #when you enter the collision of the tile...
    get_node("../Player").jumpvelocity += 500 #it will add 500 to the jump velocity in the Player script

func _on_SpringBoard_body_exited(body):  #when you exit it...
    get_node("../Player").jumpvelocity = 1300 #it will set the jump velocity back to the original value

this code will be inside the spring board script. you need to connect the spring board with itself in order to work.

Thanks!

The script now works, but for one animation.

The 'jump' animation is overrided all the time by 'walk', it never plays.

I try and try to make it work, I don't understand how to sort that override?

the problem in there is your right and left input code. You can solve this by only playing the walk animation when the player is on ground, like that:

if Input.is_action_pressed("ui_right"):
    movingright = true
    airborne = false
    velocity.x = walkspeed
    if on_ground:
         $SnoozyAnim.play("walk")

elif Input.is_action_pressed("ui_left"):
    movingright = false
    airborne = false
    velocity.x = - walkspeed
    if on_ground:
        $SnoozyAnim.play("walk")

else:
    airborne = false
    velocity.x = lerp(velocity.x, 0, 0.2)
    if on_ground:
        $SnoozyAnim.play("idle")
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.