How do you use area enter function with state machine?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By amaou310

I implemented state machine following a tutorial by Nathan Lovato and youtube, and player movement such as run, jump, airjump, and idle works perfectly fine.
I am now trying to change state when player enter enemy’s area2d by state_machine.transition_to("").
However, an error the identifier "state_machine" isn't declared in the current scope pops out. I would appreciate if you could teach me how to fix this and change state when area entered.

Player Script:

class_name Player

extends KinematicBody2D

var speed = 200
var acceleration = 30
var friction = 15
var gravity = 1500

var air_jump = true
var jump_strength = 570
var air_jump_strength := 550
var air_friction = 1

var direction := 1
var knockback := -150
var hitstate = false
var can_move = true

var _velocity := Vector2.ZERO

onready var position2D = $Position2D
onready var _animation_player: AnimationPlayer = $Position2D/PlayerSkinIK/AnimationPlayer


func get_input_direction() -> float:
    var _horizontal_direction = (
        Input.get_action_strength("move_right")
        - Input.get_action_strength("move_left")
    )
    return _horizontal_direction


func _process(delta: float) -> void:
    if get_global_mouse_position().x > $Position2D/PlayerSkinIK.global_position.x:
        position2D.scale.x=1
        direction == -1

    else:
        position2D.scale.x=-1
        direction == 1


func walk_flip():
    if get_global_mouse_position().x > $Position2D/PlayerSkinIK.global_position.x:
        position2D.scale.x=1
    else:
        position2D.scale.x=-1

    if is_on_floor() and position2D.scale.x==1 and Input.is_action_pressed("move_right"):
        _animation_player.play("Player-Run IK")
    elif is_on_floor() and position2D.scale.x==-1 and Input.is_action_pressed("move_right"):
        _animation_player.play("Player-Run IK Backward")
    elif is_on_floor() and position2D.scale.x==-1 and Input.is_action_pressed("move_left"):
        _animation_player.play("Player-Run IK")
    elif is_on_floor() and  position2D.scale.x==1 and Input.is_action_pressed("move_left"):
        _animation_player.play("Player-Run IK Backward")


func pass_through():
    set_collision_mask_bit(4, false)
    print("mask_off")
    yield(get_tree().create_timer(0.1), "timeout")
    set_collision_mask_bit(4, true)
    print("mask_on")


func _on_HurtboxPlayer_area_entered(area: Area2D):
    if area.name == "HitboxMushroom01":
        direction == -1
        print("ouch right")
        _velocity.y += -120
        _velocity.x = direction * 280


    if area.name == "HitboxMushroom02":
        direction == 1
        print("ouch left")
        _velocity.y += -120
        _velocity.x = direction * -280
        pass

Movement State:

extends PlayerState

export (NodePath) var _animation_player
onready var animation_player: AnimationPlayer = get_node(_animation_player)


func enter(_msg := {}) -> void:
    pass

func physics_update(delta: float) -> void:
    player.walk_flip()

    if not player.is_on_floor(): #If player is not on floor, FALL STATE
        state_machine.transition_to("Fall")
        return

    if not is_zero_approx(player.get_input_direction()): #If Player is moving, calculate Player's velocity.x 
        player._velocity.x = lerp(player._velocity.x, player.get_input_direction() * player.speed, player.acceleration * delta)

    player._velocity.y += player.gravity * delta #Gravity Calculation
    player._velocity = player.move_and_slide(player._velocity, Vector2.UP)


    if Input.is_action_just_pressed("jump"): #If input jump pressed, JUMP STATE
        if Input.is_action_pressed("ui_down"):
            state_machine.transition_to("JumpDown")
        else:
                state_machine.transition_to("Jump")
    elif is_zero_approx(player.get_input_direction()): #If Player is Not Moving, IDLE STATE
        state_machine.transition_to("Idle")
:bust_in_silhouette: Reply From: Ertain

I’ve used Nate’s state machine implementation, so I may know where your problem is. :wink:

Instead of the code being something like state_machine.transition_to("Fall"), it maybe _state_machine.transition_to("Fall"). IIRC, that leading underscore was written in the original member variable for the GDQuest code.

Thank you Ertaln for the help, though that’s not an answer I was looking for.
state_machine.transition_to("") inside movement state script works completely fine and I can change to any state. A problem is that inside player script, I have not declared what state is. Therefore, an error “state isnt declared” pops out when I wrote state_machine.transition_to("") inside function _on_HurtboxPlayer_area_entered(area: Area2D):. How would I fix this ? I would appreciate if you could teach me.

amaou310 | 2022-08-21 12:55

Are you trying to use only the code state_machine.transition_to(""), without passing the path to the transition_to() method? Or are you trying to use that code in the script with the Player class? It won’t work if you’re trying to use it in the Player class since it doesn’t inherit the State class. The code should be put in a class which inherits from the State class, e.g. the one meant for movement. If you want, you could connect the signal for entering the Area2D to the node that has the “movement” code attached.

Ertain | 2022-08-21 17:36

ohhh I didnt know I could do that. So I can connect area2d signal to state node.
Thank you !!

amaou310 | 2022-08-23 05:46