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 f394a0ac9e
commit 7439a962bd
3 changed files with 102 additions and 33 deletions

View File

@@ -75,7 +75,7 @@ scene dock and select "Attach Script".
.. image:: img/scripting_first_script_attach_script.png
The Attach node Script window appears. It allows you to select the script's
The Attach Node Script window appears. It allows you to select the script's
language and file path, among other options.
Change the Template from Default to Empty to start with a clean file. Leave the
@@ -83,8 +83,8 @@ other options by default and click the Create button to create the script.
.. image:: img/scripting_first_script_attach_node_script.png
The Script workspace should appear with your new file open and the following
line of code:
The Script workspace should appear with your new ``Sprite.gd`` file open and the
following line of code:
.. tabs::
.. code-tab:: gdscript GDScript
@@ -229,6 +229,7 @@ them.
.. code-tab:: gdscript GDScript
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
As we already saw, the ``var`` keyword defines a new variable. If you put it at
@@ -254,4 +255,26 @@ Run the scene to see the Godot head run in circles.
walls or the floor. In :ref:`doc_your_first_2d_game`, you will learn
another approach to moving objects while detecting collisions.
Our node currently moves by itself. In the next part, we'll use player input to control it.
Our node currently moves by itself. In the next part
:ref:`doc_scripting_player_input`, we'll use player input to control it.
Complete script
---------------
Here is the complete ``Sprite.gd`` file for reference.
.. tabs::
.. code-tab:: gdscript GDScript
extends Sprite
var speed = 400
var angular_speed = PI
func _process(delta):
rotation += angular_speed * delta
var velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta

View File

@@ -7,8 +7,9 @@
Listening to player input
=========================
Building upon the previous lesson, let's look at another important feature of
any game: giving control to the player. To add this, we need to modify our code.
Building upon the previous lesson :ref:`doc_scripting_first_script`, let's look
at another important feature of any game: giving control to the player.
To add this, we need to modify our ``Sprite.gd`` code.
.. image:: img/scripting_first_script_moving_with_input.gif
@@ -26,21 +27,20 @@ You have two main tools to process the player's input in Godot:
We're going to use the ``Input`` singleton here as we need to know if the player
wants to turn or move every frame.
For turning, we should use a new variable: ``direction``. Update the top of the
``_process()`` function like so, up to the line where we increment the sprite's
``rotation``.
For turning, we should use a new variable: ``direction``. In our ``_process()``
function, replace the ``rotation += angular_speed * delta`` line with the
code below.
.. tabs::
.. code-tab:: gdscript GDScript
func _process(delta):
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
rotation += angular_speed * direction * delta
Our ``direction`` local variable is a multiplier representing the direction in
which the player wants to turn. A value of ``0`` means the player isn't pressing
@@ -81,14 +81,15 @@ velocity. Replace the line starting with ``var velocity`` with the code below.
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
We initialize the ``velocity`` with a value of ``Vector2.ZERO``, another
constant of the built-in ``Vector`` type representing a 2D vector of length 0.
If the player presses the "ui_up" action, we then update the velocity's value,
causing the sprite to move forward.
Complete script
---------------
Here is the complete ``Sprite.gd`` file for reference.
.. tabs::
@@ -140,5 +141,5 @@ button presses from the users. There are quite a few more.
The ``Input`` singleton allows you to react to the players' input anywhere in
your code. In particular, you'll get to use it in the ``_process()`` loop.
In the next lesson, we'll build upon the relationship between scripts and nodes
by having our nodes trigger code in scripts.
In the next lesson :ref:`doc_signals`, we'll build upon the relationship between
scripts and nodes by having our nodes trigger code in scripts.

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 ``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