|
@@ -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 ``Sprite.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,7 +50,6 @@ root.
|
|
|
|
|
|
.. image:: img/signals_02_2d_scene.png
|
|
|
|
|
|
-
|
|
|
In the FileSystem dock, click and drag the ``Sprite.tscn`` file you saved
|
|
|
previously onto the Node2D to instantiate it.
|
|
|
|
|
@@ -81,6 +84,8 @@ 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
|
|
|
---------------------------------
|
|
|
|
|
@@ -155,7 +160,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 +175,13 @@ Your complete ``Sprite.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 +199,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 Sprite 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 Sprite 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 +223,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 +234,6 @@ in a variable.
|
|
|
.. tabs::
|
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
|
|
- extends Sprite
|
|
|
-
|
|
|
- #...
|
|
|
-
|
|
|
func _ready():
|
|
|
var timer = get_node("Timer")
|
|
|
|
|
@@ -258,9 +267,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 ``Sprite.gd`` file for reference.
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
+
|
|
|
+ extends Sprite
|
|
|
+
|
|
|
+ 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
|