How to prevent player from endlessly performing a slide manuever?

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

I have a slide maneuver setup that allows the player to quickly move in the direction they’re walking in. It also lowers their hitbox, but I haven’t implemented that yet. Here’s how all the movement looks in my player.gd:

const GRAVITY = 1300.0 # pixels/second/second

# Angle in degrees towards either side that the player can consider "floor"
const FLOOR_ANGLE_TOLERANCE = 50
const WALK_FORCE = 1600
const WALK_MIN_SPEED = 10
const WALK_MAX_SPEED = 400
const STOP_FORCE = 1500
const JUMP_SPEED = 600
const JUMP_MAX_AIRBORNE_TIME = 0.4
const SLIDE_SPEED = 600
const MAX_SLIDE_TIME = 0.4

var velocity = Vector2()
var rot_dir
var can_shoot = true
var health
var on_air_time = 100
var jumping = false
var can_slide = true

onready var oldScale = get_node("Sprite").get_scale()
onready var oldPosition = get_node("Sprite").get_position()

var prev_jump_pressed = false

    
func _ready():
    health = start_health
    emit_signal("health_changed", health)
  
func _physics_process(delta):
    # Create forces
    var force = Vector2(0, GRAVITY)
    
    var move_left = Input.is_action_pressed("move_left")
    var move_right = Input.is_action_pressed("move_right")
    var jump = Input.is_action_pressed("jump")
    var slide = Input.is_action_pressed("slide")
    
    var stop = true
    
    if move_left:
        if velocity.x <= WALK_MIN_SPEED and velocity.x > -WALK_MAX_SPEED:
            force.x -= WALK_FORCE
            stop = false
    elif move_right:
        if velocity.x >= -WALK_MIN_SPEED and velocity.x < WALK_MAX_SPEED:
            force.x += WALK_FORCE
            stop = false
            
    # slide right
    if slide and move_right and can_slide:
        can_slide = false
        velocity.x = +SLIDE_SPEED
        
    # slide left
    elif slide and move_left and can_slide:
        can_slide = false
        velocity.x = -SLIDE_SPEED

    if stop:
        var vsign = sign(velocity.x)
        var vlen = abs(velocity.x)
        
        vlen -= STOP_FORCE * delta
        if vlen < 0:
            vlen = 0
        
        velocity.x = vlen * vsign
    
    # Integrate forces to velocity
    velocity += force * delta    
    # Integrate velocity into motion and move
    velocity = move_and_slide(velocity, Vector2(0, -1))

My current issue is, if the player holds down the slide key, they can keep sliding forever, which currently looks like they’re just walking at an accelerated pace. I want them to only be able to slide for about 0.4 seconds, and then they have to wait a second or two before they can slide again. How do I do this?

:bust_in_silhouette: Reply From: kamel

Hello,
you need to add a tween callback or a timer to set the variable can_slide back to true after the required time passes. Here is an example using a timer:
1- add a Timer node to your scene and configure the settings as you want.
2 - connect to the signal like this

timer.connect("timeout",self,"start_count_down")

3 - add he start_count_down function to your code

func start_count_down():
   can_slide = true
  
:bust_in_silhouette: Reply From: Luck_437

You could keep counting how many times have been elapsed thanks to delta (which is the time between each pass). It seems you already use a state like can_slide which is good.
I will probably mix-match it to count the time :

var slide_elapsed = 0
const slide_time = 1.0
func _physics_process(delta):
	if slide : 	
		if elapsed_slide < slide_time :
		elapsed_slide += delta
	else :
		elapsed_slide = 0
		slide = false

This is just for restricting the slide time, validity is checked like that:

# slide is over
if slide_elapsed == 0: ...

# or counting the slide time
if slide_elapsed != 0: ...

You could count also before slide is allowed. Also using a slide object will make things probably easier to handle.

var slide = {}
func _ready():
	slide.elapsed = 0 # how many time we could slide
	slide.allowed = 0 # how many time before allowed to slide
	slide.state = false # slide validity test

You will need to think about deeper than what I’ve done, but the idea is here, hope it helps.

So I think I somewhat understand. I have this:

var on_slide_time = 0 # elapsed slide time
const MAX_SLIDE_TIME = 1

if slide and move_right:
        if on_slide_time < MAX_SLIDE_TIME:
            on_slide_time += delta
            velocity.x = +SLIDE_SPEED
        else:
            on_slide_time = 0

But it doesn’t work, because it immediately calls the else statement as soon as on_slide_time goes above 1, and just resets it back to 0, so you can still slide.

PopeRigby | 2020-04-15 19:01

Disregard this comment. I thought I figure it out but I didn’t.

PopeRigby | 2020-04-15 21:30

I understand the problem, I just need to rethink of it a little more to really make things working. The timer as suggested isn’t a bad idea.

I will try to make a simple demo-project to help you.

One thing sure, mix-matching the counter and the state wasn’t a good idea at the beginning.

I’m my game, I would probably do it with finite state machine, meaning a state for sliding, or running or jumping (one state at a time): but this is a lot of works for a beginer.

Here are some example I’ve made, from simple to more complex experementing different ideas. It doesn’t solve the cheating problem where the player could spam sliding one after another. Try to run and cook around thoses (I will comfort you to duplicate before any modifications): Archive PDF: Archivez et partagez facilement vos documents.

Luck_437 | 2020-04-17 20:29