+1 vote

Hi!
I made this super simple Stamina function, and i cant make godot to stop adding numbers when its colliding. (i made a player that can run and walk, when it runs into wall it still consumes stamina)
Here is the code...

var stamina = 200
var speed = 100

if (motion.x or motion.y) and Input.is_action_pressed("ui_accept") == true and stamina > 20:
        speed = 300
        stamina -= 1
    else:
        speed = 100
        stamina += 1*0.3
        if stamina > 200:
            stamina = 200

I tried making stamina = false, stamina == false, stamina = stamina..
But nothing pauses adding ..
How can i stop it?
P.S. Kinematicbody2d

in Engine by (225 points)
edited by

How about doing this:

  const max_stamina = 100 // or whatever
  if stamina < max_stamina:
       stamina += 1 // or whatever

Try to use the "code" format for code because is hard to tell what says without proper identation

Not sure what that "motion" means, is a Vector2 or something else?

Also I don't see a collision check there, and the way to do it will depends on how are you moving the body (with pos, with move).

Im not rly sure what " const" is, i read about it but its not rly clear for me.. but, this code you wrote seems like it will be handy too : D

@rustyStriker : what do you mean by "use the "code" format" ?
My code over all looks like this

func fixedprocess(delta):
var motion = Vector2()
var up = Input.isactionpressed("uiup")
var down = Input.is
actionpressed("uidown")
var left = Input.isactionpressed("uileft")
var right = Input.is
actionpressed("uiright")

if up:
    motion += Vector2(0,-1)
if down:
    motion += Vector2(0,1)
if left:
    motion += Vector2(-1,0)
if right:
    motion += Vector2(1,0)

if (motion.x or motion.y) and Input.is_action_pressed("ui_accept") == true and stamina > 20: 
    speed = 300
    stamina -= 1
else:
    speed = 100
    stamina += 1*0.3
    if stamina > 200:
        stamina = 200

print(stamina)
motion = motion.normalized()*speed*delta
motion = move(motion)

var sliding = 4
while(is_colliding() and sliding > 0):
    motion = get_collision_normal().slide(motion)
    motion = move(motion)
    sliding -= 1

4 Answers

0 votes
Best answer

Not ideal code here, but just a quick and dirty example of what you can do, the relevant part is:

    if(is_colliding() and get_collider().is_type("StaticBody2D")):
        hitting_wall = true

Super simplified version of handling things with flags.

extends KinematicBody2D

const MAX_STAMINA = 100
const STAMINA_LOSS_PER_SECOND = 40
const STAMINA_RECOVERY_PER_SECOND = 60
const RECOVERY_BOOST = 20
const DOWN_TIME_IN_SECONDS = 2
const SPEED = 10

var stamina = 100
var drain_stamina
var hitting_wall
var exhaustion_timer = 0

func _ready():
    set_fixed_process(true)

func _fixed_process(delta):

    drain_stamina = false
    hitting_wall = false

    if(not stamina == 0):
        if  (Input.is_key_pressed(KEY_UP)):   
            move(Vector2(0,-SPEED))
            drain_stamina = true
        elif(Input.is_key_pressed(KEY_DOWN)): 
            move(Vector2(0, SPEED))
            drain_stamina = true

        if  (Input.is_key_pressed(KEY_LEFT)):  
            move(Vector2(-SPEED, 0))
            drain_stamina = true
        elif(Input.is_key_pressed(KEY_RIGHT)): 
            move(Vector2( SPEED, 0))
            drain_stamina = true

        if(is_colliding() and get_collider().is_type("StaticBody2D")):
            hitting_wall = true

    if(exhaustion_timer > 0):
        exhaustion_timer -= delta
    else:
        if(drain_stamina and not hitting_wall):
            stamina -= STAMINA_LOSS_PER_SECOND * delta
        else:
            if(stamina == 0): stamina += RECOVERY_BOOST
            else: stamina += STAMINA_RECOVERY_PER_SECOND * delta

        stamina = clamp(stamina, 0, MAX_STAMINA)

        if(stamina == 0):
            exhaustion_timer = DOWN_TIME_IN_SECONDS
by (5,240 points)
selected by

This worked pretty fine!
But i get this problem that it also says its colliding with "kinematic2d" when its touching tileset... which had no body at all, just sprite with collision

I haven't worked with Godot's tilesets, so it might be another question you would want to post.

Just from what I've read at a glance, it appears you would create tiles and assign the collision bodies to them. Then as they get painted along, they take on the instances of the collision you've given them.

The guide on the site recommended adding StaticBody. It's usually a general practice to use static bodies for walls that won't be interactive. I can't really say why it's reporting as Kinematic, but you could probe the collisions and the objects themselves using print()s. So you can always assign your own data to test against too, if there needs to be special cases.

This is all that I've seen so far regarding tilesets: http://docs.godotengine.org/en/stable/tutorials/2d/using_tilemaps.html

I don't know what you've already read or if it's useful.

0 votes

Your code here is not very well formated so maybe I'm not understanding it very well, but maybe you should use the function KinematicBody2D.is_colliding() better than the if condition you are using.

by (110 points)
edited by

im not really sure what you mean..?

You are using a KinematicBody2D, right? This objects have a method called "is_colliding()", that you can use to detect if your object is colliding. I'm not sure if this could help because I don't understand well the code you posted, but you can try.

I can add code when its colliding but what i cant do is make it stop adding numbers when its colliding..

0 votes

What you can do is, after move, work with stamina decrease if not colliding and active:

var stamina_mode = (motion.x or motion.y) && 
                   Input.is_action_pressed("ui_accept") && 
                   stamina > 20

#...

#after move, and maybe before while
if !is_colliding() && stamina_mode: 
 do_stamina_related_stuff
else:
 do_stamina_recovery

ps: the code thing is what you did with the part of the code that is formatted in the answer (one of the buttons on the top are for set the "code" style of text does that).

by (7,894 points)
0 votes

If I understand what you're trying to do, you don't necessarily want stop stamina drain when you're colliding with a wall, but when you're not moving (that is, when you're running in place because a wall is in the way).
So, it should be best to check for movement rather than collision. Specifically, you can check your motion var's X axis for absolute values above delta (bumping into a wall will still produce a tiny amount of movement, so we want a threshold).

(also, you probably want to pair this with whatever you're using for floor detection if applicable. Moving left/right through the air probably shouldn't drain stamina either!)

var max_stamina = 200
var stamina = 200 setget _set_stamina

var stamina_burn_rate = 15      #burn 15/sec when running
var stamina_recovery_rate = 5   #recover 5/sec

func _set_stamina(value):
    stamina = clamp(value,0,max_stamina)    #keep from under/overflowing


func _fixed_process(delta):
    var motion = (motion vector got from input and stuff)

    motion = move(motion)   # any 'leftover' motion will be returned

    var Mx = abs(motion.x)
    var new_stamina = stamina
    if Mx > delta:
        new_stamina = stamina - (stamina_burn_rate*delta)
    elif Mx == 0:
        new_stamina = stamina + (stamina_recovery_rate*delta)

    if new_stamina != stamina:
        set('stamina', new_stamina)
by (1,328 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 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 webmaster@godotengine.org with your username.