From 3beb0ac5d10832a2a4fbc802513e1f61ce108abe Mon Sep 17 00:00:00 2001 From: Relintai Date: Thu, 12 Jan 2023 18:31:02 +0100 Subject: [PATCH] Removed tabs. --- .../class_reference_writing_guidelines.rst | 14 +- .../compiling_with_script_encryption_key.rst | 14 +- .../introduction_to_the_buildsystem.rst | 13 +- .../configuring_an_ide/visual_studio_code.rst | 24 +- development/cpp/custom_modules_in_cpp.rst | 5 +- .../first_2d_game/01.project_setup.rst | 32 +- .../first_2d_game/03.coding_the_player.rst | 302 ++---------------- .../first_2d_game/04.creating_the_enemy.rst | 92 +----- .../first_2d_game/05.the_main_game_scene.rst | 273 ++-------------- .../first_2d_game/06.heads_up_display.rst | 249 ++------------- .../first_3d_game/03.player_movement_code.rst | 151 +-------- .../first_3d_game/04.mob_scene.rst | 116 +------ .../first_3d_game/05.spawning_mobs.rst | 83 +---- .../first_3d_game/06.jump_and_squash.rst | 97 +----- .../first_3d_game/07.killing_player.rst | 226 +------------ .../first_3d_game/08.score_and_replay.rst | 132 ++------ .../first_3d_game/09.adding_animations.rst | 201 +----------- .../step_by_step/scripting_first_script.rst | 93 ++---- .../step_by_step/scripting_player_input.rst | 70 +--- getting_started/step_by_step/signals.rst | 55 ++-- tutorials/2d/2d_movement.rst | 175 +--------- tutorials/2d/2d_sprite_animation.rst | 58 +--- tutorials/2d/2d_transforms.rst | 22 +- tutorials/2d/custom_drawing_in_2d.rst | 201 ++---------- .../3d/procedural_geometry/arraymesh.rst | 36 ++- .../procedural_geometry/immediategeometry.rst | 10 +- .../3d/procedural_geometry/meshdatatool.rst | 25 +- .../3d/procedural_geometry/surfacetool.rst | 30 +- tutorials/3d/using_transforms.rst | 171 +++------- tutorials/animation/animation_tree.rst | 49 +-- tutorials/audio/recording_with_microphone.rst | 80 +---- tutorials/audio/sync_with_audio.rst | 64 +--- tutorials/best_practices/data_preferences.rst | 32 +- tutorials/best_practices/godot_interfaces.rst | 255 ++------------- .../best_practices/godot_notifications.rst | 104 +----- .../best_practices/logic_preferences.rst | 25 +- .../best_practices/scene_organization.rst | 96 ++---- .../best_practices/scenes_versus_scripts.rst | 57 +--- tutorials/export/exporting_basics.rst | 118 +------ tutorials/export/exporting_pcks.rst | 19 +- .../inputs/controllers_gamepads_joysticks.rst | 65 ++-- tutorials/inputs/custom_mouse_cursor.rst | 21 +- tutorials/inputs/handling_quit_requests.rst | 31 +- tutorials/inputs/input_examples.rst | 183 ++--------- tutorials/inputs/inputevent.rst | 43 +-- .../inputs/mouse_and_input_coordinates.rst | 27 +- tutorials/io/saving_games.rst | 141 +------- tutorials/math/beziers_and_curves.rst | 116 ++----- tutorials/math/interpolation.rst | 58 +--- tutorials/math/matrices_and_transforms.rst | 149 ++------- tutorials/math/random_number_generation.rst | 211 +++--------- tutorials/math/vector_math.rst | 130 ++------ tutorials/math/vectors_advanced.rst | 280 +++------------- tutorials/networking/http_client_class.rst | 118 +------ tutorials/networking/http_request_class.rst | 56 +--- .../threads/using_multiple_threads.rst | 15 +- tutorials/performance/using_multimesh.rst | 33 +- tutorials/performance/using_servers.rst | 22 +- tutorials/physics/kinematic_character_2d.rst | 102 +----- tutorials/physics/physics_introduction.rst | 107 +------ tutorials/physics/ragdoll_system.rst | 5 +- tutorials/physics/ray-casting.rst | 113 ++----- tutorials/physics/rigid_body.rst | 26 +- tutorials/physics/using_area_2d.rst | 16 +- tutorials/physics/using_kinematic_body_2d.rst | 224 ++----------- .../plugins/editor/inspector_plugins.rst | 133 +------- tutorials/plugins/editor/making_plugins.rst | 147 ++------- .../plugins/running_code_in_the_editor.rst | 152 ++------- .../scripting/change_scenes_manually.rst | 30 +- .../scripting/creating_script_templates.rst | 30 +- .../scripting/cross_language_scripting.rst | 35 +- tutorials/scripting/groups.rst | 35 +- .../scripting/idle_and_physics_processing.rst | 42 +-- .../scripting/instancing_with_signals.rst | 74 +---- .../scripting/nodes_and_scene_instances.rst | 84 ++--- tutorials/scripting/overridable_functions.rst | 65 +--- tutorials/scripting/pausing_games.rst | 47 +-- tutorials/scripting/resources.rst | 123 ++----- tutorials/scripting/scene_tree.rst | 35 +- tutorials/scripting/scene_unique_nodes.rst | 5 +- tutorials/scripting/singletons_autoload.rst | 110 ++----- tutorials/ui/custom_gui_controls.rst | 105 +----- tutorials/ui/gui_containers.rst | 5 +- tutorials/ui/gui_navigation.rst | 12 +- tutorials/ui/gui_skinning.rst | 10 +- 85 files changed, 1127 insertions(+), 6313 deletions(-) diff --git a/community/contributing/class_reference_writing_guidelines.rst b/community/contributing/class_reference_writing_guidelines.rst index e1560ad..fcb756a 100644 --- a/community/contributing/class_reference_writing_guidelines.rst +++ b/community/contributing/class_reference_writing_guidelines.rst @@ -203,20 +203,12 @@ workflow. The above will display as: -.. tabs:: - .. code-tab:: gdscript GDScript - +gdscript GDScript +``` func _ready(): var sprite = get_node("Sprite") print(sprite.get_pos()) - - .. code-tab:: csharp - - public override void _Ready() - { - var sprite = GetNode("Sprite"); - GD.Print(sprite.GetPos()); - } +``` To denote important information, add a paragraph starting with "[b]Note:[/b]" at the end of the description: diff --git a/development/compiling/compiling_with_script_encryption_key.rst b/development/compiling/compiling_with_script_encryption_key.rst index 33fc5cb..e2f8ad6 100644 --- a/development/compiling/compiling_with_script_encryption_key.rst +++ b/development/compiling/compiling_with_script_encryption_key.rst @@ -47,18 +47,18 @@ Step by step 2. Set this key as environment variable in the console that you will use to compile Godot, like this: - .. tabs:: - .. code-tab:: bash Linux/macOS - export SCRIPT_AES256_ENCRYPTION_KEY="your_generated_key" +bash Linux/macOS - .. code-tab:: bat Windows (cmd) +``` export SCRIPT_AES256_ENCRYPTION_KEY="your_generated_key" ``` - set SCRIPT_AES256_ENCRYPTION_KEY=your_generated_key +bat Windows (cmd) - .. code-tab:: bat Windows (PowerShell) +``` set SCRIPT_AES256_ENCRYPTION_KEY=your_generated_key ```` - $env:SCRIPT_AES256_ENCRYPTION_KEY="your_generated_key" +bat Windows (PowerShell) + +``` $env:SCRIPT_AES256_ENCRYPTION_KEY="your_generated_key" ``` 3. Compile Godot export templates and set them as custom export templates in the export preset options. diff --git a/development/compiling/introduction_to_the_buildsystem.rst b/development/compiling/introduction_to_the_buildsystem.rst index 082b201..1390759 100644 --- a/development/compiling/introduction_to_the_buildsystem.rst +++ b/development/compiling/introduction_to_the_buildsystem.rst @@ -297,18 +297,17 @@ options automatically without having to supply them via the command line. For instance, you may want to build Godot in parallel with the aforementioned ``-j`` option for all the future builds: -.. tabs:: - .. code-tab:: bash Linux/macOS +bash Linux/macOS - export SCONSFLAGS="-j4" +``` export SCONSFLAGS="-j4" ``` - .. code-tab:: bat Windows (cmd) +bat Windows (cmd) - set SCONSFLAGS=-j4 +``` set SCONSFLAGS=-j4 ``` - .. code-tab:: powershell Windows (powershell) +powershell Windows (powershell) - $env:SCONSFLAGS="-j4" +``` $env:SCONSFLAGS="-j4" ``` Export templates ---------------- diff --git a/development/cpp/configuring_an_ide/visual_studio_code.rst b/development/cpp/configuring_an_ide/visual_studio_code.rst index 41935b0..468e1fe 100644 --- a/development/cpp/configuring_an_ide/visual_studio_code.rst +++ b/development/cpp/configuring_an_ide/visual_studio_code.rst @@ -33,9 +33,9 @@ Importing the project - Within the ``tasks.json`` file find the ``"tasks"`` array and add a new section to it: -.. tabs:: - .. code-tab:: js Linux/X11 +js Linux/X11 +``` { "label": "build", "group": "build", @@ -46,9 +46,11 @@ Importing the project ], "problemMatcher": "$msCompile" } +``` - .. code-tab:: js Windows +js Windows +``` { "label": "build", "group": "build", @@ -62,6 +64,7 @@ Importing the project ], "problemMatcher": "$msCompile" } +``` .. figure:: img/vscode_3_tasks.json.png :figclass: figure-w480 @@ -87,9 +90,9 @@ To run and debug the project you need to create a new configuration in the ``lau adjust the configuration example provided accordingly. - Within the ``launch.json`` file find the ``"configurations"`` array and add a new section to it: -.. tabs:: - .. code-tab:: js X11 +js X11 +``` { "name": "Launch Project", "type": "lldb", @@ -105,8 +108,12 @@ To run and debug the project you need to create a new configuration in the ``lau "externalConsole": false, "preLaunchTask": "build" } - .. code-tab:: js X11_gdb +``` + +js X11_gdb + +``` { "name": "Launch Project", "type": "cppdbg", @@ -130,9 +137,11 @@ To run and debug the project you need to create a new configuration in the ``lau ], "preLaunchTask": "build" } +``` - .. code-tab:: js Windows +js Windows +``` { "name": "Launch Project", "type": "cppvsdbg", @@ -148,6 +157,7 @@ To run and debug the project you need to create a new configuration in the ``lau "visualizerFile": "${workspaceFolder}/platform/windows/godot.natvis", "preLaunchTask": "build" } +``` .. figure:: img/vscode_2_launch.json.png :figclass: figure-w480 diff --git a/development/cpp/custom_modules_in_cpp.rst b/development/cpp/custom_modules_in_cpp.rst index e2d7841..e1e84b0 100644 --- a/development/cpp/custom_modules_in_cpp.rst +++ b/development/cpp/custom_modules_in_cpp.rst @@ -230,15 +230,14 @@ Using the module You can now use your newly created module from any script: -.. tabs:: - .. code-tab:: gdscript GDScript - +``` var s = Summator.new() s.add(10) s.add(20) s.add(30) print(s.get_total()) s.reset() +``` The output will be ``60``. diff --git a/getting_started/first_2d_game/01.project_setup.rst b/getting_started/first_2d_game/01.project_setup.rst index 84a88bf..14dd28d 100644 --- a/getting_started/first_2d_game/01.project_setup.rst +++ b/getting_started/first_2d_game/01.project_setup.rst @@ -9,40 +9,14 @@ Launch Godot and create a new project. .. image:: img/new-project-button.png -.. tabs:: - .. tab:: GDScript +GDScript +``` Download :download:`dodge_assets.zip `. The archive contains the images and sounds you'll be using to make the game. Extract the archive and move the ``art/`` and ``fonts/`` directories to your project's directory. - - .. tab:: C# - - Download :download:`dodge_assets.zip `. - The archive contains the images and sounds you'll be using - to make the game. Extract the archive and move the ``art/`` - and ``fonts/`` directories to your project's directory. - - Ensure that you have the required dependencies to use C# in Godot. - You need the .NET Core 3.1 SDK, and an editor such as VS Code. - See :ref:`doc_c_sharp_setup`. - - .. tab:: GDNative C++ - - Download :download:`dodge_assets_with_gdnative.zip - `. - The archive contains the images and sounds you'll be using - to make the game. It also contains a starter GDNative project - including a ``SConstruct`` file, a ``dodge_the_creeps.gdnlib`` - file, a ``player.gdns`` file, and an ``entry.cpp`` file. - - Ensure that you have the required dependencies to use GDNative C++. - You need a C++ compiler such as GCC or Clang or MSVC that supports C++14. - On Windows you can download Visual Studio 2019 and select the C++ workload. - You also need SCons to use the build system (the SConstruct file). - Then you need to `download the Godot C++ bindings `_ - and place them in your project. +``` Your project folder should look like this. diff --git a/getting_started/first_2d_game/03.coding_the_player.rst b/getting_started/first_2d_game/03.coding_the_player.rst index 9d05cbe..074bc91 100644 --- a/getting_started/first_2d_game/03.coding_the_player.rst +++ b/getting_started/first_2d_game/03.coding_the_player.rst @@ -25,63 +25,14 @@ click "Create": Start by declaring the member variables this object will need: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` extends Area2D export var speed = 400 # How fast the player will move (pixels/sec). var screen_size # Size of the game window. - - .. code-tab:: csharp - - using Godot; - using System; - - public class Player : Area2D - { - [Export] - public int Speed = 400; // How fast the player will move (pixels/sec). - - public Vector2 ScreenSize; // Size of the game window. - } - - .. code-tab:: cpp - - // A `player.gdns` file has already been created for you. Attach it to the Player node. - - // Create two files `player.cpp` and `player.hpp` next to `entry.cpp` in `src`. - // This code goes in `player.hpp`. We also define the methods we'll be using here. - #ifndef PLAYER_H - #define PLAYER_H - - #include - #include - #include - #include - #include - - class Player : public godot::Area2D { - GODOT_CLASS(Player, godot::Area2D) - - godot::AnimatedSprite *_animated_sprite; - godot::CollisionShape2D *_collision_shape; - godot::Input *_input; - godot::Vector2 _screen_size; // Size of the game window. - - public: - real_t speed = 400; // How fast the player will move (pixels/sec). - - void _init() {} - void _ready(); - void _process(const double p_delta); - void start(const godot::Vector2 p_position); - void _on_Player_body_entered(godot::Node2D *_body); - - static void _register_methods(); - }; - - #endif // PLAYER_H +``` Using the ``export`` keyword on the first variable ``speed`` allows us to set its value in the Inspector. This can be handy for values that you want to be @@ -90,41 +41,15 @@ node and you'll see the property now appears in the "Script Variables" section of the Inspector. Remember, if you change the value here, it will override the value written in the script. -.. warning:: If you're using C#, you need to (re)build the project assemblies - whenever you want to see new export variables or signals. This - build can be manually triggered by clicking the word "Mono" at the - bottom of the editor window to reveal the Mono Panel, then clicking - the "Build Project" button. - .. image:: img/export_variable.png The ``_ready()`` function is called when a node enters the scene tree, which is a good time to find the size of the game window: -.. tabs:: - .. code-tab:: gdscript GDScript - +``` func _ready(): screen_size = get_viewport_rect().size - - .. code-tab:: csharp - - public override void _Ready() - { - ScreenSize = GetViewportRect().Size; - } - - .. code-tab:: cpp - - // This code goes in `player.cpp`. - #include "player.hpp" - - void Player::_ready() { - _animated_sprite = get_node("AnimatedSprite"); - _collision_shape = get_node("CollisionShape2D"); - _input = godot::Input::get_singleton(); - _screen_size = get_viewport_rect().size; - } +``` Now we can use the ``_process()`` function to define what the player will do. ``_process()`` is called every frame, so we'll use it to update elements of our @@ -173,9 +98,8 @@ Click the "Close" button to close the project settings. You can detect whether a key is pressed using ``Input.is_action_pressed()``, which returns ``true`` if it's pressed or ``false`` if it isn't. -.. tabs:: - .. code-tab:: gdscript GDScript - +gdscript GDScript +``` func _process(delta): var velocity = Vector2.ZERO # The player's movement vector. if Input.is_action_pressed("move_right"): @@ -192,62 +116,7 @@ which returns ``true`` if it's pressed or ``false`` if it isn't. $AnimatedSprite.play() else: $AnimatedSprite.stop() - - .. code-tab:: csharp - - public override void _Process(float delta) - { - var velocity = Vector2.Zero; // The player's movement vector. - - if (Input.IsActionPressed("move_right")) - { - velocity.x += 1; - } - - if (Input.IsActionPressed("move_left")) - { - velocity.x -= 1; - } - - if (Input.IsActionPressed("move_down")) - { - velocity.y += 1; - } - - if (Input.IsActionPressed("move_up")) - { - velocity.y -= 1; - } - - var animatedSprite = GetNode("AnimatedSprite"); - - if (velocity.Length() > 0) - { - velocity = velocity.Normalized() * Speed; - animatedSprite.Play(); - } - else - { - animatedSprite.Stop(); - } - } - - .. code-tab:: cpp - - // This code goes in `player.cpp`. - void Player::_process(const double p_delta) { - godot::Vector2 velocity(0, 0); - - velocity.x = _input->get_action_strength("move_right") - _input->get_action_strength("move_left"); - velocity.y = _input->get_action_strength("move_down") - _input->get_action_strength("move_up"); - - if (velocity.length() > 0) { - velocity = velocity.normalized() * speed; - _animated_sprite->play(); - } else { - _animated_sprite->stop(); - } - } +``` We start by setting the ``velocity`` to ``(0, 0)`` - by default, the player should not be moving. Then we check each input and add/subtract from the @@ -281,28 +150,13 @@ can also use ``clamp()`` to prevent it from leaving the screen. *Clamping* a value means restricting it to a given range. Add the following to the bottom of the ``_process`` function (make sure it's not indented under the `else`): -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` position += velocity * delta position.x = clamp(position.x, 0, screen_size.x) position.y = clamp(position.y, 0, screen_size.y) - - .. code-tab:: csharp - - Position += velocity * delta; - Position = new Vector2( - x: Mathf.Clamp(Position.x, 0, ScreenSize.x), - y: Mathf.Clamp(Position.y, 0, ScreenSize.y) - ); - - .. code-tab:: cpp - - godot::Vector2 position = get_position(); - position += velocity * (real_t)p_delta; - position.x = godot::Math::clamp(position.x, (real_t)0.0, _screen_size.x); - position.y = godot::Math::clamp(position.y, (real_t)0.0, _screen_size.y); - set_position(position); +``` .. tip:: The `delta` parameter in the `_process()` function refers to the *frame length* - the amount of time that the previous frame took to complete. @@ -331,9 +185,9 @@ horizontally using the ``flip_h`` property for left movement. We also have the "up" animation, which should be flipped vertically with ``flip_v`` for downward movement. Let's place this code at the end of the ``_process()`` function: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` if velocity.x != 0: $AnimatedSprite.animation = "walk" $AnimatedSprite.flip_v = false @@ -342,57 +196,21 @@ movement. Let's place this code at the end of the ``_process()`` function: elif velocity.y != 0: $AnimatedSprite.animation = "up" $AnimatedSprite.flip_v = velocity.y > 0 - - .. code-tab:: csharp - - if (velocity.x != 0) - { - animatedSprite.Animation = "walk"; - animatedSprite.FlipV = false; - // See the note below about boolean assignment. - animatedSprite.FlipH = velocity.x < 0; - } - else if (velocity.y != 0) - { - animatedSprite.Animation = "up"; - animatedSprite.FlipV = velocity.y > 0; - } - - .. code-tab:: cpp - - if (velocity.x != 0) { - _animated_sprite->set_animation("walk"); - _animated_sprite->set_flip_v(false); - // See the note below about boolean assignment. - _animated_sprite->set_flip_h(velocity.x < 0); - } else if (velocity.y != 0) { - _animated_sprite->set_animation("up"); - _animated_sprite->set_flip_v(velocity.y > 0); - } +``` .. Note:: The boolean assignments in the code above are a common shorthand for programmers. Since we're doing a comparison test (boolean) and also *assigning* a boolean value, we can do both at the same time. Consider this code versus the one-line boolean assignment above: - .. tabs:: - .. code-tab :: gdscript GDScript + ``` if velocity.x < 0: $AnimatedSprite.flip_h = true else: $AnimatedSprite.flip_h = false - .. code-tab:: csharp - - if (velocity.x < 0) - { - animatedSprite.FlipH = true; - } - else - { - animatedSprite.FlipH = false; - } + ``` Play the scene again and check that the animations are correct in each of the directions. @@ -405,18 +223,11 @@ directions. When you're sure the movement is working correctly, add this line to ``_ready()``, so the player will be hidden when the game starts: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` hide() - - .. code-tab:: csharp - - Hide(); - - .. code-tab:: cpp - - hide(); +``` Preparing for collisions ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -427,32 +238,11 @@ functionality to make it work. Add the following at the top of the script, after ``extends Area2D``: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` signal hit - - .. code-tab:: csharp - - // Don't forget to rebuild the project so the editor knows about the new signal. - - [Signal] - public delegate void Hit(); - - .. code-tab:: cpp - - // This code goes in `player.cpp`. - // We need to register the signal here, and while we're here, we can also - // register the other methods and register the speed property. - void Player::_register_methods() { - godot::register_method("_ready", &Player::_ready); - godot::register_method("_process", &Player::_process); - godot::register_method("start", &Player::start); - godot::register_method("_on_Player_body_entered", &Player::_on_Player_body_entered); - godot::register_property("speed", &Player::speed, (real_t)400.0); - // This below line is the signal. - godot::register_signal("hit", godot::Dictionary()); - } +``` This defines a custom signal called "hit" that we will have our player emit (send out) when it collides with an enemy. We will use ``Area2D`` to detect the @@ -473,34 +263,15 @@ your player's script. Note the green icon indicating that a signal is connected to this function. Add this code to the function: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _on_Player_body_entered(body): hide() # Player disappears after being hit. emit_signal("hit") # Must be deferred as we can't change physics properties on a physics callback. $CollisionShape2D.set_deferred("disabled", true) - - .. code-tab:: csharp - - public void OnPlayerBodyEntered(PhysicsBody2D body) - { - Hide(); // Player disappears after being hit. - EmitSignal(nameof(Hit)); - // Must be deferred as we can't change physics properties on a physics callback. - GetNode("CollisionShape2D").SetDeferred("disabled", true); - } - - .. code-tab:: cpp - - // This code goes in `player.cpp`. - void Player::_on_Player_body_entered(godot::Node2D *_body) { - hide(); // Player disappears after being hit. - emit_signal("hit"); - // Must be deferred as we can't change physics properties on a physics callback. - _collision_shape->set_deferred("disabled", true); - } +``` Each time an enemy hits the player, the signal is going to be emitted. We need to disable the player's collision so that we don't trigger the ``hit`` signal @@ -514,30 +285,13 @@ more than once. The last piece is to add a function we can call to reset the player when starting a new game. -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func start(pos): position = pos show() $CollisionShape2D.disabled = false - - .. code-tab:: csharp - - public void Start(Vector2 pos) - { - Position = pos; - Show(); - GetNode("CollisionShape2D").Disabled = false; - } - - .. code-tab:: cpp - - // This code goes in `player.cpp`. - void Player::start(const godot::Vector2 p_position) { - set_position(p_position); - show(); - _collision_shape->set_disabled(false); - } +``` With the player working, we'll work on the enemy in the next lesson. diff --git a/getting_started/first_2d_game/04.creating_the_enemy.rst b/getting_started/first_2d_game/04.creating_the_enemy.rst index 23e1848..8207c4b 100644 --- a/getting_started/first_2d_game/04.creating_the_enemy.rst +++ b/getting_started/first_2d_game/04.creating_the_enemy.rst @@ -58,84 +58,23 @@ Enemy script Add a script to the ``Mob`` like this: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` extends RigidBody2D - - .. code-tab:: csharp - - public class Mob : RigidBody2D - { - // Don't forget to rebuild the project. - } - - .. code-tab:: cpp - - // Copy `player.gdns` to `mob.gdns` and replace `Player` with `Mob`. - // Attach the `mob.gdns` file to the Mob node. - - // Create two files `mob.cpp` and `mob.hpp` next to `entry.cpp` in `src`. - // This code goes in `mob.hpp`. We also define the methods we'll be using here. - #ifndef MOB_H - #define MOB_H - - #include - #include - #include - - class Mob : public godot::RigidBody2D { - GODOT_CLASS(Mob, godot::RigidBody2D) - - godot::AnimatedSprite *_animated_sprite; - - public: - void _init() {} - void _ready(); - void _on_VisibilityNotifier2D_screen_exited(); - - static void _register_methods(); - }; - - #endif // MOB_H +``` Now let's look at the rest of the script. In ``_ready()`` we play the animation and randomly choose one of the three animation types: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _ready(): $AnimatedSprite.playing = true var mob_types = $AnimatedSprite.frames.get_animation_names() $AnimatedSprite.animation = mob_types[randi() % mob_types.size()] - - .. code-tab:: csharp - - public override void _Ready() - { - var animSprite = GetNode("AnimatedSprite"); - animSprite.Playing = true; - string[] mobTypes = animSprite.Frames.GetAnimationNames(); - animSprite.Animation = mobTypes[GD.Randi() % mobTypes.Length]; - } - - .. code-tab:: cpp - - // This code goes in `mob.cpp`. - #include "mob.hpp" - - #include - #include - - void Mob::_ready() { - godot::Ref random = godot::RandomNumberGenerator::_new(); - random->randomize(); - _animated_sprite = get_node("AnimatedSprite"); - _animated_sprite->_set_playing(true); - godot::PoolStringArray mob_types = _animated_sprite->get_sprite_frames()->get_animation_names(); - _animated_sprite->set_animation(mob_types[random->randi() % mob_types.size()]); - } +``` First, we get the list of animation names from the AnimatedSprite's ``frames`` property. This returns an Array containing all three animation names: ``["walk", @@ -153,25 +92,12 @@ The last piece is to make the mobs delete themselves when they leave the screen. Connect the ``screen_exited()`` signal of the ``VisibilityNotifier2D`` node and add this code: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _on_VisibilityNotifier2D_screen_exited(): queue_free() - - .. code-tab:: csharp - - public void OnVisibilityNotifier2DScreenExited() - { - QueueFree(); - } - - .. code-tab:: cpp - - // This code goes in `mob.cpp`. - void Mob::_on_VisibilityNotifier2D_screen_exited() { - queue_free(); - } +``` This completes the `Mob` scene. diff --git a/getting_started/first_2d_game/05.the_main_game_scene.rst b/getting_started/first_2d_game/05.the_main_game_scene.rst index 8cc8264..ae12b9f 100644 --- a/getting_started/first_2d_game/05.the_main_game_scene.rst +++ b/getting_started/first_2d_game/05.the_main_game_scene.rst @@ -76,121 +76,24 @@ Main script Add a script to ``Main``. At the top of the script, we use ``export (PackedScene)`` to allow us to choose the Mob scene we want to instance. -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` extends Node export(PackedScene) var mob_scene var score - - .. code-tab:: csharp - - public class Main : Node - { - // Don't forget to rebuild the project so the editor knows about the new export variable. - - #pragma warning disable 649 - // We assign this in the editor, so we don't need the warning about not being assigned. - [Export] - public PackedScene MobScene; - #pragma warning restore 649 - - public int Score; - } - - .. code-tab:: cpp - - // Copy `player.gdns` to `main.gdns` and replace `Player` with `Main`. - // Attach the `main.gdns` file to the Main node. - - // Create two files `main.cpp` and `main.hpp` next to `entry.cpp` in `src`. - // This code goes in `main.hpp`. We also define the methods we'll be using here. - #ifndef MAIN_H - #define MAIN_H - - #include - #include - #include - #include - #include - #include - #include - #include - - #include "hud.hpp" - #include "player.hpp" - - class Main : public godot::Node { - GODOT_CLASS(Main, godot::Node) - - int score; - HUD *_hud; - Player *_player; - godot::Node2D *_start_position; - godot::PathFollow2D *_mob_spawn_location; - godot::Timer *_mob_timer; - godot::Timer *_score_timer; - godot::Timer *_start_timer; - godot::AudioStreamPlayer *_music; - godot::AudioStreamPlayer *_death_sound; - godot::Ref _random; - - public: - godot::Ref mob_scene; - - void _init() {} - void _ready(); - void game_over(); - void new_game(); - void _on_MobTimer_timeout(); - void _on_ScoreTimer_timeout(); - void _on_StartTimer_timeout(); - - static void _register_methods(); - }; - - #endif // MAIN_H +``` We also add a call to ``randomize()`` here so that the random number generator generates different random numbers each time the game is run: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _ready(): randomize() - - .. code-tab:: csharp - - public override void _Ready() - { - GD.Randomize(); - } - - .. code-tab:: cpp - - // This code goes in `main.cpp`. - #include "main.hpp" - - #include - - #include "mob.hpp" - - void Main::_ready() { - _hud = get_node("HUD"); - _player = get_node("Player"); - _start_position = get_node("StartPosition"); - _mob_spawn_location = get_node("MobPath/MobSpawnLocation"); - _mob_timer = get_node("MobTimer"); - _score_timer = get_node("ScoreTimer"); - _start_timer = get_node("StartTimer"); - // Uncomment these after adding the nodes in the "Sound effects" section of "Finishing up". - //_music = get_node("Music"); - //_death_sound = get_node("DeathSound"); - _random = (godot::Ref)godot::RandomNumberGenerator::_new(); - _random->randomize(); - } +``` Click the ``Main`` node and you will see the ``Mob Scene`` property in the Inspector under "Script Variables". @@ -213,9 +116,9 @@ signal connection dialog and click "Connect". Add the following code to the new function, as well as a ``new_game`` function that will set everything up for a new game: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func game_over(): $ScoreTimer.stop() $MobTimer.stop() @@ -224,89 +127,22 @@ new game: score = 0 $Player.start($StartPosition.position) $StartTimer.start() - - .. code-tab:: csharp - - public void GameOver() - { - GetNode("MobTimer").Stop(); - GetNode("ScoreTimer").Stop(); - } - - public void NewGame() - { - Score = 0; - - var player = GetNode("Player"); - var startPosition = GetNode("StartPosition"); - player.Start(startPosition.Position); - - GetNode("StartTimer").Start(); - } - - .. code-tab:: cpp - - // This code goes in `main.cpp`. - void Main::game_over() { - _score_timer->stop(); - _mob_timer->stop(); - } - - void Main::new_game() { - score = 0; - _player->start(_start_position->get_position()); - _start_timer->start(); - } +``` Now connect the ``timeout()`` signal of each of the Timer nodes (``StartTimer``, ``ScoreTimer`` , and ``MobTimer``) to the main script. ``StartTimer`` will start the other two timers. ``ScoreTimer`` will increment the score by 1. -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _on_ScoreTimer_timeout(): score += 1 func _on_StartTimer_timeout(): $MobTimer.start() $ScoreTimer.start() - - .. code-tab:: csharp - - public void OnScoreTimerTimeout() - { - Score++; - } - - public void OnStartTimerTimeout() - { - GetNode("MobTimer").Start(); - GetNode("ScoreTimer").Start(); - } - - .. code-tab:: cpp - - // This code goes in `main.cpp`. - void Main::_on_ScoreTimer_timeout() { - score += 1; - } - - void Main::_on_StartTimer_timeout() { - _mob_timer->start(); - _score_timer->start(); - } - - // Also add this to register all methods and the mob scene property. - void Main::_register_methods() { - godot::register_method("_ready", &Main::_ready); - godot::register_method("game_over", &Main::game_over); - godot::register_method("new_game", &Main::new_game); - godot::register_method("_on_MobTimer_timeout", &Main::_on_MobTimer_timeout); - godot::register_method("_on_ScoreTimer_timeout", &Main::_on_ScoreTimer_timeout); - godot::register_method("_on_StartTimer_timeout", &Main::_on_StartTimer_timeout); - godot::register_property("mob_scene", &Main::mob_scene, (godot::Ref)nullptr); - } +``` In ``_on_MobTimer_timeout()``, we will create a mob instance, pick a random starting location along the ``Path2D``, and set the mob in motion. The @@ -318,9 +154,9 @@ all moving at the same speed). Note that a new instance must be added to the scene using ``add_child()``. -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _on_MobTimer_timeout(): # Create a new instance of the Mob scene. var mob = mob_scene.instance() @@ -345,67 +181,7 @@ Note that a new instance must be added to the scene using ``add_child()``. # Spawn the mob by adding it to the Main scene. add_child(mob) - - .. code-tab:: csharp - - public void OnMobTimerTimeout() - { - // Note: Normally it is best to use explicit types rather than the `var` - // keyword. However, var is acceptable to use here because the types are - // obviously Mob and PathFollow2D, since they appear later on the line. - - // Create a new instance of the Mob scene. - var mob = (Mob)MobScene.Instance(); - - // Choose a random location on Path2D. - var mobSpawnLocation = GetNode("MobPath/MobSpawnLocation"); - mobSpawnLocation.Offset = GD.Randi(); - - // Set the mob's direction perpendicular to the path direction. - float direction = mobSpawnLocation.Rotation + Mathf.Pi / 2; - - // Set the mob's position to a random location. - mob.Position = mobSpawnLocation.Position; - - // Add some randomness to the direction. - direction += (float)GD.RandRange(-Mathf.Pi / 4, Mathf.Pi / 4); - mob.Rotation = direction; - - // Choose the velocity. - var velocity = new Vector2((float)GD.RandRange(150.0, 250.0), 0); - mob.LinearVelocity = velocity.Rotated(direction); - - // Spawn the mob by adding it to the Main scene. - AddChild(mob); - } - - .. code-tab:: cpp - - // This code goes in `main.cpp`. - void Main::_on_MobTimer_timeout() { - // Create a new instance of the Mob scene. - godot::Node *mob = mob_scene->instance(); - - // Choose a random location on Path2D. - _mob_spawn_location->set_offset((real_t)_random->randi()); - - // Set the mob's direction perpendicular to the path direction. - real_t direction = _mob_spawn_location->get_rotation() + (real_t)Math_PI / 2; - - // Set the mob's position to a random location. - mob->set("position", _mob_spawn_location->get_position()); - - // Add some randomness to the direction. - direction += _random->randf_range((real_t)-Math_PI / 4, (real_t)Math_PI / 4); - mob->set("rotation", direction); - - // Choose the velocity for the mob. - godot::Vector2 velocity = godot::Vector2(_random->randf_range(150.0, 250.0), 0.0); - mob->set("linear_velocity", velocity.rotated(direction)); - - // Spawn the mob by adding it to the Main scene. - add_child(mob); - } +``` .. important:: Why ``PI``? In functions requiring angles, Godot uses *radians*, not degrees. Pi represents a half turn in radians, about @@ -420,26 +196,13 @@ Testing the scene Let's test the scene to make sure everything is working. Add this ``new_game`` call to ``_ready()``: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func _ready(): randomize() new_game() - - .. code-tab:: csharp - - public override void _Ready() - { - NewGame(); - } - - .. code-tab:: cpp - - // This code goes in `main.cpp`. - void Main::_ready() { - new_game(); - } +``` Let's also assign ``Main`` as our "Main Scene" - the one that runs automatically when the game launches. Press the "Play" button and select ``Main.tscn`` when diff --git a/getting_started/first_2d_game/06.heads_up_display.rst b/getting_started/first_2d_game/06.heads_up_display.rst index 8e089f5..ca9d598 100644 --- a/getting_started/first_2d_game/06.heads_up_display.rst +++ b/getting_started/first_2d_game/06.heads_up_display.rst @@ -97,117 +97,32 @@ property to "On". Now add this script to ``HUD``: -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` extends CanvasLayer signal start_game - - .. code-tab:: csharp - - public class HUD : CanvasLayer - { - // Don't forget to rebuild the project so the editor knows about the new signal. - - [Signal] - public delegate void StartGame(); - } - - .. code-tab:: cpp - - // Copy `player.gdns` to `hud.gdns` and replace `Player` with `HUD`. - // Attach the `hud.gdns` file to the HUD node. - - // Create two files `hud.cpp` and `hud.hpp` next to `entry.cpp` in `src`. - // This code goes in `hud.hpp`. We also define the methods we'll be using here. - #ifndef HUD_H - #define HUD_H - - #include - #include - #include - #include - #include - - class HUD : public godot::CanvasLayer { - GODOT_CLASS(HUD, godot::CanvasLayer) - - godot::Label *_score_label; - godot::Label *_message_label; - godot::Timer *_start_message_timer; - godot::Timer *_get_ready_message_timer; - godot::Button *_start_button; - godot::Timer *_start_button_timer; - - public: - void _init() {} - void _ready(); - void show_get_ready(); - void show_game_over(); - void update_score(const int score); - void _on_StartButton_pressed(); - void _on_StartMessageTimer_timeout(); - void _on_GetReadyMessageTimer_timeout(); - - static void _register_methods(); - }; - - #endif // HUD_H +``` The ``start_game`` signal tells the ``Main`` node that the button has been pressed. -.. tabs:: - .. code-tab:: gdscript GDScript +gdscript GDScript +``` func show_message(text): $Message.text = text $Message.show() $MessageTimer.start() - - .. code-tab:: csharp - - public void ShowMessage(string text) - { - var message = GetNode