+1 vote

Sorry if title a bit confusing.

So, i have 2 classes

Idle:

class IdleState:
    var player
    func _init(player):
        self.player = player
        pass

    func input(ev):
        if there is movement action detected
            exit()
        pass

    func exit():
        player.set_state(RunningState.new(player))
        pass

Running:

class RunningState:
    var player
    func _init(player):
        self.player = player
        pass

    func input(ev):
        if there is no movement detected
             exit()
        pass

    func exit():
        player.set_state(IdleState.new(player))
        pass

I got this error for those 2 classes:

Parser Error: Identifier not found: RunningState

If i type running state before the idle state, idle state can identify running state but running state can't identify idle state. vice versa.
how do i get around this?

in Engine by (26 points)

1 Answer

0 votes

You shouldn't have two classes depending on each other. Not in GDScript and not in any other language.
What I suggest you do instead. Is to have a state manager class that switches the state of the player when necessary. Or maybe just have the class called state and have attributes like idle, running, walking... etc.

class State:
    var player
    var state
    const IDLE = 0
    const RUNNING = 1
    func _init(player):
         self.player = player

    func set_running():
         state = RUNNING
by (40 points)

Good design or not, the issue raised here is still relevant. In other languages it's possible to reference class A in class B and vice-versa.

This solution only allows for a closed set of states: you cannot extend your system with more states without adding more consts, boilerplate setter functions, and presumably dict entries to map the new states to their methods, or (god forbid) making an if-elif chain longer.

It also makes the case of parameterized states messier, as you will have to dump all the state-specific data into single class, and do something like

wall_direction = LEFT
set_wall_holding()

needlessly leaking data specific to wall-holding to every other state, and increasing the chances of undetected errors (like forgetting to set wall_direction, causing it to use some old value).

If you think of the states in an interfacey record-of-functions sort of way, there is nothing more wrong about the classes instancing each other than there is wrong with 5 - 3 equaling 2 and 2 + 3 equaling 5.

Good design or not, the issue raised here is still relevant. In other
languages it's possible to reference class A in class B and
vice-versa.

+1

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.