Space Kim
Space Kim

Reputation: 13

How do I make player not move when it is attacking?

How do I prevent player to not move when it is attacking? My goal was to make player move just a little bit when it is attacking and when player is not attacking it can move normally. But right now if I press directional input and attack at the same time player can still moves normally.

This is my code:

extends CharacterBody2D

@export var speed: float = 100
@export var accel: float = 10

@export var dashing = false
@export var dashdistance: float = 300

@export var attacking = false
@export var attackdistance: float = 100

@export var dasheffect = preload("res://dasheffect.tscn")
@onready var anime = $AnimatedSprite2D

@onready var sword: Node2D = get_node("sword")
@onready var sword_anime: AnimationPlayer = get_node("sword/SwordAnimationPlayer")

@export var mouse_direction: Vector2 = (get_global_mouse_position() - global_position).normalized()

func _process(_delta: float) -> void:
    var mouse_direction: Vector2 = (get_global_mouse_position() - global_position).normalized()
    
    sword.rotation = mouse_direction.angle()
    
    if mouse_direction.x > 0 and anime.flip_h:
        anime.flip_h = false
    elif mouse_direction.x < 0 and not anime.flip_h: 
        anime.flip_h = true

enum States {
    MOVE,
    ATTACK
}

var state = States.MOVE


func _physics_process(delta):
    if attacking:
        return
    
    match state:
        States.MOVE:
            move(delta)
        States.ATTACK:
            attack()

func move(delta):
    print("move")
    
    var direction: Vector2 = Input.get_vector("left", "rihgt", "up", "down")
    
    velocity.x = move_toward(velocity.x, speed * direction.x, accel)
    velocity.y = move_toward(velocity.y, speed * direction.y, accel)
    
    if velocity != Vector2.ZERO:
        anime.play("run")
    else:
        anime.play("idle")
    
    dash()
    move_and_slide()
    
    if Input.is_action_just_pressed("attack"):
        state = States.ATTACK

func attack():
    print("attack")
    
    attacking = true
    
    sword_anime.play("swing")
    anime.play("attack")
    
    
    if !Input.is_action_just_pressed("attack"):
        state = States.MOVE
        attacking = false

func dash():
    var mouse_direction: Vector2 = (get_global_mouse_position() - global_position).normalized()
    
    if Input.is_action_just_pressed("ui_accept"):
        velocity = mouse_direction.normalized() * dashdistance
        dashing = true
        await get_tree().create_timer(0.2)
        dashing = false

Upvotes: 0

Views: 310

Answers (1)

Bugfish
Bugfish

Reputation: 1729

The problem is that you checking for an input in your attack function. So after switching into the attack state the very next frame the condition

!Input.is_action_just_pressed("attack")

will be true and you are moving back to the move state before the animation is finished.

There are multiple solutions how you could fix that. You could for example create a timer and determine, that your attack has a fixed duration and after the timer expired you could go back to the move state.

Or another way could be to use one of you attack animations as indicator, if your character is still attacking.

In my example I will be using your AnimationSprite with the attack animation: I will be using the animation_finished signal of the animated sprite. I connect it to the function on_animation_finished():

func attack():
    print("attack")
    
    attacking = true       
    sword_anime.play("swing")
    anime.play("attack") 
    //nothing else to do here

//connected to the animation_finished signal of your node AnimatedSprite2D
func on_animation_finished(): 
    if anime.animation == "attack":
        state = States.MOVE
        attacking = false

This way you will only return to the move state, if your attack animation is finished playing. If you do not want to use the signal, you could also move

if attacking:
        return

from your physics process into you attack function and do the check there:

func attack():
    if not attacking:
        print("attack")
        attacking = true       
        sword_anime.play("swing")
        anime.play("attack") 
    //if the animation changed meanwhile, or it finished playing move back to state move
    if anime.animation != "attack" or not anime.is_playing():
         state = States.MOVE
         attacking = false

Upvotes: 0

Related Questions