Skip to content

Add GDExtension C++ code snippets to GettingStarted #9821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions getting_started/step_by_step/scripting_first_script.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ The equivalent C# code has been included in another tab for convenience.

.. seealso:: To learn more about C#, head to the :ref:`C# basics <doc_c_sharp>` page.

.. seealso:: To learn more about GDExtension and godot-cpp, head to the :ref:`What is GDExtension? <doc_what_is_gdextension>` page.

Project setup
-------------

Expand Down Expand Up @@ -107,6 +109,35 @@ the following line of code:
{
}

.. code-tab:: cpp C++

#ifndef MY_SPRITE_2D_H
#define MY_SPRITE_2D_H

#include <godot_cpp/classes/sprite2d.hpp>

using namespace godot;

namespace CustomNamespace {

// MySprite2D also needs to be bound in your GDExtension's register_types.cpp file.
// More info on this in the GDExtension example setup tutorial.
class MySprite2D : public Sprite2D {
GDCLASS(MySprite2D, Sprite2D)

protected:
// _bind_methods is required for all GDCLASS's or compilation will fail!
static void _bind_methods() {}

public:
// Default constructor with no parameters is required or compilation will fail!
MySprite2D() {}
};

} // CustomNamespace

#endif // MY_SPRITE_2D_H

Every GDScript file is implicitly a class. The ``extends`` keyword defines the
class this script inherits or extends. In this case, it's ``Sprite2D``, meaning
our script will get access to all the properties and functions of the Sprite2D
Expand Down Expand Up @@ -150,6 +181,17 @@ Add the following code to your script:
GD.Print("Hello, world!");
}

.. code-tab:: cpp C++

// Add this include at the top of your header file.
#include <godot_cpp/variant/utility_functions.hpp>

// Add this inside your MySprite2D class.
public:
MySprite2D() {
UtilityFunctions::print("Hello, world!");
}


Let's break it down. The ``func`` keyword defines a new function named
``_init``. This is a special name for our class's constructor. The engine calls
Expand Down Expand Up @@ -188,6 +230,11 @@ angular speed in radians per second. Add the following after the ``extends Spri
private int _speed = 400;
private float _angularSpeed = Mathf.Pi;

.. code-tab:: cpp C++

int speed = 400;
float angular_speed = Math_PI;

Member variables sit near the top of the script, after any "extends" lines,
but before functions. Every node
instance with this script attached to it will have its own copy of the ``speed``
Expand Down Expand Up @@ -231,6 +278,13 @@ At the bottom of the script, define the function:
Rotation += _angularSpeed * (float)delta;
}

.. code-tab:: cpp C++

void _process(double p_delta) override {
// Note that properties (like rotation) are accessed via setters and getters in godot-cpp.
set_rotation(get_rotation() + angular_speed * p_delta);
}

The ``func`` keyword defines a new function. After it, we have to write the
function's name and arguments it takes in parentheses. A colon ends the
definition, and the indented blocks that follow are the function's content or
Expand Down Expand Up @@ -278,6 +332,14 @@ them.

Position += velocity * (float)delta;

.. code-tab:: cpp C++

// Note that the directional Vector2 constants do not exist in godot-cpp. So Vector2(0, -1) must be used.
Vector2 velocity = Vector2(0, -1).rotated(get_rotation()) * speed;

set_position(get_position() + velocity * p_delta);


As we already saw, the ``var`` keyword defines a new variable. If you put it at
the top of the script, it defines a property of the class. Inside a function, it
defines a local variable: it only exists within the function's scope.
Expand Down Expand Up @@ -343,3 +405,39 @@ Here is the complete ``sprite_2d.gd`` file for reference.
Position += velocity * (float)delta;
}
}

.. code-tab:: cpp C++

#ifndef MY_SPRITE_2D_H
#define MY_SPRITE_2D_H

#include <godot_cpp/classes/sprite2d.hpp>
#include <godot_cpp/core/math.hpp>

using namespace godot;

