feat: added core game and level concepts
This commit is contained in:
		
							parent
							
								
									988d39bdb4
								
							
						
					
					
						commit
						49562071c0
					
				
							
								
								
									
										34
									
								
								game_mode.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								game_mode.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
#include "game_mode.hpp"
 | 
			
		||||
#include <godot_cpp/classes/global_constants.hpp>
 | 
			
		||||
#include <godot_cpp/classes/packed_scene.hpp>
 | 
			
		||||
#include <godot_cpp/classes/scene_state.hpp>
 | 
			
		||||
#include "utils/godot_macros.h"
 | 
			
		||||
#include "game_state.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
void GameMode::_bind_methods() {
 | 
			
		||||
#define CLASSNAME GameMode
 | 
			
		||||
    GDPROPERTY_HINTED(game_state, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GameState");
 | 
			
		||||
    GDPROPERTY_HINTED(player_scene, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameMode::set_player_scene(Ref<PackedScene> scene) {
 | 
			
		||||
    this->player_scene = scene;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<PackedScene> GameMode::get_player_scene() const {
 | 
			
		||||
    return this->player_scene;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameMode::set_game_state(Ref<GameState> state) {
 | 
			
		||||
    if(state.is_null() || !state.is_valid()) {
 | 
			
		||||
        this->game_state.unref();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    this->game_state = state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<GameState> GameMode::get_game_state() {
 | 
			
		||||
    return this->game_state;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								game_mode.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								game_mode.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
#ifndef GAME_MODE_H
 | 
			
		||||
#define GAME_MODE_H
 | 
			
		||||
 | 
			
		||||
#include <godot_cpp/classes/packed_scene.hpp>
 | 
			
		||||
#include <godot_cpp/classes/resource.hpp>
 | 
			
		||||
#include "game_state.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
class GameMode : public Resource {
 | 
			
		||||
    GDCLASS(GameMode, Resource);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
    void set_player_scene(Ref<PackedScene> scene);
 | 
			
		||||
    Ref<PackedScene> get_player_scene() const;
 | 
			
		||||
    void set_game_state(Ref<GameState> state);
 | 
			
		||||
    Ref<GameState> get_game_state();
 | 
			
		||||
private:
 | 
			
		||||
    Ref<PackedScene> player_scene{};
 | 
			
		||||
    Ref<GameState> game_state{};
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !GAME_MODE_H
 | 
			
		||||
							
								
								
									
										208
									
								
								game_root.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								game_root.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,208 @@
 | 
			
		|||
#include "game_root.hpp"
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <godot_cpp/classes/global_constants.hpp>
 | 
			
		||||
#include <godot_cpp/classes/packed_scene.hpp>
 | 
			
		||||
#include <godot_cpp/classes/scene_state.hpp>
 | 
			
		||||
#include <godot_cpp/variant/string_name.hpp>
 | 
			
		||||
#include <godot_cpp/variant/utility_functions.hpp>
 | 
			
		||||
#include <godot_cpp/classes/input.hpp>
 | 
			
		||||
#include <godot_cpp/core/class_db.hpp>
 | 
			
		||||
#include "godot_cpp/templates/pair.hpp"
 | 
			
		||||
#include "utils/godot_macros.h"
 | 
			
		||||
#include "utils/player_input.hpp"
 | 
			
		||||
#include "utils/spawn_point.hpp"
 | 
			
		||||
#include "utils/player.hpp"
 | 
			
		||||
#include "game_mode.hpp"
 | 
			
		||||
#include "level.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
void GameRoot::_bind_methods() {
 | 
			
		||||
#define CLASSNAME GameRoot
 | 
			
		||||
    GDFUNCTION(reset_game_mode);
 | 
			
		||||
    ClassDB::add_signal("GameRoot", MethodInfo("player_connected", PropertyInfo(Variant::OBJECT, "player_input", PROPERTY_HINT_NODE_TYPE, "PlayerInput")));
 | 
			
		||||
    ClassDB::add_signal("GameRoot", MethodInfo("player_disconnected", PropertyInfo(Variant::OBJECT, "player_input", PROPERTY_HINT_NODE_TYPE, "PlayerInput")));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GameRoot *GameRoot::get_singleton() {
 | 
			
		||||
    return GameRoot::singleton_instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GameRoot::has_singleton() {
 | 
			
		||||
    return GameRoot::singleton_instance != nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::_enter_tree() { GDGAMEONLY();
 | 
			
		||||
    // TODO: Replace this with detecting input devices
 | 
			
		||||
    if(this->players.is_empty())
 | 
			
		||||
        this->player_connected();
 | 
			
		||||
    this->grab_singleton();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::_exit_tree() { GDGAMEONLY();
 | 
			
		||||
    this->release_singleton();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::set_game_mode(Ref<GameMode> mode) {
 | 
			
		||||
    if(mode.is_null() || !mode.is_valid()) {
 | 
			
		||||
        this->game_mode = Ref<GameMode>();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    this->game_mode = mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<GameMode> GameRoot::get_game_mode() const {
 | 
			
		||||
    return this->game_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::player_connected() {
 | 
			
		||||
    PlayerInput *input = memnew(PlayerInput);
 | 
			
		||||
    this->add_child(input);
 | 
			
		||||
    this->players.insert(this->next_player_id++, {input, nullptr});
 | 
			
		||||
    this->emit_signal(StringName("player_connected"), input);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GameRoot::initialize_player(IPlayer *player) {
 | 
			
		||||
    KeyValue<uint32_t, Pair<PlayerInput*, IPlayer*>> *found{nullptr};
 | 
			
		||||
    // find an unassigned player input instance
 | 
			
		||||
    for(KeyValue<uint32_t, Pair<PlayerInput*, IPlayer*>> &pair : this->players) {
 | 
			
		||||
        if(pair.value.second == nullptr) {
 | 
			
		||||
            found = &pair;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // no player slots available, notify caller
 | 
			
		||||
    if(!found)
 | 
			
		||||
        return false;
 | 
			
		||||
    player->player_id = found->key;
 | 
			
		||||
    found->value.second = player;
 | 
			
		||||
    player->setup_player_input(found->value.first);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::reset_game_mode() {
 | 
			
		||||
    this->game_mode.unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::grab_singleton() {
 | 
			
		||||
    if(GameRoot::has_singleton()) {
 | 
			
		||||
        this->set_process_mode(PROCESS_MODE_DISABLED);
 | 
			
		||||
        UtilityFunctions::push_error("More than one GameRoot instance active");
 | 
			
		||||
    } else {
 | 
			
		||||
        GameRoot::singleton_instance = this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot::release_singleton() {
 | 
			
		||||
    if(GameRoot::singleton_instance == this) {
 | 
			
		||||
        GameRoot::singleton_instance = nullptr;
 | 
			
		||||
    } else {
 | 
			
		||||
        UtilityFunctions::push_error("GameRoot instance attempted to release singleton while it is not the singleton instance");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GameRoot *GameRoot::singleton_instance{nullptr};
 | 
			
		||||
 | 
			
		||||
#undef CLASSNAME
 | 
			
		||||
 | 
			
		||||
void GameRoot3D::_bind_methods() {
 | 
			
		||||
#define CLASSNAME GameRoot3D
 | 
			
		||||
    GDPROPERTY_HINTED(first_boot_level, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot3D::_ready() { GDGAMEONLY();
 | 
			
		||||
    this->load_level(this->first_boot_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Level3D *GameRoot3D::load_level(Ref<PackedScene> level) {
 | 
			
		||||
    return this->load_level_at(level, Transform3D());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Level3D *GameRoot3D::load_level_at(Ref<PackedScene> level, Transform3D at) {
 | 
			
		||||
    if(!GameRoot3D::is_valid_level(level)) {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    Level3D *instance = Object::cast_to<Level3D>(level->instantiate());
 | 
			
		||||
    if(instance == nullptr) {
 | 
			
		||||
        UtilityFunctions::push_error("Unexpected failure to instantiate level scene '", level->get_path(), "'.");
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    // store and add to tree at desired transform
 | 
			
		||||
    this->add_child(instance);
 | 
			
		||||
    instance->set_global_transform(at);
 | 
			
		||||
    this->levels.insert(level->get_path(), instance);
 | 
			
		||||
    // if this is the first level containing a game mode currently active use it's gamemode as a prototype
 | 
			
		||||
    if(this->game_mode.is_null()) {
 | 
			
		||||
        this->change_game_mode(instance->get_game_mode_prototype());
 | 
			
		||||
        instance->connect("tree_exited", Callable(this, "reset_game_mode"));
 | 
			
		||||
    }
 | 
			
		||||
    return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot3D::register_spawn_point(SpawnPoint3D *spawn_point) {
 | 
			
		||||
    if(this->spawn_points.has(spawn_point)) {
 | 
			
		||||
        UtilityFunctions::push_error("Duplicate attempt to register spawnpoint '", spawn_point->get_path(), "'");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    this->spawn_points.insert(spawn_point);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot3D::unregister_spawn_point(SpawnPoint3D *spawn_point) {
 | 
			
		||||
    if(!this->spawn_points.has(spawn_point)) {
 | 
			
		||||
        UtilityFunctions::push_error("Attempt to unregister spawnpoint '", spawn_point->get_path(), "', which is not registered.");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    this->spawn_points.erase(spawn_point);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot3D::set_first_boot_level(Ref<PackedScene> level) {
 | 
			
		||||
    if(level.is_null() || !level.is_valid()) {
 | 
			
		||||
        this->first_boot_level.unref();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    StringName const root_type = level->get_state()->get_node_type(0);
 | 
			
		||||
    if(!ClassDB::is_parent_class("Level3D", root_type)) {
 | 
			
		||||
        UtilityFunctions::push_error("First boot level cannot be of type '", root_type, "'. First boot level has to inherit from Level3D");
 | 
			
		||||
        this->first_boot_level.unref();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    this->first_boot_level = level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<PackedScene> GameRoot3D::get_first_boot_level() const {
 | 
			
		||||
    return this->first_boot_level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GameRoot3D::is_valid_level(Ref<PackedScene> &level) {
 | 
			
		||||
    if(level.is_null() || !level.is_valid() || !level->can_instantiate()) {
 | 
			
		||||
        UtilityFunctions::push_error("Can't load level from invalid packed scene");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    StringName const root_type = level->get_state()->get_node_type(0);
 | 
			
		||||
    if(!ClassDB::is_parent_class("Level3D", root_type)) {
 | 
			
		||||
        UtilityFunctions::push_error("Can't load level with root type '", root_type, "'. Root node has to be of type Level3D");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameRoot3D::change_game_mode(Ref<GameMode> prototype) {
 | 
			
		||||
    // free all player instances in use
 | 
			
		||||
    for(KeyValue<uint32_t, Pair<PlayerInput*, IPlayer*>> &pair : this->players) {
 | 
			
		||||
        if(pair.value.second == nullptr) continue;
 | 
			
		||||
        Node *node = dynamic_cast<Node*>(pair.value.second);
 | 
			
		||||
        if(node == nullptr) {
 | 
			
		||||
            UtilityFunctions::push_error("Attempt to cast player '", pair.key, "' to node failed");
 | 
			
		||||
        } else {
 | 
			
		||||
            node->queue_free();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // create new gamemode instance
 | 
			
		||||
    this->game_mode = prototype->duplicate(true);
 | 
			
		||||
    Node *player_node = this->game_mode->get_player_scene()->instantiate();
 | 
			
		||||
    IPlayer *player = dynamic_cast<IPlayer*>(player_node);
 | 
			
		||||
    if(player != nullptr) {
 | 
			
		||||
        this->initialize_player(player);
 | 
			
		||||
    } else {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								game_root.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								game_root.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
#ifndef GAME_ROOT_HPP
 | 
			
		||||
#define GAME_ROOT_HPP
 | 
			
		||||
 | 
			
		||||
#include <godot_cpp/classes/packed_scene.hpp>
 | 
			
		||||
#include <godot_cpp/classes/node.hpp>
 | 
			
		||||
#include <godot_cpp/templates/hash_map.hpp>
 | 
			
		||||
#include <godot_cpp/templates/hash_set.hpp>
 | 
			
		||||
#include <godot_cpp/templates/pair.hpp>
 | 
			
		||||
#include <godot_cpp/templates/vector.hpp>
 | 
			
		||||
#include <godot_cpp/templates/pair.hpp>
 | 
			
		||||
#include "game_mode.hpp"
 | 
			
		||||
#include "level.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
class PlayerInput;
 | 
			
		||||
class IPlayer;
 | 
			
		||||
class SpawnPoint3D;
 | 
			
		||||
 | 
			
		||||
class GameRoot : public Node {
 | 
			
		||||
    GDCLASS(GameRoot, Node);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
    static GameRoot *get_singleton();
 | 
			
		||||
    static bool has_singleton();
 | 
			
		||||
 | 
			
		||||
    virtual void _enter_tree() override;
 | 
			
		||||
    virtual void _exit_tree() override;
 | 
			
		||||
 | 
			
		||||
    void set_game_mode(Ref<GameMode> mode);
 | 
			
		||||
    Ref<GameMode> get_game_mode() const;
 | 
			
		||||
 | 
			
		||||
    void player_connected();
 | 
			
		||||
    void player_disconnected();
 | 
			
		||||
    bool initialize_player(IPlayer *player);
 | 
			
		||||
 | 
			
		||||
    void reset_game_mode();
 | 
			
		||||
protected:
 | 
			
		||||
    void grab_singleton();
 | 
			
		||||
    void release_singleton();
 | 
			
		||||
protected:
 | 
			
		||||
    static GameRoot *singleton_instance;
 | 
			
		||||
 | 
			
		||||
    uint32_t next_player_id{0};
 | 
			
		||||
    HashMap<uint32_t, Pair<PlayerInput*, IPlayer*>> players{};
 | 
			
		||||
    Ref<GameMode> game_mode{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class GameRoot3D : public GameRoot {
 | 
			
		||||
    GDCLASS(GameRoot3D, GameRoot);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
    virtual void _ready() override;
 | 
			
		||||
    Level3D *load_level(Ref<PackedScene> level);
 | 
			
		||||
    Level3D *load_level_at(Ref<PackedScene> level, Transform3D at);
 | 
			
		||||
 | 
			
		||||
    void register_spawn_point(SpawnPoint3D *spawn_point);
 | 
			
		||||
    void unregister_spawn_point(SpawnPoint3D *spawn_point);
 | 
			
		||||
 | 
			
		||||
    void set_first_boot_level(Ref<PackedScene> level);
 | 
			
		||||
    Ref<PackedScene> get_first_boot_level() const;
 | 
			
		||||
private:
 | 
			
		||||
    static bool is_valid_level(Ref<PackedScene> &level);
 | 
			
		||||
    void change_game_mode(Ref<GameMode> prototype);
 | 
			
		||||
private:
 | 
			
		||||
    HashMap<StringName, Level3D*> levels{};
 | 
			
		||||
    HashSet<SpawnPoint3D*> spawn_points{};
 | 
			
		||||
 | 
			
		||||
    Ref<PackedScene> first_boot_level{};
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !GAME_ROOT_HPP
 | 
			
		||||
							
								
								
									
										7
									
								
								game_state.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								game_state.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
#include "game_state.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
void GameState::_bind_methods() {
 | 
			
		||||
#define CLASSNAME GameState
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								game_state.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								game_state.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
#ifndef GAME_STATE_HPP
 | 
			
		||||
#define GAME_STATE_HPP
 | 
			
		||||
 | 
			
		||||
#include "godot_cpp/classes/resource.hpp"
 | 
			
		||||
namespace godot {
 | 
			
		||||
class GameState : public Resource {
 | 
			
		||||
    GDCLASS(GameState, Resource);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !GAME_STATE_HPP
 | 
			
		||||
							
								
								
									
										33
									
								
								level.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								level.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
#include "level.hpp"
 | 
			
		||||
#include "utils/godot_macros.h"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
void Level3D::_bind_methods() {
 | 
			
		||||
#define CLASSNAME Level3D
 | 
			
		||||
    GDPROPERTY_HINTED(game_mode_prototype, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GameMode");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Level3D::set_game_mode_prototype(Ref<GameMode> prototype) {
 | 
			
		||||
    this->game_mode_prototype = prototype;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<GameMode> Level3D::get_game_mode_prototype() const {
 | 
			
		||||
    return this->game_mode_prototype;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef CLASSNAME // Level3D
 | 
			
		||||
 | 
			
		||||
void Level2D::_bind_methods() {
 | 
			
		||||
#define CLASSNAME Level3D
 | 
			
		||||
    GDPROPERTY_HINTED(game_mode_prototype, Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GameMode");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Level2D::set_game_mode_prototype(Ref<GameMode> prototype) {
 | 
			
		||||
    this->game_mode_prototype = prototype;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<GameMode> Level2D::get_game_mode_prototype() const {
 | 
			
		||||
    return this->game_mode_prototype;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								level.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								level.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
#ifndef LEVEL_HPP
 | 
			
		||||
#define LEVEL_HPP
 | 
			
		||||
 | 
			
		||||
#include <godot_cpp/classes/node2d.hpp>
 | 
			
		||||
#include <godot_cpp/classes/node3d.hpp>
 | 
			
		||||
#include "game_mode.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
class Level3D : public Node3D {
 | 
			
		||||
    GDCLASS(Level3D, Node3D);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
    void set_game_mode_prototype(Ref<GameMode> prototype);
 | 
			
		||||
    Ref<GameMode> get_game_mode_prototype() const;
 | 
			
		||||
private:
 | 
			
		||||
    Ref<GameMode> game_mode_prototype{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Level2D : public Node2D {
 | 
			
		||||
    GDCLASS(Level2D, Node2D);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
    void set_game_mode_prototype(Ref<GameMode> prototype);
 | 
			
		||||
    Ref<GameMode> get_game_mode_prototype() const;
 | 
			
		||||
private:
 | 
			
		||||
    Ref<GameMode> game_mode_prototype{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !LEVEL_HPP
 | 
			
		||||
							
								
								
									
										24
									
								
								player.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								player.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
#ifndef UTILS_PLAYER_HPP
 | 
			
		||||
#define UTILS_PLAYER_HPP
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <optional>
 | 
			
		||||
namespace godot {
 | 
			
		||||
class PlayerInput;
 | 
			
		||||
class Node;
 | 
			
		||||
 | 
			
		||||
class IPlayer {
 | 
			
		||||
friend class GameRoot;
 | 
			
		||||
public:
 | 
			
		||||
    virtual void setup_player_input(PlayerInput *input) = 0;
 | 
			
		||||
    virtual Node *to_node() = 0;
 | 
			
		||||
 | 
			
		||||
    uint32_t get_player_id();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::optional<uint32_t> player_id{std::nullopt};
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !UTILS_PLAYER_HPP
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								spawn_point.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								spawn_point.cpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
#include "spawn_point.hpp"
 | 
			
		||||
#include "utils/game_root.hpp"
 | 
			
		||||
 | 
			
		||||
namespace godot {
 | 
			
		||||
void SpawnPoint3D::_bind_methods() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SpawnPoint3D::_enter_tree() {
 | 
			
		||||
    GameRoot3D *root = Object::cast_to<GameRoot3D>(GameRoot3D::get_singleton());
 | 
			
		||||
    if(root == nullptr) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    root->register_spawn_point(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SpawnPoint3D::_exit_tree() {
 | 
			
		||||
    GameRoot3D *root = Object::cast_to<GameRoot3D>(GameRoot3D::get_singleton());
 | 
			
		||||
    if(root == nullptr) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    root->unregister_spawn_point(this);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								spawn_point.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								spawn_point.hpp
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
#ifndef UTILS_SPAWN_POINT_HPP
 | 
			
		||||
#define UTILS_SPAWN_POINT_HPP
 | 
			
		||||
 | 
			
		||||
#include "godot_cpp/classes/node3d.hpp"
 | 
			
		||||
namespace godot {
 | 
			
		||||
class SpawnPoint3D : public Node3D {
 | 
			
		||||
    GDCLASS(SpawnPoint3D, Node3D);
 | 
			
		||||
    static void _bind_methods();
 | 
			
		||||
public:
 | 
			
		||||
    virtual void _enter_tree() override;
 | 
			
		||||
    virtual void _exit_tree() override;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // !UTILS_SPAWN_POINT_HPP
 | 
			
		||||
		Loading…
	
		Reference in a new issue