0006 - Overcoming the lack of observables in gdscript

·

2 min read

Has been quite a year, has it not? Anyhow. Right to the point: Something that was really annoying me ever since was the lack of observables in gdscript.

My game had a bug where mobile player were greeted with player controls in the editor. That's really inkonvenient, since they were blocking the editor controls.

Anyhow: The solution would seem simple: If the editor is in the actual "edit" mode, hide the controls. If the editor is in the actual "play" mode, show them. The catch: Nothing than the editor itself actually "knows" when we are editing or not, since we always need to decouple our code as good as we can we have to involve signals somehow.

To inform other scenes about changes of the editors state, we would need a singleton global scene. The editor itself just has to announce the change to "glob".

func set_state(new_state):
    current_state = new_state
    # that boi here
    glob.new_editor_state(new_state)

In "glob", we want to declare a signal and the function to fire it into the world.

enum EDITOR_STATES {STATE_EDIT, STATE_PLAY}
signal editor_state_changed(state)

func new_editor_state(state):
    emit_signal("editor_state_changed", state)

That is it. We made something observable. Every other scene can not react to changes of our editor. Of course you could use the exact same logic of you were making a global score counter. In our players controls, we can now listen to changes and hide the controls accordingly:

# this boi contains all the touch buttons.
# We want to hide it when the editor is ... well, editing.
onready var touch_input: Node2D = $touch_input_container 

func _ready():
    glob.connect("editor_state_changed", self, "on_editor_mode_changed")


func on_editor_mode_changed(state): 
    # the "state" parameter is implicit - you do not
    # see it above in glob.connect.
    # That is pretty annoying, but that is godot.
    if state == glob.EDITOR_STATES.STATE_EDIT:
        set_controls_visible(false)
    elif state == glob.EDITOR_STATES.STATE_PLAY:
        set_controls_visible(true)

func set_controls_visible(visible: bool):
    touch_input.visible = visible

That is all there is. Another bug bites the dust, playing on smartphones and touch devices is slightly less annoying. Using the editor still kinda sucks to, but thats a topic for another decade or so.

I updated the executables, you can play already. My build pipeline still works like a charm! I made something right last year, hoho. Till 2022 or so.