Logo 3.5Cats_AndHalfAFish

3.5Cats_AndHalfAFish

The problem with Godot ...

May 07, 2019 SeaRose, screenshots
... is mostly me.

Godot logo. I have been spending some time with the Godot Engine now, and while I generally really like working with it, I have also discovered some 'annoyances'.

My main annoyance isn't Godot's fault, but my own : I don't understand the source code.
As you probably know, the Godot Engine is written in C++. The bits that are useful for us game devs (a happy accidental pun), have bindings (magic ?) so that inside the editor we can code in GDScript. Using a scripting language to develop your game can save you much time : it's simpler to write, it's less verbose, and it's generally faster because you don't have to wait for your code to compile every time you want to test something.
The disadvantage (for me) of such a setup, is that you can't consult the source code from inside the editor. This can be quite useful if the documentation is unclear, or your code behaves in a way you didn't expect.
I -could- use another editor to inspect the source code ... but ... it's still C++ (which I don't understand very well).

Aside from this, there are of course also some bugs (as with every actively developed engine or library). Some of these bugs are fixed quickly, others persist for a long time (if not many people encounter them, for instance). Also, since I'm not the one developing the engine, there are some design decisions that don't suit my particular workflow.
It's often difficult to know which is which ... But in either case, it means you have to come up with (temporary) workarounds if you want to continue working on your game.

While working on SeaRose, a 2D hidden object game, I've noticed some 'annoyances' (by design, or bug?) with the Area2D node, which I use a lot for clickable sprites.

Setting up an Area2D node.
A clickable sprite.

If you need an irregular clickable shape, you can use a CollisionPolygon2D instead of a CollisionShape2D :

Setting up an Area2D node.
An irregularly shaped clickable sprite.

As you can see, it's very easy to set up.

When I tried to implement a pause btn however, I stumbled upon the first problem with Area2D nodes.

According to the Godot documentation, implementing a 'pause game' is surprisingly easy. You basically pause the main game loop and 'white-list' the nodes that should still be responsive when the game is paused (eg. the pause btn). Both are very easy to do :


/* -- Add this code to the pause btn -- */
is_paused = !is_paused   # boolean flag to toggle state
get_tree().set_deferred("paused", is_paused)   # this happens on NEXT frame !!! 

Pause btn code.
White-list the btn.

When we test the pause btn in-game, we get this :


Clicking the sprites when the game is not paused, writes a message to the Godot console.
When the game is paused and we click a sprite, nothing seems to happen. But when we unpause again, we see that the sprites actually still respond to the mouse clicks. They just respond later.

I'm not sure if this is a bug, or if the engine was designed this way. Either way, it's a problem for my game and I need to find a way around.

My solution is rather quick and dirty : clicking the pause button toggles the visiblity of a ColorRect node layered above the game screen. The ColorRect needs to have the mouse_filter property set to 'stop' to block mouse input from passing through to objects that lay below.
In your game, you should also set the 'modulate' property of the ColorRect to fully alpha (so you can't see it anymore). It will still block mouse input. When the game is unpaused, the ColorRect should have its 'visible' property set to false.

Pause btn toggles ColorRect visibility.
A ColorRect node to stop mouse input from reaching the clickable sprites.
Pause btn code.
Pause btn code.

The result :


Note : the Godot 'pause game' implementation seems to work perfectly for Controls and Timers.

A 'cleaner' solution should probably use the _undhandled_input() function instead of the Area2D input_event() signal. The problem is now : getting a reference to the sprite that was clicked :

Pause btn code, version 2.
Pause btn code ???

So, for now, I'll keep on using the ColorRect workaround.


The second problem I noticed with Area2D nodes, is when you try to limit some mouse action to the top sprite of 2 overlapping Area2D nodes. Let me illustrate this using SeaRose.

In my current (wip) implementation of the 'show a hint' btn, the player first needs to activate the hint btn by collecting (clicking) 3 bubbles. The bubbles appear at random places near the bottom of the screen and slowly drift to the top. The bubbles are clickable sprites, and I've made one large and very pink so you can see what's going on :


Mouse over and mouse click meant for only the bubble, also register with the underlying whale sprite.
Not what I want.

My quick and dirty solution : replace the bubble Area2D node with a TextureButton ! Use the BaseButton pressed() and Control mouse_entered() and mouse_exited() signals in the editor as needed. The mouse input is now no longer bleeding through to the underluing Area2D clickable sprite.
If your (top) sprite has an irregular shape, you can use a TextureButton click_mask :

TextureButton with click mask.
TextureButton with click mask.

The player can now click the pink bubble without also clicking the whale !

Note : the image you use as a click_mask has to be black and white only, and contain no transparency. Drag the .jpg file into the Godot res://folder, and reimport as BitMap. If you skip the reimport step, it won't work !


And ... that's it for now. Back to actually working on the game ! =)


Note :