feat: implemented level loading and player spawning
parent
2fedbb07b3
commit
bce949498e
|
@ -1,27 +1,29 @@
|
||||||
#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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entrance::_exit_tree() {
|
void Entrance::_exit_tree() {
|
||||||
if(parentLevel != nullptr)
|
if (parentLevel != nullptr)
|
||||||
parentLevel->remove_entrance(this);
|
parentLevel->remove_entrance(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Level *Entrance::seek_parent_level() {
|
Level* Entrance::seek_parent_level() {
|
||||||
Node *current = this;
|
Node* current = this;
|
||||||
do {
|
do {
|
||||||
current = current->get_parent();
|
current = current->get_parent();
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue