0 votes

Hi,
I know the question has been asked about a year ago but I don't really want to reopen an old thread. Things may have changed with Godot 3.1 and to be honest I don't understand how to implement the answer.

I am doing a 2D game and I try to add a slide function to my player.
I want my slide function to
- stop responding to Input
- move following game physics to X position
- resume the input control.

So far I can only teleport to a specific location or move while in sliding position.

This is my code:

extends KinematicBody2D

const KUNAI = preload("res://scenes/Kunai.tscn")

var direction = 1

var camera_top = 0
var camera_left = 0
var camera_right = 4416
var camera_bottom = 1664 
var camera_position = 25


var is_attacking = false
var is_running = false
var is_sliding = false

export var snap = false
export var move_speed = 350
export var jump_force = 550
export var gravity = 900 
export var slop_slide_threshold = 60
var velocity = Vector2()
var destination = Vector2()

func _ready():
    connect("finished", self, "on_finished")
    $camera2D.limit_top    = camera_top
    $camera2D.limit_left   = camera_left
    $camera2D.limit_right  = camera_right
    $camera2D.limit_bottom = camera_bottom  
    set_process(true)
    pass

func  _physics_process(delta):

    ## Move ##
    var direction_x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
    velocity.x = direction_x * move_speed
    print("velocity.x: "+str(velocity.x))
    print("direction_x: "+str(direction_x))

    ## Running ##
    if Input.is_action_pressed("ui_focus_prev") && velocity.x !=0:
        is_running = true
        if snap == true && is_sliding == false:
            move_speed = 700
        $sprite.frames.set_animation_speed("Run", 25)
        camera_position = 35
    else:
        is_running = false
        if snap == true && is_sliding == false:
            move_speed = 350
        $sprite.frames.set_animation_speed("Run", 15)
        camera_position = 20

    ## Slide ##
    if is_running and Input.is_action_just_pressed("ui_down"):
        is_sliding = true
        move_speed = 1000
        $collisionshape2D.rotation_degrees = 90
    if Input.is_action_just_released("ui_down"):
        is_sliding = false
        if $collisionshape2D.rotation_degrees == 90:
            position.y = position.y-($collisionshape2D.get_shape().height/2)
            $collisionshape2D.rotation_degrees = 0

    ## Jump ##
    if Input.is_action_just_pressed("ui_select") and snap :
        velocity.y = -jump_force
        snap = false
        # insert jump sound

    ## Set Gravity ##   
    velocity.y += gravity * delta

    ## apply movement ##
    var snap_vector = Vector2(0, 32) if snap else Vector2()
    velocity = move_and_slide_with_snap(velocity, snap_vector, Vector2.UP, slop_slide_threshold)    

    ## prevent jumping ##
    if is_on_floor() and not is_sliding and (Input.is_action_just_released("ui_right") or Input.is_action_just_released("ui_left")):
        velocity.y = 0

    ## enable snap when landing ##
    var just_landed = is_on_floor() and not snap
    if just_landed:
        snap = true

    update_animation(velocity)

func update_animation(velocity: Vector2):
    var animation = "Idle"

    if abs(velocity.x) > 10.0:
        $sprite.flip_h = velocity.x < 0
        if is_sliding:
            animation = "Slide"
        else:
            animation = "Run"

    if not is_on_floor():
        animation = "Jump" if velocity.y < 0 else "Fall"

    if $sprite.animation != animation:
        $sprite.play(animation)

Thank you

asked Jul 24, 2019 in Engine by TheLastCayen (24 points)
edited Jul 24, 2019 by TheLastCayen

I was searching for a workaround and I found out the hard way, the variable in a while loop will not update inside a physicsprocess(delta).

In the same process of tough, I was trying to implement a wall jump using this:

## Wall Jump ##
if Input.is_action_just_pressed("ui_select") &&  is_on_wall() :
    velocity.y = -jump_force
    velocity.x =  run_speed * -1 
    snap = false
    while velocity.y < 0: 
        print(str(velocity.y))
        velocity.x =  10 * direction
        velocity = move_and_slide(velocity, Vector2.UP)
        update_animation(velocity)

That code doesn't even print my velocity.y once. How can I temporarily ignore the input and perform a fluid movement inside a physicsprocess ?

1 Answer

0 votes
Best answer

I don't know if it's the best practice, but I found a way and it may help some.
I am using a variable to skip the input while I perform my scripted action.
This is a part of my code:

var is_scripted_movement = false

func  _physics_process(delta):

    update_component()

    ## quit game even during scripted animation ##
    if Input.is_action_pressed("ui_cancel"):
        get_tree().quit()
    if is_scripted_movement:

        ## scripted wall jump ##
        if not snap && (is_on_wall() or velocity.y >= -gravity/5.5):
            is_scripted_movement = false

    ## scripted slide ##
    if is_sliding:
        if is_on_wall():
            direction = -sign(direction)
            update_component()
            velocity.x = run_speed * direction
            print("after: " + str(direction))
        if not is_on_floor():
            $collisionshape2D.rotation_degrees = 0
            is_scripted_movement = false
        if not $rc_left_up.is_colliding() && not $rc_right_up.is_colliding():
            if (direction == 1 && position.x >= scripted_position_end.x) or (direction == -1 && position.x <= scripted_position_end.x):
                is_sliding = false
                if is_on_floor():
                    position.y = position.y-($collisionshape2D.get_shape().extents.y)
                $collisionshape2D.rotation_degrees = 0
                is_scripted_movement = false

    ## input movement ##
    else:

        ### insert character input here ####

        ## Slide ##
        if is_on_floor() && (is_running && Input.is_action_just_pressed("ui_down")) or (Input.is_action_just_pressed("ui_select") && Input.is_action_pressed("ui_down")):
            velocity.x =  run_speed * direction
            is_sliding = true
            $collisionshape2D.rotation_degrees = 90
            position.y = position.y+($collisionshape2D.get_shape().extents.y/2)
            scripted_position_end.x = position.x + ((64*5)*direction)
            is_scripted_movement = true

        ## Wall Jump ##
        if Input.is_action_just_pressed("ui_select") &&  is_on_wall() && not is_on_floor() :
            direction = -sign(direction)
            update_component()
            velocity.y = -jump_force
            velocity.x =  run_speed * direction
            snap = false
            jump_release = false
            is_scripted_movement = true
        if Input.is_action_just_released("ui_select"): 
            jump_release = true

    ## Set Gravity ##   
    velocity.y += gravity * delta

    ## apply movement ##
    var snap_vector = Vector2(0, 32) if snap else Vector2()
    velocity = move_and_slide_with_snap(velocity, snap_vector, Vector2.UP, slop_slide_threshold)    
answered Jul 27, 2019 by TheLastCayen (24 points)
edited Jul 27, 2019 by TheLastCayen
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.