This site is currently in read-only mode during migration to a new platform.
You cannot post questions, answers or comments, as they would be lost during the migration otherwise.
0 votes

Hi,

I'm having difficulty changing the typical game mechanic I've seen in the majority of tutorials for platform game character movement with KinematicBody2D in Godot.

I'm trying to create a movement typical of 80's platform games, such as Super Mario. Where the player jumps and cannot reverse the direction of movement. Flip the sprite, yes, but not go against physics!

The desired outcome is to force the player to only jump in the direction they chose, so they are committed to it.

It's absolutely baffling how to implement it. I've attempted functions to split the controls up, but it just became too complicated as it then affected the jumping too. Plus I was creating the same code twice, which looked amateurish at best - it still didn't work though ;)

Anyway, here's my basic code before I attempted to alter it:

extends KinematicBody2D

var bear_velocity = Vector2()
var on_ground = false

const SPEED = 60
const GRAVITY = 10
const FLOOR = Vector2(0,-1)
const JUMP_POWER = -242


func _physics_process(delta):


    # Walking Left, Right or Idle
    if Input.is_action_pressed("ui_right"):
        $Sprite.flip_h = false      
        bear_velocity.x = SPEED
        $Sprite.play("Walk")    

    elif Input.is_action_pressed("ui_left"):
        $Sprite.flip_h = true       
        $Sprite.play("Walk")        
        bear_velocity.x = -SPEED
    else:
        bear_velocity.x = 0
        if on_ground == true:
            $Sprite.play("Idle")


    # Jumping
    if is_on_floor():
        on_ground = true        
    else:
        on_ground = false
        if bear_velocity.y < 0:
            $Sprite.play("Jump")                
        else:
            $Sprite.play("Fall")


    if Input.is_action_pressed("ui_select"):
        if on_ground == true:
            bear_velocity.y = JUMP_POWER
            on_ground = false


    # Variable Height Jump      
    if Input.is_action_just_released("ui_up") && bear_velocity.y < -50:
        bear_velocity.y = -50


    # Add Gravity
    bear_velocity.y += GRAVITY

    # Add Movement from Vector2 
    bear_velocity = move_and_slide(bear_velocity, FLOOR)
in Engine by (86 points)

2 Answers

+1 vote

A way to make the player unable to change direction when not on the ground is to prevent direction change when the player is not on the grund (as you see, the question gives an answer).

if Input.is_action_pressed("ui_right") && on_ground:

For this, you will have to do the is_on_floor() check before the input handling to get the correct grounded status.

by (7,954 points)

Thanks, but this causes a small issue. The character can no longer move left or right when jumping.

Someone else suggested I place the control inside the if on_floor, e.g.:

if is_on_floor():
    if Input.is_action_pressed("ui_right"): # move right if you press right-key
        bear_velocity.x = SPEED
    elif Input.is_action_pressed("ui_left"): # move left if you press left-key
        bear_velocity.x = -SPEED
    else: # don't move if you are grounded and neither left nor right key is pressed
        bear_velocity.x = 0

But that isn't right either, again the player has no control over the amount of distance traveled left or right. The player is locked to one big jump left, or one big jump right.

Here's a link to Super Mario for reference (forget the inertia, I have to tackle that next):

https://oldgameshelf.com/super-mario-bros-1217.html

If you want SMB style then the ting is different, you need to apply inertia to add speed ( stop adding on release), and SMB probably applies similar drag to floor and air.

0 votes

SUPER LATE but. Hello, im also a new to godot and just happened to find a way to implement this. So basically you remove the numbers on the speed var and add a normSpeed and jumping_moveSpeed, then change the speed based on if the bear is on the air or not. something like this

var speed
var normSpeed = #your desired normal speed
var jumping_moveSpeed = #you can make it zero so they can flip but not move or just change it to a small value

func _physics_process(delta):

    if   !on_ground:
        speed = jumping_moveSpeed
    elif  on_ground:
        speed = moveSpeed

    # Walking Left, Right or Idle
    if Input.is_action_pressed("ui_right"):
        $Sprite.flip_h = false      
        bear_velocity.x = speed
        $Sprite.play("Walk")    

    elif Input.is_action_pressed("ui_left"):
        $Sprite.flip_h = true       
        $Sprite.play("Walk")        
        bear_velocity.x = -speed
    else:
        bear_velocity.x = 0
        if on_ground == true:
            $Sprite.play("Idle")

if Input.is_action_pressed("ui_select"):
    if on_ground == true:
        bear_velocity.y = JUMP_POWER
        on_ground = false
by (24 points)
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 Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.