Home > Back-end >  Why is my elif statement always executing in Godot?
Why is my elif statement always executing in Godot?

Time:09-27

I'm new to Godot programming, just to preface this. I'm trying to make it so that when you fall off of a platform without jumping you start accelerating downwards rather than just going down at a fixed speed. I almost have that, but my elif statement is happening every frame rather than the frame you leave the ground.

I've tried changing things, but I'm stuck at a logical dead end where any option I think of or find has resulted in the same or worse behavior.

extends KinematicBody2D

const UP_DIRECTION = Vector2.UP #up is up and down is down

# Declare member variables here.
var speed = 200 #speed of walk
var velocity = Vector2() #movement Vectors
var gravity = 1000 #gravity, it's real
var jump = 0 #jumping speed
var canjump = 0 #jumps left
var jumpcount = 1 #times you can jump
var nojump = false #did you fall or did you jump?
# Called every physics update.
func _physics_process(delta):
    #jumping
    if (canjump > 0 && Input.is_action_just_pressed("Jump") || is_on_floor() && canjump > 0 && Input.is_action_pressed("Jump")):
        jump = -2000
        canjump -= 1
        nojump = false
    #falling without jumping first
    elif not (is_on_floor() && Input.is_action_just_pressed("Jump") && nojump == false):
        jump = -gravity
        canjump -= 1
        nojump = false
    #decelerating jumps
    if (jump < 0):
        jump  = 45
    #grounding jump variables
    if(is_on_floor()):
        canjump = jumpcount
        nojump = true
    #setting x and y
    velocity.x = (Input.get_action_strength("Right") - Input.get_action_strength("Left")) * speed
    velocity.y = gravity   jump
    #using found inputs
    velocity = move_and_slide(velocity, UP_DIRECTION)
    pass 

Here's my code, it tried commenting in the tdlr of what things are supposed to do. Again all I'm looking for is the reason why my elif statement is being applied every frame and how to fix that.

CodePudding user response:

If you have a conditional that looks like this:

if condition:
    prints("Something")

The execution flow would enter it when the condition is true.


Let us look at this as example:

if is_on_floor() && Input.is_action_just_pressed("Jump") && nojump == false:
    prints("Something")

The above conditional requires three things:

  • is_on_floor() must be true.
  • Input.is_action_just_pressed("Jump") must be true.
  • nojump == false must be true. I mean, nojump must be false.

I think we can agree that does not happen all the time.


Now, if I negate the conditional:

if not condition:
    prints("Something")

The execution flow would enter when the condition is false.


So, in a case like the one on your code:

if not (is_on_floor() && Input.is_action_just_pressed("Jump") && nojump == false):
    prints("Something")

The conditional has one requirement:

not (is_on_floor() && Input.is_action_just_pressed("Jump") && nojump == false)`

Must be true. I mean:

is_on_floor() && Input.is_action_just_pressed("Jump") && nojump == false

Must be false. Double check D'Morgan's Law if you need to.

It is false when either:

  • is_on_floor() is false.
  • Or Input.is_action_just_pressed("Jump") is false.
  • Or nojump == false is false.

In other words, only one of these being false is sufficient.

To restate that. This condition:

not (is_on_floor() && Input.is_action_just_pressed("Jump") && nojump == false)`

Is equivalent to the following condition (by D'Morgan's law):

not is_on_floor() or not Input.is_action_just_pressed("Jump") or not nojump == false

By the way, using and and or is idiomatic in GDScript.

Wait, I can simplify that a bit:

not is_on_floor() or not Input.is_action_just_pressed("Jump") or nojump`

Thus, the execution flow will enter if either:

  • not is_on_floor() is true. I mean, if is_on_floor() is false.
  • not Input.is_action_just_pressed("Jump") is true. I mean, if Input.is_action_just_pressed("Jump") is false.
  • nojump is true.

And I reiterate that is either of them. Only one is sufficient. And I believe most of the time you haven't just pressed "Jump", also being on the air is enough. And I suspect nojump is false most of the time.

So, we can conclude that the execution flow will enter most of the time.


Write what you mean. You say in comments:

#falling without jumping first

Let us do that. What does falling mean? Does it mean on the air?

var falling := not is_on_floor()

Or do you also mean going down?

var falling := not is_on_floor() and velocity.dot(Vector2.DOWN) > 0.0

Alright, your pick. What does jumping first mean? Does it mean the player got in the air as a result of a jump? Ok... So you would do this when the player jumped:

jumped = true

Which I believe is this:

if canjump > 0 && Input.is_action_just_pressed("Jump"):
    jumped = true

And reset it on the ground:

if is_on_floor():
    jumped = false

Now we can say "falling without jumping first":

if falling and not jumped:
    prints("something")

Almost as if it were the comment, but unlike the comment it can be executed.

  • Related