+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..
How can i stop it?
P.S. Kinematicbody2d

in Engine
edited

``````  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
``````

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

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

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..

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)

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)