From ac86f148ba9e02ac8e17c2184ca06c18a7d0fe4f Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Sat, 9 Apr 2022 22:16:27 -0400 Subject: [PATCH 1/8] merge develop --- godot/Main.tscn | 6 ++++++ godot/characters/player/Player.tscn | 20 ++++++++++++++++---- src/godot.cpp | 10 ++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/godot/Main.tscn b/godot/Main.tscn index d264a5c..9d1190c 100644 --- a/godot/Main.tscn +++ b/godot/Main.tscn @@ -7,3 +7,9 @@ script = ExtResource( 1 ) [node name="Level1" parent="." instance=ExtResource( 2 )] + +[node name="StateMachine" type="Node" parent="."] + +[node name="Walk" type="Node" parent="StateMachine"] + +[node name="Run" type="Node" parent="StateMachine"] diff --git a/godot/characters/player/Player.tscn b/godot/characters/player/Player.tscn index dde73e1..b8ef56b 100644 --- a/godot/characters/player/Player.tscn +++ b/godot/characters/player/Player.tscn @@ -1,13 +1,14 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://characters/player/sprites/green.tres" type="SpriteFrames" id=1] -[ext_resource path="res://characters/player/Player.gdns" type="Script" id=2] +[ext_resource path="res://characters/player/states/Idle.gdns" type="Script" id=2] +[ext_resource path="res://characters/player/Player.gdns" type="Script" id=3] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 7, 11.5 ) [node name="Player" type="KinematicBody2D"] -script = ExtResource( 2 ) +script = ExtResource( 3 ) [node name="AnimatedSprite" type="AnimatedSprite" parent="."] frames = ExtResource( 1 ) @@ -18,4 +19,15 @@ centered = false position = Vector2( 12, 12.5 ) shape = SubResource( 1 ) -[connection signal="player_moved" from="." to="." method="_on_Player_player_moved"] +[node name="StateMachine" type="Node" parent="."] + +[node name="Idle" type="Node" parent="StateMachine"] +script = ExtResource( 2 ) + +[node name="Move" type="Node" parent="StateMachine"] + +[node name="Jump" type="Node" parent="StateMachine"] + +[node name="DoubleJump" type="Node" parent="StateMachine"] + +[node name="Fall" type="Node" parent="StateMachine"] diff --git a/src/godot.cpp b/src/godot.cpp index 4389706..d8f50b7 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -1,7 +1,12 @@ #include +#include "StateMachine.h" +#include "State.h" +#include "Walk.h" +#include "Run.h" #include "Main.h" #include "Player.h" +#include "PlayerIdle.h" using namespace godot; @@ -21,6 +26,11 @@ extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_opt extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) { Godot::nativescript_init(handle); + register_class(); + register_class(); + register_class(); + register_class(); register_class
(); register_class(); + register_class(); } -- 2.30.2 From 8f76f9a2c9144567a77014ec2f0cb131c1946dfa Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Sat, 9 Apr 2022 22:20:02 -0400 Subject: [PATCH 2/8] move player code --- src/{ => player}/Player.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{ => player}/Player.cpp (100%) diff --git a/src/Player.cpp b/src/player/Player.cpp similarity index 100% rename from src/Player.cpp rename to src/player/Player.cpp -- 2.30.2 From 35af76cda4ee0f0fe1d44954c9c0d2f7cedd6d44 Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Sat, 9 Apr 2022 22:21:04 -0400 Subject: [PATCH 3/8] detatch script --- godot/characters/player/Player.tscn | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/godot/characters/player/Player.tscn b/godot/characters/player/Player.tscn index b8ef56b..b5643c5 100644 --- a/godot/characters/player/Player.tscn +++ b/godot/characters/player/Player.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://characters/player/sprites/green.tres" type="SpriteFrames" id=1] -[ext_resource path="res://characters/player/states/Idle.gdns" type="Script" id=2] [ext_resource path="res://characters/player/Player.gdns" type="Script" id=3] [sub_resource type="RectangleShape2D" id=1] @@ -22,7 +21,6 @@ shape = SubResource( 1 ) [node name="StateMachine" type="Node" parent="."] [node name="Idle" type="Node" parent="StateMachine"] -script = ExtResource( 2 ) [node name="Move" type="Node" parent="StateMachine"] -- 2.30.2 From 6d2d1178a74c67106bd06ca317a9526e9487b57f Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Sun, 10 Apr 2022 09:43:33 -0400 Subject: [PATCH 4/8] remove include directory --- SConstruct | 3 ++- src/{include => }/Main.h | 0 src/{include => player}/Player.h | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename src/{include => }/Main.h (100%) rename src/{include => player}/Player.h (100%) diff --git a/SConstruct b/SConstruct index d6aa482..a17df99 100644 --- a/SConstruct +++ b/SConstruct @@ -63,6 +63,7 @@ if env['platform'] == 'linux': env.Append(CCFLAGS=['-g3', '-Og']) else: env.Append(CCFLAGS=['-g', '-O3']) + env.Append(CPPDEFINES=['NDEBUG']) env.Append(CCFLAGS=['-m64']) env.Append(LINKFLAGS=['-m64']) @@ -109,7 +110,7 @@ else: cpp_library += '.' + str(env['bits']) # make sure our binding library is properly includes -env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/', 'src/include/', 'lib/include']) +env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/']) env.Append(LIBPATH=[cpp_bindings_path + 'bin/']) env.Append(LIBS=[cpp_library]) diff --git a/src/include/Main.h b/src/Main.h similarity index 100% rename from src/include/Main.h rename to src/Main.h diff --git a/src/include/Player.h b/src/player/Player.h similarity index 100% rename from src/include/Player.h rename to src/player/Player.h -- 2.30.2 From ecd6fe45b2aecc976c907377d6c56d8df8bce7e2 Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Mon, 11 Apr 2022 13:30:51 -0400 Subject: [PATCH 5/8] add state machine and have player use it --- godot/Main.gdns | 2 +- godot/Main.tscn | 6 - godot/characters/player/Player.gdns | 9 +- godot/characters/player/Player.tscn | 23 +- godot/characters/player/states/Fall.gdns | 8 + godot/characters/player/states/Idle.gdns | 8 + godot/characters/player/states/Jump.gdns | 8 + godot/characters/player/states/Move.gdns | 8 + godot/gdnative/{libalai.tres => alai.tres} | 0 godot/state_machine/State.gdns | 8 + godot/state_machine/StateMachine.gdns | 8 + src/Main.cpp | 20 +- src/Main.h | 214 +++++++------ src/godot.cpp | 24 +- src/player/Player.cpp | 118 ++------ src/player/Player.h | 330 ++++++++++----------- src/player/states/PlayerFall.cpp | 78 +++++ src/player/states/PlayerFall.h | 44 +++ src/player/states/PlayerIdle.cpp | 65 ++++ src/player/states/PlayerIdle.h | 45 +++ src/player/states/PlayerJump.cpp | 105 +++++++ src/player/states/PlayerJump.h | 45 +++ src/player/states/PlayerMove.cpp | 94 ++++++ src/player/states/PlayerMove.h | 46 +++ src/state_machine/State.cpp | 54 ++++ src/state_machine/State.h | 46 +++ src/state_machine/StateMachine.cpp | 208 +++++++++++++ src/state_machine/StateMachine.h | 95 ++++++ 28 files changed, 1303 insertions(+), 416 deletions(-) create mode 100644 godot/characters/player/states/Fall.gdns create mode 100644 godot/characters/player/states/Idle.gdns create mode 100644 godot/characters/player/states/Jump.gdns create mode 100644 godot/characters/player/states/Move.gdns rename godot/gdnative/{libalai.tres => alai.tres} (100%) create mode 100644 godot/state_machine/State.gdns create mode 100644 godot/state_machine/StateMachine.gdns create mode 100644 src/player/states/PlayerFall.cpp create mode 100644 src/player/states/PlayerFall.h create mode 100644 src/player/states/PlayerIdle.cpp create mode 100644 src/player/states/PlayerIdle.h create mode 100644 src/player/states/PlayerJump.cpp create mode 100644 src/player/states/PlayerJump.h create mode 100644 src/player/states/PlayerMove.cpp create mode 100644 src/player/states/PlayerMove.h create mode 100644 src/state_machine/State.cpp create mode 100644 src/state_machine/State.h create mode 100644 src/state_machine/StateMachine.cpp create mode 100644 src/state_machine/StateMachine.h diff --git a/godot/Main.gdns b/godot/Main.gdns index 764a788..524516e 100644 --- a/godot/Main.gdns +++ b/godot/Main.gdns @@ -1,6 +1,6 @@ [gd_resource type="NativeScript" load_steps=2 format=2] -[ext_resource path="res://gdnative/libalai.tres" type="GDNativeLibrary" id=1] +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] [resource] resource_name = "Main" diff --git a/godot/Main.tscn b/godot/Main.tscn index 9d1190c..d264a5c 100644 --- a/godot/Main.tscn +++ b/godot/Main.tscn @@ -7,9 +7,3 @@ script = ExtResource( 1 ) [node name="Level1" parent="." instance=ExtResource( 2 )] - -[node name="StateMachine" type="Node" parent="."] - -[node name="Walk" type="Node" parent="StateMachine"] - -[node name="Run" type="Node" parent="StateMachine"] diff --git a/godot/characters/player/Player.gdns b/godot/characters/player/Player.gdns index 40af8ae..4553176 100644 --- a/godot/characters/player/Player.gdns +++ b/godot/characters/player/Player.gdns @@ -1,8 +1,13 @@ [gd_resource type="NativeScript" load_steps=2 format=2] -[ext_resource path="res://gdnative/libalai.tres" type="GDNativeLibrary" id=1] +[sub_resource type="GDNativeLibrary" id=1] +symbol_prefix = "godot_player" +entry/Windows.64 = "res://gdnative/windows.64/libalai.dll" +entry/X11.64 = "res://gdnative/linux.64/libalai.so" +dependency/Windows.64 = [ ] +dependency/X11.64 = [ ] [resource] resource_name = "Player" class_name = "Player" -library = ExtResource( 1 ) +library = SubResource( 1 ) diff --git a/godot/characters/player/Player.tscn b/godot/characters/player/Player.tscn index b5643c5..fd71fe2 100644 --- a/godot/characters/player/Player.tscn +++ b/godot/characters/player/Player.tscn @@ -1,13 +1,18 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=9 format=2] [ext_resource path="res://characters/player/sprites/green.tres" type="SpriteFrames" id=1] -[ext_resource path="res://characters/player/Player.gdns" type="Script" id=3] +[ext_resource path="res://characters/player/states/Idle.gdns" type="Script" id=2] +[ext_resource path="res://state_machine/StateMachine.gdns" type="Script" id=3] +[ext_resource path="res://characters/player/states/Move.gdns" type="Script" id=4] +[ext_resource path="res://characters/player/Player.gdns" type="Script" id=5] +[ext_resource path="res://characters/player/states/Jump.gdns" type="Script" id=6] +[ext_resource path="res://characters/player/states/Fall.gdns" type="Script" id=7] [sub_resource type="RectangleShape2D" id=1] -extents = Vector2( 7, 11.5 ) +extents = Vector2( 7, 12 ) [node name="Player" type="KinematicBody2D"] -script = ExtResource( 3 ) +script = ExtResource( 5 ) [node name="AnimatedSprite" type="AnimatedSprite" parent="."] frames = ExtResource( 1 ) @@ -15,17 +20,21 @@ animation = "idle" centered = false [node name="CollisionShape2D" type="CollisionShape2D" parent="."] -position = Vector2( 12, 12.5 ) +position = Vector2( 12, 12 ) shape = SubResource( 1 ) [node name="StateMachine" type="Node" parent="."] +script = ExtResource( 3 ) +default_state = "Idle" [node name="Idle" type="Node" parent="StateMachine"] +script = ExtResource( 2 ) [node name="Move" type="Node" parent="StateMachine"] +script = ExtResource( 4 ) [node name="Jump" type="Node" parent="StateMachine"] - -[node name="DoubleJump" type="Node" parent="StateMachine"] +script = ExtResource( 6 ) [node name="Fall" type="Node" parent="StateMachine"] +script = ExtResource( 7 ) diff --git a/godot/characters/player/states/Fall.gdns b/godot/characters/player/states/Fall.gdns new file mode 100644 index 0000000..520e3af --- /dev/null +++ b/godot/characters/player/states/Fall.gdns @@ -0,0 +1,8 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] + +[resource] +resource_name = "PlayerFall" +class_name = "PlayerFall" +library = ExtResource( 1 ) diff --git a/godot/characters/player/states/Idle.gdns b/godot/characters/player/states/Idle.gdns new file mode 100644 index 0000000..4e5fb7d --- /dev/null +++ b/godot/characters/player/states/Idle.gdns @@ -0,0 +1,8 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] + +[resource] +resource_name = "PlayerIdle" +class_name = "PlayerIdle" +library = ExtResource( 1 ) diff --git a/godot/characters/player/states/Jump.gdns b/godot/characters/player/states/Jump.gdns new file mode 100644 index 0000000..915bbca --- /dev/null +++ b/godot/characters/player/states/Jump.gdns @@ -0,0 +1,8 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] + +[resource] +resource_name = "PlayerJump" +class_name = "PlayerJump" +library = ExtResource( 1 ) diff --git a/godot/characters/player/states/Move.gdns b/godot/characters/player/states/Move.gdns new file mode 100644 index 0000000..5b43556 --- /dev/null +++ b/godot/characters/player/states/Move.gdns @@ -0,0 +1,8 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] + +[resource] +resource_name = "PlayerMove" +class_name = "PlayerMove" +library = ExtResource( 1 ) diff --git a/godot/gdnative/libalai.tres b/godot/gdnative/alai.tres similarity index 100% rename from godot/gdnative/libalai.tres rename to godot/gdnative/alai.tres diff --git a/godot/state_machine/State.gdns b/godot/state_machine/State.gdns new file mode 100644 index 0000000..dad8e97 --- /dev/null +++ b/godot/state_machine/State.gdns @@ -0,0 +1,8 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdnative/libalai.tres" type="GDNativeLibrary" id=1] + +[resource] +resource_name = "State" +class_name = "State" +library = ExtResource( 1 ) diff --git a/godot/state_machine/StateMachine.gdns b/godot/state_machine/StateMachine.gdns new file mode 100644 index 0000000..77bc502 --- /dev/null +++ b/godot/state_machine/StateMachine.gdns @@ -0,0 +1,8 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] + +[resource] +resource_name = "StateMachine" +class_name = "StateMachine" +library = ExtResource( 1 ) diff --git a/src/Main.cpp b/src/Main.cpp index 315bf3b..ef0fe55 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -3,14 +3,15 @@ #include using namespace godot; +using namespace main; void Main::_register_methods() { register_method("_ready", &Main::_ready); register_method("_physics_process", &Main::_physics_process); - register_property("full_screen", &Main::set_full_screen, &Main::get_full_screen, ALAI_MAIN_FULL_SCREEN); - register_property("window_size", &Main::set_window_size, &Main::get_window_size, ALAI_MAIN_WINDOW_SIZE); - register_property("launch_screen", &Main::set_launch_screen, &Main::get_launch_screen, ALAI_MAIN_LAUNCH_SCREEN); + register_property("full_screen", &Main::set_full_screen, &Main::get_full_screen, main::full_screen); + register_property("window_size", &Main::set_window_size, &Main::get_window_size, main::window_size); + register_property("launch_screen", &Main::set_launch_screen, &Main::get_launch_screen, main::launch_screen); } Main::Main() @@ -26,9 +27,9 @@ void Main::_init() _os = OS::get_singleton(); _input = Input::get_singleton(); - full_screen = ALAI_MAIN_FULL_SCREEN; - window_size = ALAI_MAIN_WINDOW_SIZE; - launch_screen = ALAI_MAIN_LAUNCH_SCREEN; + full_screen = main::full_screen; + window_size = main::window_size; + launch_screen = main::launch_screen; } void Main::_ready() @@ -39,17 +40,10 @@ void Main::_ready() } else { - String resolution = String("Resolution before: " + String().num(_os->get_window_size().x) + "x" + String().num(_os->get_window_size().y)); - Godot::print(resolution); - _os->set_window_size(window_size); _os->set_window_position( _os->get_screen_position(get_launch_screen()) + _os->get_screen_size() * 0.5 - _os->get_window_size() * 0.5 ); - - resolution = String("Resolution after: " + String().num(_os->get_window_size().x) + "x" + String().num(_os->get_window_size().y)); - - Godot::print(resolution); } } diff --git a/src/Main.h b/src/Main.h index 71c9253..3a65398 100644 --- a/src/Main.h +++ b/src/Main.h @@ -6,138 +6,130 @@ #include #include -/** - * @brief If the game should be full screen or not by default. - */ -#define ALAI_MAIN_FULL_SCREEN false -/** - * @brief The default size of the window. - * @details This is ignored if full screen is true. - */ -#define ALAI_MAIN_WINDOW_SIZE Vector2(1280, 720) -/** - * @brief Which screen to launch the game on. - * @details If -1 it will launch the game on the "active" screen. Anything between 0 and N represents the screen number to show the game on when opened. - */ -#define ALAI_MAIN_LAUNCH_SCREEN -1 - /** * @brief This is the godot namespace for all the code included in the library. * @details This namespace is used a prefix when the Godot engine looks for classes, methods, and properties. */ namespace godot { - /** - * @brief This class controls the Main node. - * @details The main node is responsible for controling the window and the game iteself is a child of it. - */ - class Main : public Node + namespace main { - GODOT_CLASS(Main, Node) + const bool full_screen = false; + const Vector2 window_size = Vector2(1280, 720); + const int8_t launch_screen = -1; - private: - /** - * @brief OS singleton. - */ - OS *_os; - /** - * @brief Input singleton. - */ - Input *_input; + /** + * @brief This class controls the Main node. + * @details The main node is responsible for controling the window and the game iteself is a child of it. + */ + class Main : public Node + { + GODOT_CLASS(Main, Node) - /** - * @brief If the window is full screen or not. - */ - bool full_screen; - /** - * @brief The size of the window. - */ - Vector2 window_size; - /** - * @brief The screen to launch the game on. - */ - int8_t launch_screen; + private: + /** + * @brief OS singleton. + */ + OS *_os; + /** + * @brief Input singleton. + */ + Input *_input; - public: - /** - * @brief This method registers classes with Godot. - * @details This method registers methods, properties, and signals with the Godot engine. - */ - static void _register_methods(); + /** + * @brief If the window is full screen or not. + */ + bool full_screen; + /** + * @brief The size of the window. + */ + Vector2 window_size; + /** + * @brief The screen to launch the game on. + */ + int8_t launch_screen; - /** - * @brief Construct a new Main object. - */ - Main(); + public: + /** + * @brief This method registers classes with Godot. + * @details This method registers methods, properties, and signals with the Godot engine. + */ + static void _register_methods(); - /** - * @brief Destroy the Main object. - */ - ~Main(); + /** + * @brief Construct a new Main object. + */ + Main(); - /** - * @brief Initialize the class from Godot. - * @details This method is called just once when the Godot engine connects to the instance of the class. - */ - void _init(); + /** + * @brief Destroy the Main object. + */ + ~Main(); - /** - * @brief Code to be run when ready. - * @details This method is run when all the children of this node are ready. - */ - void _ready(); + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); - /** - * @brief This class handles the physics processing. - * @details Every delta time, this function is called to check for input and update positioning. - * - * @param[in] delta The difference in time that passed since the last call to this method. - */ - void _physics_process(float delta); + /** + * @brief Code to be run when ready. + * @details This method is run when all the children of this node are ready. + */ + void _ready(); - /** - * @brief Set the full screen object. - * - * @param[in] new_full_screen The new full screen state. - */ - void set_full_screen(bool new_full_screen); + /** + * @brief This class handles the physics processing. + * @details Every delta time, this function is called to check for input and update positioning. + * + * @param[in] delta The difference in time that passed since the last call to this method. + */ + void _physics_process(float delta); - /** - * @brief Get the full screen object. - * - * @return true If full screen. - * @return false If not full screen. - */ - bool get_full_screen(); + /** + * @brief Set the full screen object. + * + * @param[in] new_full_screen The new full screen state. + */ + void set_full_screen(bool new_full_screen); - /** - * @brief Set the window size object. - * - * @param[in] new_window_size The new window size. - */ - void set_window_size(Vector2 new_window_size); + /** + * @brief Get the full screen object. + * + * @return true If full screen. + * @return false If not full screen. + */ + bool get_full_screen(); - /** - * @brief Get the window size object. - * - * @return Vector2 The window size. - */ - Vector2 get_window_size(); + /** + * @brief Set the window size object. + * + * @param[in] new_window_size The new window size. + */ + void set_window_size(Vector2 new_window_size); - /** - * @brief Set the launch screen object. - * - * @param[in] new_launch_screen The launch screen to use. - */ - void set_launch_screen(int8_t new_launch_screen); + /** + * @brief Get the window size object. + * + * @return Vector2 The window size. + */ + Vector2 get_window_size(); - /** - * @brief Get the launch screen object. - * - * @return int8_t The launch screen. - */ - int8_t get_launch_screen(); - }; + /** + * @brief Set the launch screen object. + * + * @param[in] new_launch_screen The launch screen to use. + */ + void set_launch_screen(int8_t new_launch_screen); + + /** + * @brief Get the launch screen object. + * + * @return int8_t The launch screen. + */ + int8_t get_launch_screen(); + }; + } } #endif diff --git a/src/godot.cpp b/src/godot.cpp index d8f50b7..b449e46 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -1,12 +1,13 @@ #include -#include "StateMachine.h" -#include "State.h" -#include "Walk.h" -#include "Run.h" +#include "state_machine/StateMachine.h" +#include "state_machine/State.h" #include "Main.h" -#include "Player.h" -#include "PlayerIdle.h" +#include "player/Player.h" +#include "player/states/PlayerIdle.h" +#include "player/states/PlayerMove.h" +#include "player/states/PlayerJump.h" +#include "player/states/PlayerFall.h" using namespace godot; @@ -28,9 +29,10 @@ extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) Godot::nativescript_init(handle); register_class(); register_class(); - register_class(); - register_class(); - register_class
(); - register_class(); - register_class(); + register_class(); + register_class(); + register_class(); + register_class(); + register_class(); + register_class(); } diff --git a/src/player/Player.cpp b/src/player/Player.cpp index 0b0e0fe..30c801d 100644 --- a/src/player/Player.cpp +++ b/src/player/Player.cpp @@ -7,18 +7,20 @@ #include using namespace godot; +using namespace player; void Player::_register_methods() { register_method("_ready", &Player::_ready); register_method("_physics_process", &Player::_physics_process); - register_method("_on_Player_player_moved", &Player::_on_Player_player_moved); + register_method("set_velocity", &Player::set_velocity); + register_method("get_velocity", &Player::get_velocity); //register_property>("sprite_frames", &Player::set_sprite_frames, &Player::get_sprite_frames, Ref(), GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RESOURCE_TYPE, String("SpriteFrames")); - register_property("speed", &Player::set_speed, &Player::get_speed, ALAI_PLAYER_SPEED); - register_property("jump_force", &Player::set_jump_force, &Player::get_jump_force, ALAI_PLAYER_JUMP_FORCE); - register_property("gravity", &Player::set_gravity, &Player::get_gravity, ALAI_PLAYER_GRAVITY); - register_property("run_speed", &Player::set_run_speed, &Player::get_run_speed, ALAI_PLAYER_RUN_SPEED); - register_signal("player_moved", "position", GODOT_VARIANT_TYPE_VECTOR2); + register_property("speed", &Player::set_speed, &Player::get_speed, player::speed); + register_property("jump_force", &Player::set_jump_force, &Player::get_jump_force, player::jump_force); + register_property("gravity", &Player::set_gravity, &Player::get_gravity, player::gravity); + register_property("run_speed", &Player::set_run_speed, &Player::get_run_speed, player::run_speed); + register_property("double_jump", &Player::set_double_jump, &Player::get_double_jump, player::double_jump); } Player::Player() @@ -31,21 +33,18 @@ Player::~Player() void Player::_init() { - _os = OS::get_singleton(); - _input = Input::get_singleton(); _resource_loader = ResourceLoader::get_singleton(); - //sprite_frames = _resource_loader->load(ALAI_PLAYER_SPRITE_FRAMES); - set_speed(ALAI_PLAYER_SPEED); - set_jump_force(ALAI_PLAYER_JUMP_FORCE); - set_gravity(ALAI_PLAYER_GRAVITY); - set_run_speed(ALAI_PLAYER_RUN_SPEED); + //sprite_frames = _resource_loader->load(player::sprite_frames); + set_speed(player::speed); + set_jump_force(player::jump_force); + set_gravity(player::gravity); + set_run_speed(player::run_speed); + set_double_jump(player::double_jump); coins = 0; velocity = Vector2(); - - jumping = 0; } void Player::_ready() @@ -53,7 +52,7 @@ void Player::_ready() animated_sprite = get_node("AnimatedSprite"); if (!animated_sprite) { - WARN_PRINT("AnimateSprite not found!"); + ERR_PRINT("AnimateSprite not found!"); animated_sprite = AnimatedSprite()._new(); } //animated_sprite->set_sprite_frames(sprite_frames); @@ -74,74 +73,7 @@ void Player::_ready() void Player::_physics_process(float delta) { - auto current_speed = get_speed(); - velocity.x = 0; - if (_input->is_action_pressed("run")) - { - current_speed *= get_run_speed(); - } - - if (_input->is_action_pressed("right")) - { - velocity.x += current_speed; - } - - if (_input->is_action_pressed("left")) - { - velocity.x += -current_speed; - } - - if (velocity.x > 0) - { - animated_sprite->play("move"); - animated_sprite->set_flip_h(true); - } - else if (velocity.x < 0) - { - animated_sprite->play("move"); - animated_sprite->set_flip_h(false); - } - else - { - animated_sprite->stop(); - animated_sprite->set_animation("idle"); - } - - if (jumping > 0 && is_on_floor()) - { - animated_sprite->set_frame(1); - jumping = 0; - } - - if (!is_on_floor()) - { - animated_sprite->stop(); - animated_sprite->set_animation("air"); - if (jumping == 0) - { - jumping = 2; - } - } - velocity.y += get_gravity(); - if (_input->is_action_just_pressed("jump") && jumping < 2) - { - velocity.y = -get_jump_force(); - jumping++; - } - - if (_input->is_action_just_released("jump")) - { - if (velocity.y < -100) - { - velocity.y = -100; - } - } - - if (velocity.x < 0 || velocity.x > 0) - { - //emit_signal("player_moved", get_position()); - } velocity = move_and_slide(velocity, Vector2::UP, true); velocity.x = Math::lerp((float) velocity.x, (float) 0, (float) 0.2); @@ -170,7 +102,6 @@ void Player::_physics_process(float delta) { if (get_parent()->get_class() == "TileMap") { - Godot::print("Off screen"); auto error = get_tree()->change_scene("res://Main.tscn"); if (error != Error::OK) { @@ -231,7 +162,22 @@ float Player::get_run_speed() return run_speed; } -void Player::_on_Player_player_moved(Vector2 position) +void Player::set_double_jump(bool double_jump) { - Godot::print(position); + this->double_jump = double_jump; +} + +bool Player::get_double_jump() +{ + return this->double_jump; +} + +void Player::set_velocity(Vector2 velocity) +{ + this->velocity = velocity; +} + +Vector2 Player::get_velocity() +{ + return this->velocity; } diff --git a/src/player/Player.h b/src/player/Player.h index aca9b16..67ff8c4 100644 --- a/src/player/Player.h +++ b/src/player/Player.h @@ -1,37 +1,12 @@ #ifndef ALAI_PLAYER_H #define ALAI_PLAYER_H -/** - * @brief This resource is loaded by default for the AnimatedSprite node. - */ -#define ALAI_PLAYER_SPRITE_FRAMES "res://characters/player/sprites/green.tres" -/** - * @brief The speed the player should move it. - */ -#define ALAI_PLAYER_SPEED 60.0 -/** - * @brief The force applied to the player when jumping. - */ -#define ALAI_PLAYER_JUMP_FORCE 300.0 -/** - * @brief The gravity applied to the player. - */ -#define ALAI_PLAYER_GRAVITY 9.81 -/** - * @brief The multiplier used to change the speed of the player when running. - */ -#define ALAI_PLAYER_RUN_SPEED 2.0 - #include #include -#include #include -#include -#include #include #include #include -#include /** * @brief This is the godot namespace for all the code included in the library. @@ -39,181 +14,178 @@ */ namespace godot { - /** - * @brief This class is used to control the player. - * @details This class allows the player to move, run, and jump as well as controls the sprite displayed for those actions. - */ - class Player : public KinematicBody2D + namespace player { - GODOT_CLASS(Player, KinematicBody2D) + const char player_sprite_frames[] = "res://characters/player/sprites/green.tres"; + const float speed = 60.0; + const float jump_force = 300.0; + const float gravity = 9.81; + const float run_speed = 2.0; + const bool double_jump = true; - private: - /** - * @brief OS singleton. - */ - OS *_os; - /** - * @brief Input singleton. - */ - Input *_input; - /** - * @brief ResourceLoader singleton. - */ - ResourceLoader *_resource_loader; + /** + * @brief This class is used to control the player. + * @details This class allows the player to move, run, and jump as well as controls the sprite displayed for those actions. + */ + class Player : public KinematicBody2D + { + GODOT_CLASS(Player, KinematicBody2D) - /** - * @brief The animated sprite connected to the KinematicBody2D. - */ - AnimatedSprite *animated_sprite; - /** - * @brief The sprite frames used in the animated sprite. - */ - Ref sprite_frames; - /** - * @brief The coins the player has collected. - */ - uint8_t coins; - /** - * @brief The velocity at which moves the player moves. - */ - Vector2 velocity; - /** - * @brief The speed that the player moves in. - */ - float speed; - /** - * @brief The force applied to the player when jumping. - */ - float jump_force; - /** - * @brief The gravity applied to the player. - */ - float gravity; - /** - * @brief The speed multiplier used to make the player move faster. - */ - float run_speed; + private: + /** + * @brief ResourceLoader singleton. + */ + ResourceLoader *_resource_loader; - /** - * @brief State of jumping of the player. To be replaced with a state machine in the future. - */ - uint8_t jumping; + /** + * @brief The animated sprite connected to the KinematicBody2D. + */ + AnimatedSprite *animated_sprite; + /** + * @brief The sprite frames used in the animated sprite. + */ + Ref sprite_frames; + /** + * @brief The coins the player has collected. + */ + uint8_t coins; + /** + * @brief The velocity at which moves the player moves. + */ + Vector2 velocity; + /** + * @brief The speed that the player moves in. + */ + float speed; + /** + * @brief The force applied to the player when jumping. + */ + float jump_force; + /** + * @brief The gravity applied to the player. + */ + float gravity; + /** + * @brief The speed multiplier used to make the player move faster. + */ + float run_speed; - public: - /** - * @brief This method registers classes with Godot. - * @details This method registers methods, properties, and signals with the Godot engine. - */ - static void _register_methods(); + bool double_jump; - /** - * @brief Construct a new Player object. - */ - Player(); + public: + /** + * @brief This method registers classes with Godot. + * @details This method registers methods, properties, and signals with the Godot engine. + */ + static void _register_methods(); - /** - * @brief Destroy the Player object. - */ - ~Player(); + /** + * @brief Construct a new Player object. + */ + Player(); - /** - * @brief Initialize the class from Godot. - * @details This method is called just once when the Godot engine connects to the instance of the class. - */ - void _init(); + /** + * @brief Destroy the Player object. + */ + ~Player(); - /** - * @brief Code to be run when ready. - * @details This method is run when all the children of this node are ready. - */ - void _ready(); + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); - /** - * @brief This class handles the physics processing. - * @details Every delta time, this function is called to check for input and update positioning. - * - * @param[in] delta The difference in time that passed since the last call to this method. - */ - void _physics_process(float delta); + /** + * @brief Code to be run when ready. + * @details This method is run when all the children of this node are ready. + */ + void _ready(); - /** - * @brief Set the sprite frames object. - * - * @param[in] new_sprite_frames The new sprite frame. - */ - void set_sprite_frames(Ref new_sprite_frames); + /** + * @brief This class handles the physics processing. + * @details Every delta time, this function is called to check for input and update positioning. + * + * @param[in] delta The difference in time that passed since the last call to this method. + */ + void _physics_process(float delta); - /** - * @brief Get the sprite frames object. - * - * @return Ref A reference to the sprite frames object. - */ - Ref get_sprite_frames(); + /** + * @brief Set the sprite frames object. + * + * @param[in] new_sprite_frames The new sprite frame. + */ + void set_sprite_frames(Ref new_sprite_frames); - /** - * @brief Set the speed object. - * - * @param[in] new_speed The new speed. - */ - void set_speed(float new_speed); + /** + * @brief Get the sprite frames object. + * + * @return Ref A reference to the sprite frames object. + */ + Ref get_sprite_frames(); - /** - * @brief Get the speed object. - * - * @return float The current speed of the player. - */ - float get_speed(); + /** + * @brief Set the speed object. + * + * @param[in] new_speed The new speed. + */ + void set_speed(float new_speed); - /** - * @brief Set the jump force object. - * - * @param[in] new_jump_force The new force applied to the player to make him jump. - */ - void set_jump_force(float new_jump_force); + /** + * @brief Get the speed object. + * + * @return float The current speed of the player. + */ + float get_speed(); - /** - * @brief Get the jump force object. - * - * @return float The current force being applied to the player. - */ - float get_jump_force(); + /** + * @brief Set the jump force object. + * + * @param[in] new_jump_force The new force applied to the player to make him jump. + */ + void set_jump_force(float new_jump_force); - /** - * @brief Set the gravity object. - * - * @param[in] new_gravity The new gravity to apply to the player. - */ - void set_gravity(float new_gravity); + /** + * @brief Get the jump force object. + * + * @return float The current force being applied to the player. + */ + float get_jump_force(); - /** - * @brief Get the gravity object. - * - * @return float The current gravity applied to the player. - */ - float get_gravity(); + /** + * @brief Set the gravity object. + * + * @param[in] new_gravity The new gravity to apply to the player. + */ + void set_gravity(float new_gravity); - /** - * @brief Set the run speed object. - * - * @param[in] new_run_speed The new speed for running. - */ - void set_run_speed(float new_run_speed); + /** + * @brief Get the gravity object. + * + * @return float The current gravity applied to the player. + */ + float get_gravity(); - /** - * @brief Get the run speed object. - * - * @return float The current run speed of the player. - */ - float get_run_speed(); + /** + * @brief Set the run speed object. + * + * @param[in] new_run_speed The new speed for running. + */ + void set_run_speed(float new_run_speed); - /** - * @brief This signal is called when the player moves. - * @details The jump action is not included in this signal, just moving left or right. - * - * @param[in] position The new position of the player. - */ - void _on_Player_player_moved(Vector2 position); - }; + /** + * @brief Get the run speed object. + * + * @return float The current run speed of the player. + */ + float get_run_speed(); + + void set_double_jump(bool double_jump); + bool get_double_jump(); + + void set_velocity(Vector2 velocity); + Vector2 get_velocity(); + }; + } } #endif diff --git a/src/player/states/PlayerFall.cpp b/src/player/states/PlayerFall.cpp new file mode 100644 index 0000000..c3e6ff4 --- /dev/null +++ b/src/player/states/PlayerFall.cpp @@ -0,0 +1,78 @@ +#include "player/states/PlayerFall.h" +#include "player/Player.h" + +using namespace godot; +using namespace player; + +void PlayerFall::_register_methods() +{ + register_method("_state_enter", &PlayerFall::_state_enter); + register_method("_state_exit", &PlayerFall::_state_exit); + register_method("_physics_process", &PlayerFall::_physics_process); +} + +PlayerFall::PlayerFall() +{ +} + +PlayerFall::~PlayerFall() +{ +} + +void PlayerFall::_init() +{ + _input = Input::get_singleton(); +} + +void PlayerFall::_state_enter() +{ + animated_sprite = get_parent()->get_node("AnimatedSprite"); + animated_sprite->stop(); + animated_sprite->set_animation("air"); +} + +void PlayerFall::_state_exit() +{ + animated_sprite->set_animation("move"); + animated_sprite->set_frame(1); +} + +void PlayerFall::_physics_process(float delta) +{ + auto parent = Object::cast_to(get_parent()); + + if (parent->is_on_floor()) + { + get_state_machine()->change("Move"); + return; + } + + auto current_speed = parent->get_speed(); + auto velocity = parent->get_velocity(); + velocity.x = 0; + if (_input->is_action_pressed("run")) + { + current_speed *= parent->get_run_speed(); + } + + if (_input->is_action_pressed("right")) + { + velocity.x += current_speed; + } + + if (_input->is_action_pressed("left")) + { + velocity.x += -current_speed; + } + + if (velocity.x > 0) + { + animated_sprite->set_flip_h(true); + } + else if (velocity.x < 0) + { + animated_sprite->set_flip_h(false); + } + + parent->set_velocity(velocity); +} diff --git a/src/player/states/PlayerFall.h b/src/player/states/PlayerFall.h new file mode 100644 index 0000000..4fcbf83 --- /dev/null +++ b/src/player/states/PlayerFall.h @@ -0,0 +1,44 @@ +#ifndef JUEGO_PLAYER_FALL_H +#define JUEGO_PLAYER_FALL_H + +#include "state_machine/State.h" + +#include +#include +#include + +namespace godot +{ + namespace player + { + class PlayerFall : public State + { + GODOT_CLASS(PlayerFall, State) + + private: + Input *_input; + AnimatedSprite *animated_sprite; + + public: + static void _register_methods(); + + PlayerFall(); + + ~PlayerFall(); + + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); + + void _state_enter(); + + void _state_exit(); + + void _physics_process(float delta); + }; + } +} + +#endif diff --git a/src/player/states/PlayerIdle.cpp b/src/player/states/PlayerIdle.cpp new file mode 100644 index 0000000..026b5cf --- /dev/null +++ b/src/player/states/PlayerIdle.cpp @@ -0,0 +1,65 @@ +#include "player/states/PlayerIdle.h" +#include "player/Player.h" + +using namespace godot; +using namespace player; + +void PlayerIdle::_register_methods() +{ + register_method("_state_enter", &PlayerIdle::_state_enter); + register_method("_state_exit", &PlayerIdle::_state_exit); + register_method("_physics_process", &PlayerIdle::_physics_process); +} + +PlayerIdle::PlayerIdle() +{ +} + +PlayerIdle::~PlayerIdle() +{ +} + +void PlayerIdle::_init() +{ + _input = Input::get_singleton(); +} + +void PlayerIdle::_state_enter() +{ + animated_sprite = get_parent()->get_node("AnimatedSprite"); + animated_sprite->stop(); + animated_sprite->set_animation("idle"); +} + +void PlayerIdle::_state_exit() +{ +} + +void PlayerIdle::_physics_process(float delta) +{ + auto parent = Object::cast_to(get_parent()); + + if (_input->is_action_pressed("right")) + { + get_state_machine()->change("Move"); + return; + } + + if (_input->is_action_pressed("left")) + { + get_state_machine()->change("Move"); + return; + } + + if (_input->is_action_just_pressed("jump")) + { + get_state_machine()->change("Jump"); + return; + } + + if (!parent->is_on_floor()) + { + get_state_machine()->change("Fall"); + return; + } +} diff --git a/src/player/states/PlayerIdle.h b/src/player/states/PlayerIdle.h new file mode 100644 index 0000000..631aef4 --- /dev/null +++ b/src/player/states/PlayerIdle.h @@ -0,0 +1,45 @@ +#ifndef JUEGO_PLAYER_IDLE_H +#define JUEGO_PLAYER_IDLE_H + +#include "state_machine/State.h" + +#include +#include +#include +#include + +namespace godot +{ + namespace player + { + class PlayerIdle : public State + { + GODOT_CLASS(PlayerIdle, State) + + private: + Input *_input; + AnimatedSprite *animated_sprite; + + public: + static void _register_methods(); + + PlayerIdle(); + + ~PlayerIdle(); + + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); + + void _state_enter(); + + void _state_exit(); + + void _physics_process(float delta); + }; + } +} + +#endif diff --git a/src/player/states/PlayerJump.cpp b/src/player/states/PlayerJump.cpp new file mode 100644 index 0000000..8255e1b --- /dev/null +++ b/src/player/states/PlayerJump.cpp @@ -0,0 +1,105 @@ +#include "player/states/PlayerJump.h" +#include "player/Player.h" + +using namespace godot; +using namespace player; + +void PlayerJump::_register_methods() +{ + register_method("_state_enter", &PlayerJump::_state_enter); + register_method("_state_exit", &PlayerJump::_state_exit); + register_method("_physics_process", &PlayerJump::_physics_process); +} + +PlayerJump::PlayerJump() +{ +} + +PlayerJump::~PlayerJump() +{ +} + +void PlayerJump::_init() +{ + _input = Input::get_singleton(); +} + +void PlayerJump::_state_enter(const String state) +{ + animated_sprite = get_parent()->get_node("AnimatedSprite"); + animated_sprite->stop(); + animated_sprite->set_animation("air"); + + if (state == "Jump") + { + double_jumped = true; + } + else + { + double_jumped = false; + } + + auto parent = Object::cast_to(get_parent()); + auto velocity = parent->get_velocity(); + velocity.y = -parent->get_jump_force(); + parent->set_velocity(velocity); +} + +void PlayerJump::_state_exit() +{ + animated_sprite->set_animation("move"); + animated_sprite->set_frame(1); +} + +void PlayerJump::_physics_process(float delta) +{ + auto parent = Object::cast_to(get_parent()); + if (parent->is_on_floor()) + { + get_state_machine()->change("Move"); + return; + } + + auto current_speed = parent->get_speed(); + auto velocity = parent->get_velocity(); + velocity.x = 0; + if (_input->is_action_pressed("run")) + { + current_speed *= parent->get_run_speed(); + } + + if (_input->is_action_pressed("right")) + { + velocity.x += current_speed; + } + + if (_input->is_action_pressed("left")) + { + velocity.x += -current_speed; + } + + if (_input->is_action_just_released("jump")) + { + if (velocity.y < -100) + { + velocity.y = -100; + } + } + + if (parent->get_double_jump() && !double_jumped && _input->is_action_just_pressed("jump")) + { + get_state_machine()->change("Jump"); + return; + } + + if (velocity.x > 0) + { + animated_sprite->set_flip_h(true); + } + else if (velocity.x < 0) + { + animated_sprite->set_flip_h(false); + } + + parent->set_velocity(velocity); +} diff --git a/src/player/states/PlayerJump.h b/src/player/states/PlayerJump.h new file mode 100644 index 0000000..7458832 --- /dev/null +++ b/src/player/states/PlayerJump.h @@ -0,0 +1,45 @@ +#ifndef JUEGO_PLAYER_JUMP_H +#define JUEGO_PLAYER_JUMP_H + +#include "state_machine/State.h" + +#include +#include +#include + +namespace godot +{ + namespace player + { + class PlayerJump : public State + { + GODOT_CLASS(PlayerJump, State) + + private: + Input *_input; + AnimatedSprite *animated_sprite; + bool double_jumped; + + public: + static void _register_methods(); + + PlayerJump(); + + ~PlayerJump(); + + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); + + void _state_enter(const String state); + + void _state_exit(); + + void _physics_process(float delta); + }; + } +} + +#endif diff --git a/src/player/states/PlayerMove.cpp b/src/player/states/PlayerMove.cpp new file mode 100644 index 0000000..787db1d --- /dev/null +++ b/src/player/states/PlayerMove.cpp @@ -0,0 +1,94 @@ +#include "player/states/PlayerMove.h" +#include "player/Player.h" + +using namespace godot; +using namespace player; + +void PlayerMove::_register_methods() +{ + register_method("_state_enter", &PlayerMove::_state_enter); + register_method("_state_exit", &PlayerMove::_state_exit); + register_method("_physics_process", &PlayerMove::_physics_process); +} + +PlayerMove::PlayerMove() +{ +} + +PlayerMove::~PlayerMove() +{ +} + +void PlayerMove::_init() +{ + _input = Input::get_singleton(); +} + +void PlayerMove::_state_enter(String state, Array args) +{ + animated_sprite = get_parent()->get_node("AnimatedSprite"); + animated_sprite->set_animation("move"); + animated_sprite->play(); +} + +void PlayerMove::_state_exit() +{ +} + +void PlayerMove::_physics_process(float delta) +{ + auto parent = Object::cast_to(get_parent()); + + auto direction_pressed = false; + + auto current_speed = parent->get_speed(); + auto velocity = parent->get_velocity(); + velocity.x = 0; + if (_input->is_action_pressed("run")) + { + current_speed *= parent->get_run_speed(); + } + + if (_input->is_action_pressed("right")) + { + direction_pressed = true; + velocity.x += current_speed; + } + + if (_input->is_action_pressed("left")) + { + direction_pressed = true; + velocity.x += -current_speed; + } + + if (_input->is_action_just_pressed("jump")) + { + get_state_machine()->change("Jump"); + return; + } + + if (velocity.x > 0) + { + animated_sprite->set_flip_h(true); + } + else if (velocity.x < 0) + { + animated_sprite->set_flip_h(false); + } + else + { + if (!direction_pressed) + { + get_state_machine()->change("Idle"); + } + return; + } + + parent->set_velocity(velocity); + + if (!parent->is_on_floor()) + { + get_state_machine()->change("Fall"); + return; + } +} diff --git a/src/player/states/PlayerMove.h b/src/player/states/PlayerMove.h new file mode 100644 index 0000000..a41e6d4 --- /dev/null +++ b/src/player/states/PlayerMove.h @@ -0,0 +1,46 @@ +#ifndef JUEGO_PLAYER_MOVE_H +#define JUEGO_PLAYER_MOVE_H + +#include "state_machine/State.h" + +#include +#include +#include + +namespace godot +{ + namespace player + { + class PlayerMove : public State + { + GODOT_CLASS(PlayerMove, State) + + private: + Input *_input; + AnimatedSprite *animated_sprite; + + public: + static void _register_methods(); + + PlayerMove(); + + ~PlayerMove(); + + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); + + void _state_enter(String state, Array args); + + void _state_exit(); + + void _physics_process(float delta); + + Vector2 move_player(Vector2 velocity); + }; + } +} + +#endif diff --git a/src/state_machine/State.cpp b/src/state_machine/State.cpp new file mode 100644 index 0000000..6e53a52 --- /dev/null +++ b/src/state_machine/State.cpp @@ -0,0 +1,54 @@ +#include "State.h" + +using namespace godot; + +void State::_register_methods() +{ + register_method("set_parent", &State::set_parent); + register_method("get_parent", &State::get_parent); + register_method("set_state_machine", &State::set_state_machine); + register_method("_state_enter", &State::_state_enter); + register_method("_state_exit", &State::_state_exit); +} + +State::State() +{ +} + +State::~State() +{ +} + +void State::_init() +{ +} + +void State::_state_enter(const String state, const Array args) +{ + WARN_PRINT("State " + state + " is missing its _state_enter method!"); +} + +void State::_state_exit(const String state, const Array args) +{ + WARN_PRINT("State " + state + " is missing its _state_exit method!"); +} + +void State::set_parent(Node *new_parent) +{ + parent = new_parent; +} + +Node *State::get_parent() +{ + return parent; +} + +void State::set_state_machine(StateMachine *new_state_machine) +{ + state_machine = new_state_machine; +} + +StateMachine *State::get_state_machine() +{ + return state_machine; +} diff --git a/src/state_machine/State.h b/src/state_machine/State.h new file mode 100644 index 0000000..5ae0db8 --- /dev/null +++ b/src/state_machine/State.h @@ -0,0 +1,46 @@ +#ifndef JUEGO_STATE_H +#define JUEGO_STATE_H + +#include "StateMachine.h" + +#include +#include + +namespace godot +{ + class State : public StateMachine + { + GODOT_CLASS(State, Node) + + private: + StateMachine *state_machine; + + public: + Node *parent; + static void _register_methods(); + + State(); + + ~State(); + + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + virtual void _init(); + + virtual void _state_enter(const String state, const Array args = Array()); + + virtual void _state_exit(const String state, const Array args = Array()); + + virtual void set_parent(Node *new_parent) final; + + virtual Node *get_parent() final; + + virtual void set_state_machine(StateMachine *new_state_machine) final; + + virtual StateMachine *get_state_machine() final; + }; +} + +#endif diff --git a/src/state_machine/StateMachine.cpp b/src/state_machine/StateMachine.cpp new file mode 100644 index 0000000..200883b --- /dev/null +++ b/src/state_machine/StateMachine.cpp @@ -0,0 +1,208 @@ +#include "StateMachine.h" +#include "State.h" + +using namespace godot; + +void StateMachine::_register_methods() +{ + register_method("_ready", &StateMachine::_ready); + register_method("_on_StateMachine_tree_entered", &StateMachine::_on_StateMachine_tree_entered); + register_method("_on_StateMachine_tree_exiting", &StateMachine::_on_StateMachine_tree_exiting); + register_property("default_state", &StateMachine::set_default_state, &StateMachine::get_default_state, String()); + register_property("debug", &StateMachine::set_debug, &StateMachine::get_debug, false); + register_signal("state_entered", "state", GODOT_VARIANT_TYPE_STRING); + register_signal("state_exited", "state", GODOT_VARIANT_TYPE_STRING); + register_signal("state_restarted", "state", GODOT_VARIANT_TYPE_STRING); +} + +StateMachine::StateMachine() +{ +} + +StateMachine::~StateMachine() +{ +} + +void StateMachine::_init() +{ + set_default_state(String()); + set_debug(false); +} + +void StateMachine::_ready() +{ + connect("tree_entered", this, "_on_StateMachine_tree_entered"); + connect("tree_exiting", this, "_on_StateMachine_tree_exiting"); + parent = get_parent(); + set_current_state(get_default_state()); + setup(); +} + +void StateMachine::setup() +{ + auto children = get_children(); + + if (get_current_state() == "") + { + if (children.size() > 0) + { + WARN_PRINT("State machine doesn't have a default state set, using first child!"); + auto child = Object::cast_to(children[0].operator Object*()); + set_current_state(child->get_name()); + } + else + { + ERR_PRINT("State machine doesn't have a default state set and has no child states!"); + return; + } + } + + for (uint8_t i = 0; i < children.size(); i++) + { + auto child = Object::cast_to(children[i].operator Object*()); + add_state(child->get_name(), child); + + child->call("set_state_machine", this); + + child->call("set_parent", parent); + + if (child->get_name() != get_current_state()) + { + this->remove_child(child); + } + } + + this->call("_state_enter", get_current_state()); +} + +void StateMachine::add_state(const String state, Node *child) +{ + states[state] = child; +} + +bool StateMachine::is_current(const String state) +{ + if (get_current_state() == "") + { + return false; + } + else + { + return get_current_state() == state; + } +} + +bool StateMachine::has(const String state) +{ + return states.has(state); +} + +void StateMachine::restart(const String state, const Array& args) +{ + this->call("_state_exit", state, args); + this->call("_state_enter", state, args); + this->emit_signal("state_restarted", get_current_state()); +} + +void StateMachine::change(const String state, const Array &args) +{ + if (is_current(state)) + { + return this->restart(state, args); + } + + auto previous_state = get_current_state(); + auto exiting = this->call("_state_exit", state, args); + + if (get_current_state() != "") + { + auto child = Object::cast_to(states[get_current_state()].operator Object*()); + if (child != nullptr) + { + this->remove_child(child); + } + this->emit_signal("state_exited", get_current_state()); + if (debug) + { + Godot::print(get_current_state() + " exited!"); + } + } + + set_current_state(state); + auto child = Object::cast_to(states[get_current_state()].operator Object*()); + this->add_child(child); + + this->call("_state_enter", previous_state, args); + this->emit_signal("state_entered", get_current_state()); + if (debug) + { + Godot::print(get_current_state() + " entered!"); + } +} + +Variant StateMachine::call(const String method, const Array &args) +{ + auto node = Object::cast_to(states[get_current_state()].operator Object*()); + if (node != nullptr) + { + return node->call(method, args); + } + return Variant(); +} + +Variant StateMachine::_call(const String method, const Array &args) +{ + return this->call(method, args); +} + +void StateMachine::set_default_state(const String new_default_state) +{ + default_state = new_default_state; +} + +String StateMachine::get_default_state() +{ + return default_state; +} + +void StateMachine::set_current_state(const String new_current_sate) +{ + current_state = new_current_sate; +} + +String StateMachine::get_current_state() +{ + return current_state; +} + +void StateMachine::set_debug(bool debug) +{ + this->debug = debug; +} + +bool StateMachine::get_debug() +{ + return this->debug; +} + +void StateMachine::_on_StateMachine_tree_entered() +{ + setup(); +} + +void StateMachine::_on_StateMachine_tree_exiting() +{ + auto keys = states.keys(); + for (uint8_t i = 0; i < keys.size(); i++) + { + auto child = Object::cast_to(states[keys[i]].operator Object*()); + if (child != nullptr) + { + auto children = get_children(); + if (!children.has(child)) + { + this->add_child(child); + } + } + } +} diff --git a/src/state_machine/StateMachine.h b/src/state_machine/StateMachine.h new file mode 100644 index 0000000..66920e3 --- /dev/null +++ b/src/state_machine/StateMachine.h @@ -0,0 +1,95 @@ +#ifndef JUEGO_STATE_MACHINE_H +#define JUEGO_STATE_MACHINE_H + +#include +#include + +namespace godot +{ + class StateMachine : public Node + { + GODOT_CLASS(StateMachine, Node) + + private: + Node *parent; + String default_state; + bool debug; + String current_state; + Dictionary states; + + void add_state(const String state, Node *child); + + public: + static void _register_methods(); + + StateMachine(); + + ~StateMachine(); + + /** + * @brief Initialize the class from Godot. + * @details This method is called just once when the Godot engine connects to the instance of the class. + */ + void _init(); + + /** + * @brief Code to be run when ready. + * @details This method is run when all the children of this node are ready. + */ + void _ready(); + + void setup(); + + bool is_current(); + + bool is_current(const String state); + + bool has(const String state); + + void restart(const String state, const Array& args = Array()); + + void change(const String state, const Array &args = Array()); + + Variant call(const String method, const Array &args = Array()); + + Variant _call(const String method, const Array &args = Array()); + + template Variant restart(Args ...args) + { + return restart(Array::make(args...)); + } + + template Variant change(const String state, Args ...args) + { + return change(state, Array::make(args...)); + } + + template Variant call(const String method, Args ...args) + { + return call(method, Array::make(args...)); + } + + template Variant _call(const String method, Args ...args) + { + return _call(method, Array::make(args...)); + } + + void set_default_state(const String new_default_state); + + String get_default_state(); + + void set_debug(bool debug); + + bool get_debug(); + + void set_current_state(const String new_current_state); + + String get_current_state(); + + void _on_StateMachine_tree_entered(); + + void _on_StateMachine_tree_exiting(); + }; +} + +#endif -- 2.30.2 From 219b277e5c43bcaf2b99c9c062af84842ce7a3e0 Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Tue, 12 Apr 2022 11:33:22 -0400 Subject: [PATCH 6/8] some cleanup of the code --- src/Main.cpp | 20 +++++++++---------- src/Main.h | 12 +++++------ src/player/Player.cpp | 32 +++++++++++++++--------------- src/player/Player.h | 20 +++++++++---------- src/state_machine/State.cpp | 10 +++++----- src/state_machine/State.h | 4 ++-- src/state_machine/StateMachine.cpp | 12 +++++------ src/state_machine/StateMachine.h | 4 ++-- 8 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/Main.cpp b/src/Main.cpp index ef0fe55..387ff6e 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -55,39 +55,39 @@ void Main::_physics_process(float delta) } } -void Main::set_full_screen(bool new_full_screen) +void Main::set_full_screen(bool full_screen) { - full_screen = new_full_screen; + this->full_screen = full_screen; } bool Main::get_full_screen() { - return full_screen; + return this->full_screen; } -void Main::set_window_size(Vector2 new_window_size) +void Main::set_window_size(Vector2 window_size) { - window_size = new_window_size; + this-> window_size = window_size; } Vector2 Main::get_window_size() { - return window_size; + return this->window_size; } -void Main::set_launch_screen(int8_t new_launch_screen) +void Main::set_launch_screen(int8_t launch_screen) { - launch_screen = new_launch_screen; + this->launch_screen = launch_screen; } int8_t Main::get_launch_screen() { - if (launch_screen == -1) + if (this->launch_screen == -1) { return _os->get_current_screen(); } else { - return launch_screen; + return this->launch_screen; } } diff --git a/src/Main.h b/src/Main.h index 3a65398..af61ec8 100644 --- a/src/Main.h +++ b/src/Main.h @@ -89,9 +89,9 @@ namespace godot /** * @brief Set the full screen object. * - * @param[in] new_full_screen The new full screen state. + * @param[in] full_screen The new full screen state. */ - void set_full_screen(bool new_full_screen); + void set_full_screen(bool full_screen); /** * @brief Get the full screen object. @@ -104,9 +104,9 @@ namespace godot /** * @brief Set the window size object. * - * @param[in] new_window_size The new window size. + * @param[in] window_size The new window size. */ - void set_window_size(Vector2 new_window_size); + void set_window_size(Vector2 window_size); /** * @brief Get the window size object. @@ -118,9 +118,9 @@ namespace godot /** * @brief Set the launch screen object. * - * @param[in] new_launch_screen The launch screen to use. + * @param[in] launch_screen The launch screen to use. */ - void set_launch_screen(int8_t new_launch_screen); + void set_launch_screen(int8_t launch_screen); /** * @brief Get the launch screen object. diff --git a/src/player/Player.cpp b/src/player/Player.cpp index 30c801d..843043b 100644 --- a/src/player/Player.cpp +++ b/src/player/Player.cpp @@ -1,4 +1,4 @@ -#include "Player.h" +#include "player/Player.h" #include #include @@ -112,54 +112,54 @@ void Player::_physics_process(float delta) } } -void Player::set_sprite_frames(Ref new_sprite_frames) +void Player::set_sprite_frames(Ref sprite_frames) { - sprite_frames = new_sprite_frames; + this->sprite_frames = sprite_frames; } Ref Player::get_sprite_frames() { - return sprite_frames; + return this->sprite_frames; } -void Player::set_speed(float new_speed) +void Player::set_speed(float speed) { - speed = new_speed; + this->speed = speed; } float Player::get_speed() { - return speed; + return this->speed; } -void Player::set_jump_force(float new_jump_force) +void Player::set_jump_force(float jump_force) { - jump_force = new_jump_force; + this->jump_force = jump_force; } float Player::get_jump_force() { - return jump_force; + return this->jump_force; } -void Player::set_gravity(float new_gravity) +void Player::set_gravity(float gravity) { - gravity = new_gravity; + this->gravity = gravity; } float Player::get_gravity() { - return gravity; + return this->gravity; } -void Player::set_run_speed(float new_run_speed) +void Player::set_run_speed(float run_speed) { - run_speed = new_run_speed; + this->run_speed = run_speed; } float Player::get_run_speed() { - return run_speed; + return this->run_speed; } void Player::set_double_jump(bool double_jump) diff --git a/src/player/Player.h b/src/player/Player.h index 67ff8c4..78bc986 100644 --- a/src/player/Player.h +++ b/src/player/Player.h @@ -112,9 +112,9 @@ namespace godot /** * @brief Set the sprite frames object. * - * @param[in] new_sprite_frames The new sprite frame. + * @param[in] sprite_frames The new sprite frame. */ - void set_sprite_frames(Ref new_sprite_frames); + void set_sprite_frames(Ref sprite_frames); /** * @brief Get the sprite frames object. @@ -126,9 +126,9 @@ namespace godot /** * @brief Set the speed object. * - * @param[in] new_speed The new speed. + * @param[in] speed The new speed. */ - void set_speed(float new_speed); + void set_speed(float speed); /** * @brief Get the speed object. @@ -140,9 +140,9 @@ namespace godot /** * @brief Set the jump force object. * - * @param[in] new_jump_force The new force applied to the player to make him jump. + * @param[in] jump_force The new force applied to the player to make him jump. */ - void set_jump_force(float new_jump_force); + void set_jump_force(float jump_force); /** * @brief Get the jump force object. @@ -154,9 +154,9 @@ namespace godot /** * @brief Set the gravity object. * - * @param[in] new_gravity The new gravity to apply to the player. + * @param[in] gravity The new gravity to apply to the player. */ - void set_gravity(float new_gravity); + void set_gravity(float gravity); /** * @brief Get the gravity object. @@ -168,9 +168,9 @@ namespace godot /** * @brief Set the run speed object. * - * @param[in] new_run_speed The new speed for running. + * @param[in] run_speed The new speed for running. */ - void set_run_speed(float new_run_speed); + void set_run_speed(float run_speed); /** * @brief Get the run speed object. diff --git a/src/state_machine/State.cpp b/src/state_machine/State.cpp index 6e53a52..24d8b6d 100644 --- a/src/state_machine/State.cpp +++ b/src/state_machine/State.cpp @@ -33,9 +33,9 @@ void State::_state_exit(const String state, const Array args) WARN_PRINT("State " + state + " is missing its _state_exit method!"); } -void State::set_parent(Node *new_parent) +void State::set_parent(Node *parent) { - parent = new_parent; + this->parent = parent; } Node *State::get_parent() @@ -43,12 +43,12 @@ Node *State::get_parent() return parent; } -void State::set_state_machine(StateMachine *new_state_machine) +void State::set_state_machine(StateMachine *state_machine) { - state_machine = new_state_machine; + this->state_machine = state_machine; } StateMachine *State::get_state_machine() { - return state_machine; + return this->state_machine; } diff --git a/src/state_machine/State.h b/src/state_machine/State.h index 5ae0db8..bd8d787 100644 --- a/src/state_machine/State.h +++ b/src/state_machine/State.h @@ -33,11 +33,11 @@ namespace godot virtual void _state_exit(const String state, const Array args = Array()); - virtual void set_parent(Node *new_parent) final; + virtual void set_parent(Node *parent) final; virtual Node *get_parent() final; - virtual void set_state_machine(StateMachine *new_state_machine) final; + virtual void set_state_machine(StateMachine *state_machine) final; virtual StateMachine *get_state_machine() final; }; diff --git a/src/state_machine/StateMachine.cpp b/src/state_machine/StateMachine.cpp index 200883b..6556431 100644 --- a/src/state_machine/StateMachine.cpp +++ b/src/state_machine/StateMachine.cpp @@ -155,24 +155,24 @@ Variant StateMachine::_call(const String method, const Array &args) return this->call(method, args); } -void StateMachine::set_default_state(const String new_default_state) +void StateMachine::set_default_state(const String default_state) { - default_state = new_default_state; + this->default_state = default_state; } String StateMachine::get_default_state() { - return default_state; + return this->default_state; } -void StateMachine::set_current_state(const String new_current_sate) +void StateMachine::set_current_state(const String current_sate) { - current_state = new_current_sate; + this->current_state = current_sate; } String StateMachine::get_current_state() { - return current_state; + return this->current_state; } void StateMachine::set_debug(bool debug) diff --git a/src/state_machine/StateMachine.h b/src/state_machine/StateMachine.h index 66920e3..5f0cea5 100644 --- a/src/state_machine/StateMachine.h +++ b/src/state_machine/StateMachine.h @@ -74,7 +74,7 @@ namespace godot return _call(method, Array::make(args...)); } - void set_default_state(const String new_default_state); + void set_default_state(const String default_state); String get_default_state(); @@ -82,7 +82,7 @@ namespace godot bool get_debug(); - void set_current_state(const String new_current_state); + void set_current_state(const String current_state); String get_current_state(); -- 2.30.2 From 1c24ba0cd15a5d8e64ff8594e2a85cbeefedfa03 Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Wed, 13 Apr 2022 00:59:23 -0400 Subject: [PATCH 7/8] add documentation --- src/Main.h | 30 +++++ src/godot.cpp | 12 ++ src/player/Player.h | 73 ++++++++++- src/player/states/PlayerFall.h | 45 +++++++ src/player/states/PlayerIdle.h | 39 ++++++ src/player/states/PlayerJump.h | 46 +++++++ src/player/states/PlayerMove.cpp | 2 +- src/player/states/PlayerMove.h | 43 +++++- src/state_machine/State.cpp | 2 +- src/state_machine/State.h | 60 ++++++++- src/state_machine/StateMachine.cpp | 4 +- src/state_machine/StateMachine.h | 203 ++++++++++++++++++++++++++--- 12 files changed, 529 insertions(+), 30 deletions(-) diff --git a/src/Main.h b/src/Main.h index af61ec8..4d86783 100644 --- a/src/Main.h +++ b/src/Main.h @@ -8,18 +8,37 @@ /** * @brief This is the godot namespace for all the code included in the library. + * * @details This namespace is used a prefix when the Godot engine looks for classes, methods, and properties. */ namespace godot { + /** + * @brief This namespace houses some global variables and the main class. + * + */ namespace main { + /** + * @brief The default value for if the game should start in full screen. + * + */ const bool full_screen = false; + /** + * @brief The default resolution for the game window. + * + */ const Vector2 window_size = Vector2(1280, 720); + /** + * @brief The default screen the the game should open on. + * + * @details -1 opens it on the currently active screen. And 0 and above are the screens to use. + */ const int8_t launch_screen = -1; /** * @brief This class controls the Main node. + * * @details The main node is responsible for controling the window and the game iteself is a child of it. */ class Main : public Node @@ -29,57 +48,68 @@ namespace godot private: /** * @brief OS singleton. + * */ OS *_os; /** * @brief Input singleton. + * */ Input *_input; /** * @brief If the window is full screen or not. + * */ bool full_screen; /** * @brief The size of the window. + * */ Vector2 window_size; /** * @brief The screen to launch the game on. + * */ int8_t launch_screen; public: /** * @brief This method registers classes with Godot. + * * @details This method registers methods, properties, and signals with the Godot engine. */ static void _register_methods(); /** * @brief Construct a new Main object. + * */ Main(); /** * @brief Destroy the Main object. + * */ ~Main(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); /** * @brief Code to be run when ready. + * * @details This method is run when all the children of this node are ready. */ void _ready(); /** * @brief This class handles the physics processing. + * * @details Every delta time, this function is called to check for input and update positioning. * * @param[in] delta The difference in time that passed since the last call to this method. diff --git a/src/godot.cpp b/src/godot.cpp index b449e46..76e07ec 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -11,11 +11,19 @@ using namespace godot; +/** + * @brief This function connects the gdnative init function. + * + */ extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) { Godot::gdnative_init(o); } +/** + * @brief This function connects the gdnative terminate function. + * + */ extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o) { // This next line is a workaround to fix bug: @@ -24,6 +32,10 @@ extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_opt Godot::gdnative_terminate(o); } +/** + * @brief This function connects the init methods in the classes to godot's gdnative. + * + */ extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) { Godot::nativescript_init(handle); diff --git a/src/player/Player.h b/src/player/Player.h index 78bc986..fd2474a 100644 --- a/src/player/Player.h +++ b/src/player/Player.h @@ -10,21 +10,51 @@ /** * @brief This is the godot namespace for all the code included in the library. + * * @details This namespace is used a prefix when the Godot engine looks for classes, methods, and properties. */ namespace godot { + /** + * @brief This namespace contains the global variables related to the player and its states. + * + */ namespace player { + /** + * @brief The default sprite resource of the player. + * + */ const char player_sprite_frames[] = "res://characters/player/sprites/green.tres"; + /** + * @brief The default speed of the player. + * + */ const float speed = 60.0; + /** + * @brief The default jump force applied when jumping. + * + */ const float jump_force = 300.0; + /** + * @brief The default gravity applied to the player. + * + */ const float gravity = 9.81; + /** + * @brief The default run speed multiplier. + * + */ const float run_speed = 2.0; + /** + * @brief The default double jump activation state. + * + */ const bool double_jump = true; /** * @brief This class is used to control the player. + * * @details This class allows the player to move, run, and jump as well as controls the sprite displayed for those actions. */ class Player : public KinematicBody2D @@ -34,75 +64,93 @@ namespace godot private: /** * @brief ResourceLoader singleton. + * */ ResourceLoader *_resource_loader; /** * @brief The animated sprite connected to the KinematicBody2D. + * */ AnimatedSprite *animated_sprite; /** * @brief The sprite frames used in the animated sprite. + * */ Ref sprite_frames; /** * @brief The coins the player has collected. + * */ uint8_t coins; /** * @brief The velocity at which moves the player moves. + * */ Vector2 velocity; /** * @brief The speed that the player moves in. + * */ float speed; /** * @brief The force applied to the player when jumping. + * */ float jump_force; /** * @brief The gravity applied to the player. + * */ float gravity; /** * @brief The speed multiplier used to make the player move faster. + * */ float run_speed; - + /** + * @brief If double jump is enabled or not. + * + */ bool double_jump; public: /** * @brief This method registers classes with Godot. + * * @details This method registers methods, properties, and signals with the Godot engine. */ static void _register_methods(); /** * @brief Construct a new Player object. + * */ Player(); /** * @brief Destroy the Player object. + * */ ~Player(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); /** * @brief Code to be run when ready. + * * @details This method is run when all the children of this node are ready. */ void _ready(); /** * @brief This class handles the physics processing. + * * @details Every delta time, this function is called to check for input and update positioning. * * @param[in] delta The difference in time that passed since the last call to this method. @@ -179,10 +227,33 @@ namespace godot */ float get_run_speed(); + /** + * @brief Set the double jump object. + * + * @param[in] double_jump The new double dump value. + */ void set_double_jump(bool double_jump); + + /** + * @brief Get the double jump object. + * + * @return true If double jump is enabled. + * @return false If double jump is disabled. + */ bool get_double_jump(); + /** + * @brief Set the velocity object. + * + * @param[in] velocity The new velocity of the player. + */ void set_velocity(Vector2 velocity); + + /** + * @brief Get the velocity object. + * + * @return Vector2 Returns the velocity of the player. + */ Vector2 get_velocity(); }; } diff --git a/src/player/states/PlayerFall.h b/src/player/states/PlayerFall.h index 4fcbf83..d53fd4f 100644 --- a/src/player/states/PlayerFall.h +++ b/src/player/states/PlayerFall.h @@ -7,35 +7,80 @@ #include #include +/** + * @brief This is the godot namespace for all the code included in the library. + * + * @details This namespace is used a prefix when the Godot engine looks for classes, methods, and properties. + */ namespace godot { namespace player { + /** + * @brief This class controls what happens when the player is in a falling state. + * + */ class PlayerFall : public State { GODOT_CLASS(PlayerFall, State) private: + /** + * @brief Input singleton. + * + */ Input *_input; + + /** + * @brief The animated sprite connected to the player. + * + */ AnimatedSprite *animated_sprite; public: + /** + * @brief This method registers classes with Godot. + * + * @details This method registers methods, properties, and signals with the Godot engine. + */ static void _register_methods(); + /** + * @brief Construct a new Player Fall object. + * + */ PlayerFall(); + /** + * @brief Destroy the Player Fall object. + * + */ ~PlayerFall(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); + /** + * @brief Called when the fall state is entered. + * + */ void _state_enter(); + /** + * @brief Called when the fall state is exited. + * + */ void _state_exit(); + /** + * @brief The physics processed every delta time. + * + * @param[in] delta The time since the method was last run. + */ void _physics_process(float delta); }; } diff --git a/src/player/states/PlayerIdle.h b/src/player/states/PlayerIdle.h index 631aef4..76e4685 100644 --- a/src/player/states/PlayerIdle.h +++ b/src/player/states/PlayerIdle.h @@ -12,31 +12,70 @@ namespace godot { namespace player { + /** + * @brief This class controls what happens when the player is in the idle state. + * + */ class PlayerIdle : public State { GODOT_CLASS(PlayerIdle, State) private: + /** + * @brief Input singleton. + * + */ Input *_input; + /** + * @brief The animated sprite of the player. + * + */ AnimatedSprite *animated_sprite; public: + /** + * @brief This method registers classes with Godot. + * + * @details This method registers methods, properties, and signals with the Godot engine. + */ static void _register_methods(); + /** + * @brief Construct a new Player Idle object. + * + */ PlayerIdle(); + /** + * @brief Destroy the Player Idle object. + * + */ ~PlayerIdle(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); + /** + * @brief Called when the idle state is entered. + * + */ void _state_enter(); + /** + * @brief Called when the idle state is exited. + * + */ void _state_exit(); + /** + * @brief The physics processed every delta time. + * + * @param[in] delta The time since the method was last run. + */ void _physics_process(float delta); }; } diff --git a/src/player/states/PlayerJump.h b/src/player/states/PlayerJump.h index 7458832..aee1059 100644 --- a/src/player/states/PlayerJump.h +++ b/src/player/states/PlayerJump.h @@ -11,32 +11,78 @@ namespace godot { namespace player { + /** + * @brief This class control what happens when the player is in the jump state. + * + */ class PlayerJump : public State { GODOT_CLASS(PlayerJump, State) private: + /** + * @brief Input singleton. + * + */ Input *_input; + /** + * @brief The animated sprite connected to the player. + * + */ AnimatedSprite *animated_sprite; + /** + * @brief If the player has already performed a double jump or not. + * + */ bool double_jumped; public: + /** + * @brief This method registers classes with Godot. + * + * @details This method registers methods, properties, and signals with the Godot engine. + */ static void _register_methods(); + /** + * @brief Construct a new Player Jump object. + * + */ PlayerJump(); + /** + * @brief Destroy the Player Jump object. + * + */ ~PlayerJump(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); + /** + * @brief Called when the player enters the jump state. + * + * @details If the previous state was the jump state, a double jump was performed. + * + * @param[in] state The previous state before this one was entered. + */ void _state_enter(const String state); + /** + * @brief Called when the player exits the jump state. + * + */ void _state_exit(); + /** + * @brief The physics processed every delta time. + * + * @param[in] delta The time since the method was last run. + */ void _physics_process(float delta); }; } diff --git a/src/player/states/PlayerMove.cpp b/src/player/states/PlayerMove.cpp index 787db1d..77df13e 100644 --- a/src/player/states/PlayerMove.cpp +++ b/src/player/states/PlayerMove.cpp @@ -24,7 +24,7 @@ void PlayerMove::_init() _input = Input::get_singleton(); } -void PlayerMove::_state_enter(String state, Array args) +void PlayerMove::_state_enter() { animated_sprite = get_parent()->get_node("AnimatedSprite"); animated_sprite->set_animation("move"); diff --git a/src/player/states/PlayerMove.h b/src/player/states/PlayerMove.h index a41e6d4..0df3078 100644 --- a/src/player/states/PlayerMove.h +++ b/src/player/states/PlayerMove.h @@ -11,34 +11,71 @@ namespace godot { namespace player { + /** + * @brief This class controls what happens when the player is in the move state. + * + */ class PlayerMove : public State { GODOT_CLASS(PlayerMove, State) private: + /** + * @brief Input singleton. + * + */ Input *_input; + /** + * @brief The animated sprite of the player. + * + */ AnimatedSprite *animated_sprite; public: + /** + * @brief This method registers classes with Godot. + * + * @details This method registers methods, properties, and signals with the Godot engine. + */ static void _register_methods(); + /** + * @brief Construct a new Player Move object. + * + */ PlayerMove(); + /** + * @brief Destroy the Player Move object. + * + */ ~PlayerMove(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); - void _state_enter(String state, Array args); + /** + * @brief Called when the player enters the move state. + * + */ + void _state_enter(); + /** + * @brief Called when the player exists the move state. + * + */ void _state_exit(); + /** + * @brief The physics processed every delta time. + * + * @param[in] delta The time since the method was last run. + */ void _physics_process(float delta); - - Vector2 move_player(Vector2 velocity); }; } } diff --git a/src/state_machine/State.cpp b/src/state_machine/State.cpp index 24d8b6d..29efa48 100644 --- a/src/state_machine/State.cpp +++ b/src/state_machine/State.cpp @@ -1,4 +1,4 @@ -#include "State.h" +#include "state_machine/State.h" using namespace godot; diff --git a/src/state_machine/State.h b/src/state_machine/State.h index bd8d787..46ebe38 100644 --- a/src/state_machine/State.h +++ b/src/state_machine/State.h @@ -8,37 +8,95 @@ namespace godot { + /** + * @brief This class provides a virtual template state that real states should extend from and override. + * + */ class State : public StateMachine { GODOT_CLASS(State, Node) private: + /** + * @brief The state's parent, this is the node 1 level above the state machine. + * + */ + Node *parent; + /** + * @brief The state machine itself, used to handle all state related work. + * + */ StateMachine *state_machine; public: - Node *parent; + /** + * @brief This method registers classes with Godot. + * + * @details This method registers methods, properties, and signals with the Godot engine. + */ static void _register_methods(); + /** + * @brief Construct a new State object. + * + */ State(); + /** + * @brief Destroy the State object. + * + */ ~State(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ virtual void _init(); + /** + * @brief This is called when a state is entered. + * + * @param[in] state This will contain the previous state. + * @param[in] args The arguments passed to the state. + */ virtual void _state_enter(const String state, const Array args = Array()); + /** + * @brief This is called when a state is exited. + * + * @param[in] state The state we are going to. + * @param[in] args The arguments passed to the state. + */ virtual void _state_exit(const String state, const Array args = Array()); + /** + * @brief Set the parent object. + * + * @param[in] parent The parent of the state. + */ virtual void set_parent(Node *parent) final; + /** + * @brief Get the parent object. + * + * @return Node* The parent of the state. + */ virtual Node *get_parent() final; + /** + * @brief Set the state machine object. + * + * @param[in] state_machine The state machine. + */ virtual void set_state_machine(StateMachine *state_machine) final; + /** + * @brief Get the state machine object. + * + * @return StateMachine* The state machine. + */ virtual StateMachine *get_state_machine() final; }; } diff --git a/src/state_machine/StateMachine.cpp b/src/state_machine/StateMachine.cpp index 6556431..4370842 100644 --- a/src/state_machine/StateMachine.cpp +++ b/src/state_machine/StateMachine.cpp @@ -1,5 +1,5 @@ -#include "StateMachine.h" -#include "State.h" +#include "state_machine/StateMachine.h" +#include "state_machine/State.h" using namespace godot; diff --git a/src/state_machine/StateMachine.h b/src/state_machine/StateMachine.h index 5f0cea5..02789ba 100644 --- a/src/state_machine/StateMachine.h +++ b/src/state_machine/StateMachine.h @@ -6,89 +6,250 @@ namespace godot { + /** + * @brief This class provides a finite state machine that can be used with any scene and node. + * + */ class StateMachine : public Node { GODOT_CLASS(StateMachine, Node) private: + /** + * @brief The parent node which is one level above the state machine. + * + */ Node *parent; + /** + * @brief The default state for the state machine to run. + * + * @details If this is not set, the state machine will try to run the first state node. + * If no state nodes are present, an error will be printed and the state machine will not work. + */ String default_state; + /** + * @brief If set to true the state machine will print a message showing when it enters or exits a state. + * + */ bool debug; + /** + * @brief The current state the machine is in. + * + */ String current_state; + /** + * @brief A list of the states in the state machine. + * + */ Dictionary states; + /** + * @brief This adds a state to the list of states in the state machine. + * + * @param[in] state The new state. + * @param[in] child The godot node which represents the state. + */ void add_state(const String state, Node *child); public: + /** + * @brief This method registers classes with Godot. + * + * @details This method registers methods, properties, and signals with the Godot engine. + */ static void _register_methods(); + /** + * @brief Construct a new State Machine object. + */ StateMachine(); + /** + * @brief Destroy the State Machine object. + */ ~StateMachine(); /** * @brief Initialize the class from Godot. + * * @details This method is called just once when the Godot engine connects to the instance of the class. */ void _init(); /** * @brief Code to be run when ready. + * * @details This method is run when all the children of this node are ready. */ void _ready(); + /** + * @brief This method will remove all no default states from the scene tree and start the default state. + * + */ void setup(); - bool is_current(); - + /** + * @brief Check if the given state is the current running state. + * + * @param[in] state The state to compare with the running state. + * @return true If the running state and given state are the same. + * @return false If the running state and given state are not the same. + */ bool is_current(const String state); + /** + * @brief Check if the state machine has a given state. + * + * @param[in] state The state to check for. + * @return true If the state exists. + * @return false If the state doesn't exist. + */ bool has(const String state); + /** + * @brief Restar the running state by calling its enter and exit methods. + * + * @param[in] state The state that is being restarted. + * @param[in] args The arguments to pass to the state on exit and enter. + */ void restart(const String state, const Array& args = Array()); + /** + * @brief Change to a different state. + * + * @details If the running state is the same as the state it will restart it. + * + * @param[in] state The state to change to. + * @param[in] args The arguments to pass to the exiting state and the entering state. + */ void change(const String state, const Array &args = Array()); + /** + * @brief Call a registered godot method in the class. + * + * @param[in] method The method name to call. + * @param[in] args The arguments to pass to the method. + * @return Variant Returns a Variant based off what the method returns. + */ Variant call(const String method, const Array &args = Array()); + /** + * @brief This method is to link up a signal call back. + * + * @param[in] method The method to call for the signal. + * @param[in] args The arguments to pass to the method. + * @return Variant Returns a Variant based off what the method returns. + */ Variant _call(const String method, const Array &args = Array()); - template Variant restart(Args ...args) + /** + * @brief Set the default state object. + * + * @param[in] default_state The new default state. + */ + void set_default_state(const String default_state); + + /** + * @brief Get the default state object. + * + * @return String The default state. + */ + String get_default_state(); + + /** + * @brief Set the debug object. + * + * @param[in] debug Whether or not to debug. + */ + void set_debug(bool debug); + + /** + * @brief Get the debug object. + * + * @return true If debugging is enabled. + * @return false If debugging is disabled. + */ + bool get_debug(); + + /** + * @brief Set the current state object. + * + * @param[in] current_state The current state that is running. + */ + void set_current_state(const String current_state); + + /** + * @brief Get the current state object. + * + * @return String The current running state. + */ + String get_current_state(); + + /** + * @brief This method is called when the signal tree_entered is emitted. + * + * @details This will run the setup method to prepare the state machine for use. + */ + void _on_StateMachine_tree_entered(); + + /** + * @brief This method is called when the signal tree_exiting is emitted. + * + * @details If the tree is in the exiting state readd all the removed state nodes to the scene tree. + * This is important because the memory won't be freed if they are no longer in the scene tree. + */ + void _on_StateMachine_tree_exiting(); + + /** + * @brief Restarts the running state. + * + * @tparam Args Variable number of arguments to pass to restart. + * @param[in] state The state being restarted. + * @param[in] args The arguments to pass when restarting. + */ + template void restart(const String state, Args ...args) { - return restart(Array::make(args...)); + return restart(state, Array::make(args...)); } - template Variant change(const String state, Args ...args) + /** + * @brief Changes to a new state. + * + * @tparam Args Variable number of arguments to pass when chaning states. + * @param[in] state The state to change to. + * @param[in] args The arguments to pass to the new state. + */ + template void change(const String state, Args ...args) { return change(state, Array::make(args...)); } + /** + * @brief Call a registered godot method in the class. + * + * @tparam Args The variable arguments to pass to the method. + * @param[in] method The method to call. + * @param[in] args The arguments to pass to it. + * @return Variant The Variant object returned by the method called. + */ template Variant call(const String method, Args ...args) { return call(method, Array::make(args...)); } + /** + * @brief This is used to connect a callback from a signal. + * + * @tparam Args The arguments to pass to the callback method. + * @param[in] method The method to call. + * @param[in] args The arguments to pass. + * @return Variant The Variant object returned by the method called. + */ template Variant _call(const String method, Args ...args) { return _call(method, Array::make(args...)); } - - void set_default_state(const String default_state); - - String get_default_state(); - - void set_debug(bool debug); - - bool get_debug(); - - void set_current_state(const String current_state); - - String get_current_state(); - - void _on_StateMachine_tree_entered(); - - void _on_StateMachine_tree_exiting(); }; } -- 2.30.2 From 8bbf3942cdcb4887578a0fa9da612c91fc407338 Mon Sep 17 00:00:00 2001 From: Chris Cromer Date: Wed, 13 Apr 2022 01:10:40 -0400 Subject: [PATCH 8/8] fix incorrect gdnative resource --- godot/state_machine/State.gdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/godot/state_machine/State.gdns b/godot/state_machine/State.gdns index dad8e97..757946d 100644 --- a/godot/state_machine/State.gdns +++ b/godot/state_machine/State.gdns @@ -1,6 +1,6 @@ [gd_resource type="NativeScript" load_steps=2 format=2] -[ext_resource path="res://gdnative/libalai.tres" type="GDNativeLibrary" id=1] +[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] [resource] resource_name = "State" -- 2.30.2