namespace CustomNamespace {

class MySprite2D : public Sprite2D {
GDCLASS(MySprite2D, Sprite2D)

int speed = 400;
float angular_speed = Math_PI;

protected:
static void _bind_methods() {}

public:
MySprite2D() {}

void _process(double p_delta) override {
set_rotation(get_rotation() + angular_speed * p_delta);

Vector2 velocity = Vector2(0, -1).rotated(get_rotation()) * speed;
set_position(get_position() + velocity * p_delta);
}
};

} // CustomNamespace

#endif // MY_SPRITE_2D_H
74 changes: 74 additions & 0 deletions getting_started/step_by_step/scripting_player_input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ code below.

Rotation += _angularSpeed * direction * (float)delta;

.. code-tab:: cpp C++

int direction = 0;
if (Input::get_singleton()->is_action_pressed("ui_left")) {
direction = -1;
}
if (Input::get_singleton()->is_action_pressed("ui_right")) {
direction = 1;
}

set_rotation(get_rotation() + angular_speed * direction * p_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
the left or the right arrow key. A value of ``1`` means the player wants to turn
Expand Down Expand Up @@ -95,6 +107,12 @@ Comment out the lines ``var velocity = Vector2.UP.rotated(rotation) * speed`` an

//Position += velocity * (float)delta;

.. code-tab:: cpp C++

//Vector2 velocity = Vector2(0, -1).rotated(get_rotation()) * speed;

//set_position(get_position() + velocity * p_delta);

This will ignore the code that moved the icon's position in a circle without user input from the previous exercise.

If you run the scene with this code, the icon should rotate when you press
Expand All @@ -121,6 +139,13 @@ velocity. Uncomment the code and replace the line starting with ``var velocity``
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}

.. code-tab:: cpp C++

Vector2 velocity = Vector2(0, 0);
if (Input::get_singleton()->is_action_pressed("ui_up")) {
velocity = Vector2(0, -1).rotated(get_rotation()) * speed;
}

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.

Expand Down Expand Up @@ -189,6 +214,55 @@ Here is the complete ``sprite_2d.gd`` file for reference.
}
}

.. code-tab:: cpp C++

#ifndef MY_SPRITE_2D_H
#define MY_SPRITE_2D_H

#include <godot_cpp/classes/input.hpp>
#include <godot_cpp/classes/sprite2d.hpp>
#include <godot_cpp/core/math.hpp>

using namespace godot;

namespace CustomNamespace {

class MySprite2D : public Sprite2D {
GDCLASS(MySprite2D, Sprite2D)

int speed = 400;
float angular_speed = Math_PI;

protected:
static void _bind_methods() {}

public:
MySprite2D() {}

void _process(double p_delta) override {
int direction = 0;
if (Input::get_singleton()->is_action_pressed("ui_left")) {
direction = -1;
}
if (Input::get_singleton()->is_action_pressed("ui_right")) {
direction = 1;
}

set_rotation(get_rotation() + angular_speed * p_delta);

Vector2 velocity = Vector2(0, 0);
if (Input::get_singleton()->is_action_pressed("ui_up")) {
velocity = Vector2(0, -1).rotated(get_rotation()) * speed;
}

set_position(get_position() + velocity * p_delta);
}
};

} //namespace CustomNamespace

#endif // MY_SPRITE_2D_H

If you run the scene, you should now be able to rotate with the left and right
arrow keys and move forward by pressing :kbd:`Up`.

Expand Down
2 changes: 2 additions & 0 deletions getting_started/step_by_step/signals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ what you can do with the Signal type directly.
observer pattern. You can learn more about it in
`Game Programming Patterns <https://gameprogrammingpatterns.com/observer.html>`__.

.. note:: Signals in godot-cpp are used in slightly different ways than GDScript or CSharp. To learn more head to the :ref:`GDExtension C++ example <doc_gdextension_cpp_signals_example>` page.

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.

Expand Down
2 changes: 2 additions & 0 deletions tutorials/scripting/gdextension/gdextension_cpp_example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,8 @@ The first two arguments are the minimum and maximum value and the third is the s
There are a lot more options to choose from. These can be used to
further configure how properties are displayed and set on the Godot side.

.. _doc_gdextension_cpp_signals_example:

Signals
-------

Expand Down
Loading