How to add loss in speed over time?

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

I am trying to implement sliding into my game, and I’ve hit a roadblock, I don’t know how to subtract from my speed variable over a certain amount of time. I want it to be where the longer I am holding the “sprint” and “crouch” keys, the more speed I lose (so like I’ll start at 20 speed, then after a second, lose 1 speed, so it is 19, then after another second its 18, etc.). I also would like it to exit the slide when I hit 0 speed. Does anyone know how to do this?

:bust_in_silhouette: Reply From: Bad-Mouth

Some users would use a Timer object to do such a thing, but me I prefer to use cycles and seconds, this is because a Timer object does not start right away and it ends after an action has occurred. I use Timers for non-critical timing tasks. Cycles however, occur every physics frame and it takes 60 cycles to equal one second.

So, I suggest you create two global variables to keep track on cycles and seconds. These global variables must be initialized to zero at startup and they must also be reset to zero when they over-flow or when your slide input keys are not being pressed.

In the (_physics_process) method you would increment (add + 1) to the cycle timer and you would check if it has overflowed (incremented up to 60 cycles). If it does, you would reset it to zero and you would increment the second counter by 1.

In your input key method you would use the second time counter to reduce the speed, if the second time counter is zero you would not lose any speed.

Once you let go of the sliding input keys, you will need to make sure to reset both the cycle and second time counters for next use!

You can call these global time counters as follows:

Cycle_Count
Second_Count

Note that you may want to use only the cycle counter since seconds may be too long. In this case you would only need the cycle counter to keep track of sliding time.


Update:

The following is code prototype which shows you what you need to do:

Step 1.

Declare global cycle and second counters.

var CycleCount : int = 0; var SecondCount : int = 0

Step 2.
func _process(_delta):
# Upon entering this method, we get input from user.
GetInput()

Step 3.
func _physics_process(delta):
# Upon entering this method, increment the cycle counter by one.
CycleCount += 1
# Check for overflow?
# NOTE:
# You can also check for
# lesser than 60 cycles,
# which reduces speed
# much quicker.
# ENDN:
if CycleCount >= 60:
# On overflow, reset cycle counter.
CycleCount = 0
# Increment second counter.
# NOTE:
# Here, you can increase the
# value to say 2 pixels which
# reduces speed by 2 pixels
# for every call to (GetInput)
# method.
# ENDN:
SecondCount += 1

Step 4.
Note that this step will be different from your code, so just add appropriate code in its place.

func GetInput():
# Upon entering this method, we check if user is pressing the sprint + crouch keys?
if Input.is_action_pressed(“sprint”) == true and Input.is_action_pressed(“crouch”) == true:
# If so, then we subtract seconds from current speed.
# NOTE:
# Speed is assume to be global.
# ENDN:
Speed = clamp(Speed - SecondCount, 0, Speed)
# Check if speed is zero?
if Speed <= 0:
# Here, you can perform an action when speed is zero,
# but is not necessary since actor will stop sliding.
# NOTE:
# Never apply a zero speed to
# the actor movement vector.
# Else, actor will be position
# out of screen view.
# ENDN:
pass

Else, reset cycle and second counters.

else:
	CycleCount = 0; SecondCount = 0

If you still cannot understand or perform the above, then I suggest you read the GDScript documentation to learn how to program. This forum is not a programming language tutorial site, for that you got Godot documentation and other web sites.
Good luck!

Thank you so much for the update! I really appreciate it!
You explained it really well, so I understood it perfectly!

NewbieGodotUser | 2022-09-13 18:29

:bust_in_silhouette: Reply From: Pomelo

I would have 2 vars max_speed and current_speed and use the current speed to do all your movement. Then while pressing a button just decrease the value of current speed by decrease_rate * delta in a _procces() function (where decrease_rate is just a number that determines how fast or slow you want the deacrease to be) (set it to 60 if you want to deacrese the value of current speed by 1 every “second”). Simple as that

Now when you want to gain the original speed back just set current_speed to max_speed, and if you want to trigger an event when reaching speed=0 , just do it

if current_speed == 0:
    do something()

and finally, remember to not let current speed take negative numbers!

When you mean “pressing a button”, do you mean like a entirely separate button for just sliding? I’d like to keep sliding as a crouch+sprint action, instead of an entirely different button.

NewbieGodotUser | 2022-09-13 18:42