Step by step: Improve flow and clarity for code replacement instructions

This commit is contained in:
Rémi Verschelde
2022-04-29 10:45:29 +02:00
parent b94f5dc89d
commit e0a3991ca9
3 changed files with 122 additions and 51 deletions

View File

@@ -8,7 +8,7 @@
.. _doc_signals:
Using Signals
Using signals
=============
In this lesson, we will look at signals. They are messages that nodes emit when
@@ -29,14 +29,18 @@ the bar to reflect the change. To do so, in Godot, you would use signals.
observer pattern. You can learn more about it here:
https://gameprogrammingpatterns.com/observer.html
We will now use a signal to make our Godot icon from last part move and stop
by pressing a button.
We will now use a signal to make our Godot icon from the previous lesson
(:ref:`doc_scripting_player_input`) move and stop by pressing a button.
.. Example
Scene setup
-----------
To add a button to our game, we will create a new main scene which will include
both a button and the ``Sprite2D.tscn`` scene that we scripted in previous
lessons.
Create a new scene by going to the menu Scene -> New Scene.
.. image:: img/signals_01_new_scene.png
@@ -46,14 +50,13 @@ root.
.. image:: img/signals_02_2d_scene.png
In the FileSystem dock, click and drag the ``Sprite2D.tscn`` file you saved
previously onto the Node2D to instantiate it.
.. image:: img/signals_03_dragging_scene.png
We want to add another node as a sibling of the Sprite2D. To do so, right-click on
Node2D and select Add Child Node.
We want to add another node as a sibling of the Sprite2D. To do so, right-click
on Node2D and select Add Child Node.
.. image:: img/signals_04_add_child_node.png
@@ -81,12 +84,15 @@ Your scene tree and viewport should look like this.
.. image:: img/signals_09_scene_setup.png
Save your newly created scene. You can then run it with :kbd:`F6`.
Connecting a signal in the editor
---------------------------------
Here, we want to connect the Button's "pressed" signal to our Sprite2D, and we
want to call a new function that will toggle its motion on and off. We need to
have a script attached to the Sprite2D node, which we do from the previous lesson.
have a script attached to the Sprite2D node, which we do from the previous
lesson.
You can connect signals in the Node dock. Select the Button node and, on the
right side of the editor, click on the tab named "Node" next to the Inspector.
@@ -101,10 +107,10 @@ Double-click the "pressed" signal to open the node connection window.
.. image:: img/signals_12_node_connection.png
There, you can connect the signal to the Sprite2D node. The node needs a receiver
method, a function that Godot will call when the Button emits the signal. The
editor generates one for you. By convention, we name these callback methods
"_on_NodeName_signal_name". Here, it'll be "_on_Button_pressed".
There, you can connect the signal to the Sprite2D node. The node needs a
receiver method, a function that Godot will call when the Button emits the
signal. The editor generates one for you. By convention, we name these callback
methods "_on_NodeName_signal_name". Here, it'll be "_on_Button_pressed".
.. note::
@@ -133,8 +139,8 @@ connection. This feature is only available when connecting nodes in the editor.
Let's replace the line with the ``pass`` keyword with code that'll toggle the
node's motion.
Our Sprite2D moves thanks to code in the ``_process()`` function. Godot provides a
method to toggle processing on and off: :ref:`Node.set_process()
Our Sprite2D moves thanks to code in the ``_process()`` function. Godot provides
a method to toggle processing on and off: :ref:`Node.set_process()
<class_Node_method_set_process>`. Another method of the Node class,
``is_processing()``, returns ``true`` if idle processing is active. We can use
the ``not`` keyword to invert the value.
@@ -155,7 +161,7 @@ following code, which we saw two lessons ago:
.. tabs::
.. code-tab:: gdscript GDScript
func _process(delta: float) -> void:
func _process(delta):
rotation += angular_speed * delta
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
@@ -170,11 +176,13 @@ Your complete ``Sprite2D.gd`` code should look like the following.
var speed = 400
var angular_speed = PI
func _process(delta: float) -> void:
func _process(delta):
rotation += angular_speed * delta
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
func _on_Button_pressed():
set_process(not is_processing())
@@ -192,12 +200,14 @@ that's useful to implement skill cooldown times, weapon reloading, and more.
Head back to the 2D workspace. You can either click the "2D" text at the top of
the window or press :kbd:`Ctrl + F1` (:kbd:`Alt + 1` on macOS).
In the Scene dock, right-click on the Sprite2D node and add a new child node. Search for
Timer and add the corresponding node. Your scene should now look like this.
In the Scene dock, right-click on the Sprite2D node and add a new child node.
Search for Timer and add the corresponding node. Your scene should now look like
this.
.. image:: img/signals_15_scene_tree.png
With the Timer node selected, go to the Inspector and check the **Autostart** property.
With the Timer node selected, go to the Inspector and check the **Autostart**
property.
.. image:: img/signals_18_timer_autostart.png
@@ -214,6 +224,10 @@ We need to do two operations to connect the nodes via code:
method of the node you want to listen to. In this case, we want to
listen to the Timer's "timeout" signal.
We want to connect the signal when the scene is intantiated, and we can do that
using the :ref:`Node._ready() <class_Node_method__ready>` built-in function,
which is called automatically by the engine when a node is fully instantiated.
To get a reference to a node relative to the current one, we use the method
:ref:`Node.get_node() <class_Node_method_get_node>`. We can store the reference
in a variable.
@@ -221,10 +235,6 @@ in a variable.
.. tabs::
.. code-tab:: gdscript GDScript
extends Sprite2D
#...
func _ready():
var timer = get_node("Timer")
@@ -258,9 +268,45 @@ The ``visible`` property is a boolean that controls the visibility of our node.
The line ``visible = not visible`` toggles the value. If ``visible`` is
``true``, it becomes ``false``, and vice-versa.
Complete script
---------------
That's it for our little moving and blinking Godot icon demo!
Here is the complete ``Sprite2D.gd`` file for reference.
.. tabs::
.. code-tab:: gdscript GDScript
extends Sprite2D
var speed = 400
var angular_speed = PI
func _ready():
var timer = get_node("Timer")
timer.connect("timeout", self, "_on_Timer_timeout")
func _process(delta):
rotation += angular_speed * delta
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
func _on_Button_pressed():
set_process(not is_processing())
func _on_Timer_timeout():
visible = not visible
Custom signals
--------------
.. note:: This section is a reference on how to define and use your own signals,
and does not build upon the project created in previous lessons.
You can define custom signals in a script. Say, for example, that you want to
show a game over screen when the player's health reaches zero. To do so, you
could define a signal named "died" or "health_depleted" when their health