Search code examples
godotgdscript

how to stop my character from jumping right whenever I just jump?


I'm working on a 2d side scrolling game and i ran into a problem when trying to implement the shooting into the player character, it used to be when shooting while jumping it does not shoot but now whenever I press the jump key the player jumps towards the right even when I'm not activating the direction keys

here is the code

extends KinematicBody2D

const GRAVITY = 20
const SPEED = 200
const JUMP_HIGHT = -550
const UP = Vector2(0,-1)

const SHOOT = preload("res://shoot.tscn")

var motion = Vector2()
var on_ground = false
var is_attacking = false

# warning-ignore:unused_argument
func _physics_process(delta: float) -> void:
    motion.y += GRAVITY

    if Input.is_action_pressed("right") || is_on_floor() == false:
        if is_attacking == false:
            motion.x = SPEED
            if is_attacking == false:
                $Sprite.flip_h = false
                $Sprite.play("run")
                if sign($Position2D.position.x) == -1:
                    $Position2D.position.x *= -1

    elif Input.is_action_pressed("left") || is_on_floor() == false:
        if is_attacking == false :
            motion.x = -SPEED
            if is_attacking == false:
                $Sprite.flip_h = true
                $Sprite.play("run")
                if sign($Position2D.position.x) == 1:
                    $Position2D.position.x *= -1

    else : 
        if on_ground == true && is_attacking == false :
            $Sprite.play("idle")
            motion.x = 0

    
    if Input.is_action_just_pressed("jump"):
        if is_attacking == false :
            if on_ground == true :
                    motion.y = JUMP_HIGHT
                    on_ground = false

    if is_on_floor():
        if on_ground == false :
            is_attacking = false
        on_ground = true
    else :
        if is_attacking == false :
            on_ground = false
            if motion.y < 0 :
                $Sprite.play("jump")
            else :
                $Sprite.play("fall")

    if Input.is_action_just_pressed("shoot") && is_attacking == false:
        if is_on_floor() :
            motion.x = 0
        is_attacking = true
        $Sprite.play("attack")
        var shoot = SHOOT.instance()
        if sign($Position2D.position.x) == 1 :
            shoot.set_shoot_direction(1)
        else:
            shoot.set_shoot_direction(-1)
        
        get_parent().add_child(shoot)
        shoot.position = $Position2D.global_position
        
    motion = move_and_slide(motion,UP)
    

func _on_Sprite_animation_finished() -> void:
    is_attacking = false

Solution

  • I think you are going in the wrong direction from the start and I haven't seen anyone in tutorials doing this. You have input checks together with state checks and movement repeatedly. Since you are new you need to write platformer code from scratch many times to experiment and have a feel how code should flow. Do it separately:

    # don't use $ for nodes you call often save reference in variable (I'm guessing it's AnimatedSprite)
    var sprite:AnimatedSprite = $Sprite
    var dir:float = 0.0 #used for movement and sprite flipping
    #Limit your code to physics process only for physics related logic
    func _physics_process(delta:float)->void:
        # get direction input
        # math trick to get value -1 to 1 to know how strong go which direction
        dir = Input.get_action_strength("move_right") - 
        Input.get_action_strength("move_left")
    
        #ground check - call function once and use variable
        is_grounded = is_on_floor()
    
        # apply speed(use dir to give direction)
        motion.x = SPEED * dir
    
        # apply gravity
        if !is_grounded:
            motion.y += GRAVITY * delta
        elif Input.is_action_just_pressed("jump"):
            motion.y = JUMP_HIGHT
    
        # apply movement
        motion = move_and_slide(motion, Vector2.UP)
    
    # use process for sprites
    func _process(delta:float)->void:
        #check if direction is not close to 0
        if abs(dir) > 0.001:
            if dir > 0:
                sprite.h_flip = false
            else:
                sprite.h_flip = true
        
        #state check for sprites
        if is_grounded:
            if abs(dir) > 0.001:
                sprite.play("run")
            else:
                sprite.play("idle")
        else:
            if motion.y < 0.0:
                sprite.play("jump")
            else:
                sprite.play("fall")
    

    This will be a better starting ground to implement shooting. seems like you have stopped movement on shooting, so you can interrupt dir before applying speed.

       if is_shooting && is_grounded:
           dir = 0.0