feat: implemented level loading and player spawning

main
Sara 2024-02-04 22:33:21 +01:00
parent 2fedbb07b3
commit bce949498e
4 changed files with 154 additions and 21 deletions

View File

@ -1,10 +1,11 @@
#include "entrance.hpp" #include "entrance.hpp"
#include "godot_cpp/variant/utility_functions.hpp"
#include "level.hpp" #include "level.hpp"
namespace godot { namespace godot {
void Entrance::_bind_methods() {} void Entrance::_bind_methods() {}
void Entrance::_enter_tree() { void Entrance::_enter_tree() {
this->seek_parent_level(); parentLevel = this->seek_parent_level();
if (parentLevel != nullptr) { if (parentLevel != nullptr) {
parentLevel->add_entrance(this); parentLevel->add_entrance(this);
} }
@ -22,6 +23,7 @@ Level *Entrance::seek_parent_level() {
if (Level* level = Object::cast_to<Level>(current)) if (Level* level = Object::cast_to<Level>(current))
return level; return level;
} while (current != nullptr); } while (current != nullptr);
UtilityFunctions::push_error("Failed to find level");
return nullptr; return nullptr;
} }
} } // namespace godot

View File

@ -9,14 +9,17 @@ class Level;
class Entrance : public Node3D { class Entrance : public Node3D {
GDCLASS(Entrance, Node3D) GDCLASS(Entrance, Node3D)
static void _bind_methods(); static void _bind_methods();
protected: protected:
Level* parentLevel; Level* parentLevel;
public: public:
virtual void _enter_tree() override; virtual void _enter_tree() override;
virtual void _exit_tree() override; virtual void _exit_tree() override;
protected: protected:
Level* seek_parent_level(); Level* seek_parent_level();
}; };
} } // namespace godot
#endif // !ENTRANCE_HPP #endif // !ENTRANCE_HPP

109
src/game_mode.cpp Normal file
View File

@ -0,0 +1,109 @@
#include "game_mode.hpp"
#include <optional>
#include "godot_cpp/variant/utility_functions.hpp"
#include "godot_macros.h"
#include "level.hpp"
#include "player.hpp"
namespace godot {
GameMode* GameMode::static_instance{nullptr};
void GameMode::_bind_methods() {
#define CLASSNAME GameMode
GDPROPERTY_HINTED(first_level, Variant::OBJECT,
PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
GDPROPERTY_HINTED(player_scene, Variant::OBJECT,
PropertyHint::PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
}
void GameMode::_enter_tree() {
GDGAMEONLY();
if (GameMode::static_instance != nullptr) {
this->queue_free();
} else {
GameMode::static_instance = this;
}
}
void GameMode::_exit_tree() {
GDGAMEONLY();
if (GameMode::static_instance == this) {
GameMode::static_instance = nullptr;
}
}
void GameMode::_ready() {
GDGAMEONLY();
this->load_level(firstLevel, std::nullopt);
}
void GameMode::spawn_player(String const& entrance) {
if (playerInstance == nullptr) {
Node* node = playerScene->instantiate();
if (node == nullptr) {
UtilityFunctions::push_error(
"Failed to instantiate player subscene");
return;
}
playerInstance = Object::cast_to<Player>(node);
if (playerInstance == nullptr) {
UtilityFunctions::push_error(
"Player scene root is not of type Player");
node->queue_free();
return;
}
this->add_child(playerInstance);
}
if (levelInstance != nullptr)
playerInstance->set_global_transform(
levelInstance->get_entrance(entrance));
else
UtilityFunctions::push_error("Cannot spawn player without a level");
}
void GameMode::load_level(Ref<PackedScene>& level,
std::optional<String> entrance) {
if (levelInstance != nullptr)
levelInstance->queue_free();
if (firstLevel.is_null() || !firstLevel.is_valid()) {
UtilityFunctions::push_error("No initial level configured");
return;
}
Node* inst = firstLevel->instantiate();
if (inst == nullptr) {
UtilityFunctions::push_error("Failed to instantiate level");
return;
}
levelInstance = Object::cast_to<Level>(inst);
if (levelInstance == nullptr) {
UtilityFunctions::push_error("Level scene root is not of type Level");
inst->queue_free();
return;
}
this->add_child(inst);
if (entrance.has_value())
this->spawn_player(entrance.value());
else
this->spawn_player(levelInstance->get_default_entrance());
}
Player* GameMode::get_player_instance() const {
return playerInstance;
}
void GameMode::set_first_level(Ref<PackedScene> level) {
firstLevel = level;
}
Ref<PackedScene> GameMode::get_first_level() const {
return firstLevel;
}
void GameMode::set_player_scene(Ref<PackedScene> scene) {
playerScene = scene;
}
Ref<PackedScene> GameMode::get_player_scene() const {
return playerScene;
}
} // namespace godot

View File

@ -1,6 +1,8 @@
#ifndef GAME_STATE_HPP #ifndef GAME_STATE_HPP
#define GAME_STATE_HPP #define GAME_STATE_HPP
#include "optional"
#include "godot_cpp/classes/node.hpp" #include "godot_cpp/classes/node.hpp"
#include "godot_cpp/classes/packed_scene.hpp" #include "godot_cpp/classes/packed_scene.hpp"
@ -11,14 +13,31 @@ class Player;
class GameMode : public Node { class GameMode : public Node {
GDCLASS(GameMode, Node) GDCLASS(GameMode, Node)
static void _bind_methods(); static void _bind_methods();
static GameMode* static_instance;
protected: protected:
Level *currentLevel{nullptr}; Level* levelInstance{nullptr};
Ref<PackedScene> firstLevel{}; Ref<PackedScene> firstLevel{};
Player* playerInstance{nullptr}; Player* playerInstance{nullptr};
Ref<PackedScene> playerScene{};
public: public:
void load_level(Ref<PackedScene> levelScene); virtual void _enter_tree() override;
virtual void _exit_tree() override;
virtual void _ready() override;
void spawn_player(String const& entrance);
void load_level(Ref<PackedScene>& levelScene,
std::optional<String> entrance);
Player* get_player_instance() const;
void set_first_level(Ref<PackedScene> level);
Ref<PackedScene> get_first_level() const;
void set_player_scene(Ref<PackedScene> scene);
Ref<PackedScene> get_player_scene() const;
}; };
} } // namespace godot
#endif // !GAME_STATE_HPP #endif // !GAME_STATE_HPP