Добавил shared_from_this как основной способ создать умный указатель на "себя". Добавил пример работы с ним

This commit is contained in:
Jiga228
2026-06-28 15:44:58 +07:00
parent 311772cca4
commit ad881a97a9
13 changed files with 77 additions and 47 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ GENERATE_META(Actor)
class Actor : public ISave, public IRTTI class Actor : public ISave, public IRTTI
{ {
World* world_; std::shared_ptr<World> world_;
std::string name_; std::string name_;
std::shared_ptr<Vector3D> loc_, rot_, scale_; std::shared_ptr<Vector3D> loc_, rot_, scale_;
@@ -54,7 +54,7 @@ public:
void RemoveTag(const std::string& tag) noexcept; void RemoveTag(const std::string& tag) noexcept;
const std::list<std::string>& GetTags() const { return tags; } const std::list<std::string>& GetTags() const { return tags; }
World* GetWorld() const { return world_; } std::shared_ptr<World> GetWorld() const { return world_; }
const std::string& GetName() const { return name_; } const std::string& GetName() const { return name_; }
friend class World; friend class World;
+9 -13
View File
@@ -7,10 +7,11 @@
#include "Core/CoreInstance.hpp" #include "Core/CoreInstance.hpp"
#include "Game/WorldFactory.hpp" #include "Game/WorldFactory.hpp"
#include "Game/World/World.hpp" #include "Game/World/World.hpp"
#include "Log/Log.hpp"
extern std::vector<WorldFactory> world_factories; extern std::vector<WorldFactory> world_factories;
GameInstance::GameInstance(CoreInstance& core) : core(core) GameInstance::GameInstance(CoreInstance& core) : core_(core)
{ {
const std::string& base_world = core.getBaseWorldName(); const std::string& base_world = core.getBaseWorldName();
@@ -21,33 +22,28 @@ GameInstance::GameInstance(CoreInstance& core) : core(core)
{ {
if (factories.world_name == base_world) if (factories.world_name == base_world)
{ {
world = factories.factory(*this); world_ = factories.factory(*this);
break; break;
} }
} }
if (world == nullptr) if (world_ == nullptr)
throw std::runtime_error("Can't find world"); throw std::runtime_error("Can't find world");
} }
GameInstance::~GameInstance()
{
delete world;
}
void GameInstance::start() void GameInstance::start()
{ {
world->BeginPlay(); world_->BeginPlay();
auto first = std::chrono::steady_clock::now(); auto first = std::chrono::steady_clock::now();
while (is_running) while (is_running_)
{ {
auto second = std::chrono::steady_clock::now(); auto second = std::chrono::steady_clock::now();
std::chrono::milliseconds delta_time = std::chrono::duration_cast<std::chrono::milliseconds>(second - first); std::chrono::milliseconds delta_time = std::chrono::duration_cast<std::chrono::milliseconds>(second - first);
world->Tick(delta_time.count() / 1000.0); world_->Tick(delta_time.count() / 1000.0);
first = second; first = second;
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
@@ -55,11 +51,11 @@ void GameInstance::start()
void GameInstance::stop() void GameInstance::stop()
{ {
is_running = false; is_running_ = false;
} }
void GameInstance::quit() void GameInstance::quit()
{ {
stop(); stop();
core.quit(); core_.quit();
} }
+6 -6
View File
@@ -11,10 +11,10 @@ GameInstance* GameFactory(CoreInstance& core) { return new Class(core); }
class GameInstance class GameInstance
{ {
CoreInstance& core; CoreInstance& core_;
World* world = nullptr; std::shared_ptr<World> world_;
std::atomic<bool> is_running = true; std::atomic<bool> is_running_ = true;
void start(); void start();
// Stop call from the core // Stop call from the core
@@ -25,10 +25,10 @@ public:
// Init vulkan // Init vulkan
GameInstance(CoreInstance& core); GameInstance(CoreInstance& core);
virtual ~GameInstance(); virtual ~GameInstance() = default;
World* GetWorld() const { return world; } std::shared_ptr<World> GetWorld() const { return world_; }
CoreInstance& GetCore() const { return core; } CoreInstance& GetCore() const { return core_; }
friend class CoreInstance; friend class CoreInstance;
}; };
+1 -1
View File
@@ -4,7 +4,7 @@
class SaveMap; class SaveMap;
class ISave class ISave : public std::enable_shared_from_this<ISave>
{ {
public: public:
virtual ~ISave() = default; virtual ~ISave() = default;
+5 -5
View File
@@ -56,14 +56,14 @@ SaveMap::SaveMap(const std::string& json_data)
size_t end = i = json_data_blank.find_first_of(",}", i); size_t end = i = json_data_blank.find_first_of(",}", i);
i++; i++;
std::string value = json_data_blank.substr(begin, end - begin); std::string value = json_data_blank.substr(begin, end - begin);
save_long[name.c_str() + 1] = std::stoll(value); save_long[name.c_str() + 1] = std::stoll(value); // (name.c_str() + 1) - отсекаем метаданные
} else if (name[0] == 'd') } else if (name[0] == 'd')
{ {
size_t begin = json_data_blank.find(':', i) + 1; size_t begin = json_data_blank.find(':', i) + 1;
size_t end = i = json_data_blank.find_first_of(",}", i); size_t end = i = json_data_blank.find_first_of(",}", i);
i++; i++;
std::string value = json_data_blank.substr(begin, end - begin); std::string value = json_data_blank.substr(begin, end - begin);
save_double[name.c_str() + 1] = std::stod(value); save_double[name.c_str() + 1] = std::stod(value); // (name.c_str() + 1) - отсекаем метаданные
} else if (name[0] == 's') } else if (name[0] == 's')
{ {
size_t begin = json_data_blank.find(':', i) + 2; size_t begin = json_data_blank.find(':', i) + 2;
@@ -74,7 +74,7 @@ SaveMap::SaveMap(const std::string& json_data)
value = json_data_blank.substr(begin, end - begin); value = json_data_blank.substr(begin, end - begin);
else else
value = ""; value = "";
save_string[name.c_str() + 1] = value; save_string[name.c_str() + 1] = value; // (name.c_str() + 1) - отсекаем метаданные
} else if (name[0] == 'o') } else if (name[0] == 'o')
{ {
size_t begin = i = json_data_blank.find('{', i); size_t begin = i = json_data_blank.find('{', i);
@@ -100,10 +100,10 @@ SaveMap::SaveMap(const std::string& json_data)
std::shared_ptr<ISave> object_ptr(MakeObjectByName(object_name)); std::shared_ptr<ISave> object_ptr(MakeObjectByName(object_name));
object_ptr->load(std::make_shared<SaveMap>(object_json)); object_ptr->load(std::make_shared<SaveMap>(object_json));
save_objects[name.c_str() + 1] = object_ptr; save_objects[name.c_str() + 1] = object_ptr; // (name.c_str() + 1) - отсекаем метаданные
} else if (name[0] == 'v') } else if (name[0] == 'v')
{ {
std::string key = name.substr(2, name.length() - 2); std::string key = name.substr(2, name.length() - 2); // (off = 2) - отсечение метаданных; (name.length() - 2) - отсечение кавычки и перевод в индексы
size_t begin_arr = i = json_data_blank.find('[', i); size_t begin_arr = i = json_data_blank.find('[', i);
int open = 1, close = 0; int open = 1, close = 0;
+3 -3
View File
@@ -46,13 +46,13 @@ std::shared_ptr<SaveMap> World::save()
void World::load(std::shared_ptr<SaveMap> save) void World::load(std::shared_ptr<SaveMap> save)
{ {
std::vector<std::string> actors_IDs = save->GetVectorString("ActorsIDs"); std::vector<std::string> actors_IDs = save->GetVectorString("ActorsIDs");
std::list<std::shared_ptr<Actor>> act = std::move(reinterpret_cast<std::list<std::shared_ptr<Actor>>&>(save->GetListObject("Actors"))); std::list<std::shared_ptr<ISave>> act = save->GetListObject("Actors");
size_t i_id = 0; size_t i_id = 0;
for (auto& i : act) for (auto& i : act)
{ {
auto[it, flag] = actors_map.try_emplace(actors_IDs[i_id], i); auto[it, flag] = actors_map.try_emplace(actors_IDs[i_id], std::static_pointer_cast<Actor>(i));
it->second->world_ = this; it->second->world_ = std::static_pointer_cast<World>(shared_from_this());
it->second->name_ = it->first; it->second->name_ = it->first;
i_id++; i_id++;
} }
+4 -4
View File
@@ -11,7 +11,7 @@ class World;
struct WorldFactory struct WorldFactory
{ {
const char* world_name; const char* world_name;
World*(*factory)(GameInstance&); std::shared_ptr<World>(*factory)(GameInstance&);
}; };
// Создаёт ассоцеативный список // Создаёт ассоцеативный список
@@ -20,8 +20,8 @@ struct WorldFactory
// Генерирует элемент списка // Генерирует элемент списка
#define GENERATE_WORLD_FACTORY(Class, WorldName) WorldFactory{#WorldName,\ #define GENERATE_WORLD_FACTORY(Class, WorldName) WorldFactory{#WorldName,\
[](GameInstance& game_insance)->World* {\ [](GameInstance& game_insance)->std::shared_ptr<World> {\
Class* world = new Class(game_insance);\ std::shared_ptr<Class> world = std::make_shared<Class>(game_insance);\
std::ifstream config_file("./Worlds/" #WorldName ".world");\ std::ifstream config_file("./Worlds/" #WorldName ".world");\
if (config_file.fail())\ if (config_file.fail())\
throw std::runtime_error("Can't open world file");\ throw std::runtime_error("Can't open world file");\
@@ -32,7 +32,7 @@ struct WorldFactory
data.resize(file_size);\ data.resize(file_size);\
config_file.read(data.data(), file_size);\ config_file.read(data.data(), file_size);\
world->load(std::make_shared<SaveMap>(data));\ world->load(std::make_shared<SaveMap>(data));\
return world;\ return std::static_pointer_cast<World>(world);\
}}, }},
/* /*
+14
View File
@@ -1,12 +1,26 @@
#include "TestActor.h" #include "TestActor.h"
#include "Game/Actors/Camera.hpp"
#include "Game/SaveMap/SaveMap.hpp" #include "Game/SaveMap/SaveMap.hpp"
#include "Game/World/World.hpp"
#include "Log/Log.hpp" #include "Log/Log.hpp"
void TestActor::print_when_main_camera_rotate(const Vector3D& rot)
{
std::string msg = + "(" + name_ + ") camera move to x: " + std::to_string(rot.x) +
" y: " + std::to_string(rot.y) +
" z: " + std::to_string(rot.z);
Loging::Message(msg);
}
void TestActor::BeginPlay() void TestActor::BeginPlay()
{ {
Actor::BeginPlay(); Actor::BeginPlay();
Loging::Log("TestActor::BeginPlay"); Loging::Log("TestActor::BeginPlay");
GetWorld()->GetActorsByClass<Camera>()[0].lock()->OnSetActorRotate.bind<TestActor>(
std::static_pointer_cast<TestActor>(shared_from_this()),
&TestActor::print_when_main_camera_rotate
);
} }
std::shared_ptr<SaveMap> TestActor::save() std::shared_ptr<SaveMap> TestActor::save()
+2
View File
@@ -5,6 +5,8 @@
GENERATE_META(TestActor) GENERATE_META(TestActor)
class TestActor final : public Actor class TestActor final : public Actor
{ {
const std::string name_ = "First test actor";
void print_when_main_camera_rotate(const Vector3D& rot);
public: public:
void BeginPlay() override; void BeginPlay() override;
+23 -7
View File
@@ -1,6 +1,5 @@
#include "TestWorld.h" #include "TestWorld.h"
#include <glm/glm.hpp>
#include <glm/ext/scalar_constants.hpp> #include <glm/ext/scalar_constants.hpp>
#include "../Actors/TestActor.h" #include "../Actors/TestActor.h"
@@ -10,6 +9,14 @@
#include "Log/Log.hpp" #include "Log/Log.hpp"
#include "Game/Actors/Mesh/Mesh.hpp" #include "Game/Actors/Mesh/Mesh.hpp"
void TestWorld::print_when_camera_move(const Vector3D& loc_)
{
std::string msg = + "(" + name_ + ") camera move to x: " + std::to_string(loc_.x) +
" y: " + std::to_string(loc_.y) +
" z: " + std::to_string(loc_.z);
Loging::Message(msg);
}
TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance) TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance)
{} {}
@@ -22,10 +29,15 @@ void TestWorld::BeginPlay()
Loging::Log("Load actor: " + i.lock()->GetName()); Loging::Log("Load actor: " + i.lock()->GetName());
} }
GetActorsByClass<Camera>()[0].lock()->SetActive(); main_camera_ = GetActorsByClass<Camera>()[0];
//SpawnActorFormClass<TestActor>("TestActor1"); std::shared_ptr<Camera> lock_main_camera = main_camera_.lock();
//std::shared_ptr<SaveMap> save_world = save(); lock_main_camera->SetActive();
//Loging::Log(save_world->serialize()); lock_main_camera->OnSetActorLocate.bind<TestWorld>(
std::static_pointer_cast<TestWorld>(shared_from_this()),
&TestWorld::print_when_camera_move
);
std::shared_ptr<SaveMap> save_world = save();
Loging::Message(save_world->serialize());
} }
void TestWorld::Tick(double delta_time) void TestWorld::Tick(double delta_time)
@@ -36,8 +48,12 @@ void TestWorld::Tick(double delta_time)
time1 += delta_time; time1 += delta_time;
double delta1 = sin(time1); double delta1 = sin(time1);
double delta2 = sin(3*time1); double delta2 = sin(3*time1);
GetActorsByClass<Camera>()[0].lock()->SetActorLocate(Vector3D{2 + delta2, 2 + delta2, 2 + delta2}); std::shared_ptr<Camera> lock_main_camera = main_camera_.lock();
GetActorsByClass<Camera>()[0].lock()->SetActorRotate(Vector3D{-3*glm::pi<double>()/4 + glm::pi<double>()/4 * delta1, glm::pi<double>() / -4, 0}); if (lock_main_camera != nullptr)
{
lock_main_camera->SetActorLocate(Vector3D{2 + delta2, 2 + delta2, 2 + delta2});
lock_main_camera->SetActorRotate(Vector3D{-3*glm::pi<double>()/4 + glm::pi<double>()/4 * delta1, glm::pi<double>() / -4, 0});
}
time += delta_time; time += delta_time;
if (time >= 10.0) if (time >= 10.0)
+6
View File
@@ -2,10 +2,16 @@
#include "Game/World/World.hpp" #include "Game/World/World.hpp"
class Camera;
GENERATE_META(TestWorld) GENERATE_META(TestWorld)
class TestWorld final : public World class TestWorld final : public World
{ {
double time = 0; double time = 0;
std::weak_ptr<Camera> main_camera_;
const std::string name_ = "First test world";
void print_when_camera_move(const Vector3D& loc_);
public: public:
TestWorld(GameInstance& game_instance); TestWorld(GameInstance& game_instance);
@@ -1,8 +1,6 @@
#include "UwURenderEngine.hpp" #include "UwURenderEngine.hpp"
#include <array> #include <array>
#include <stdexcept>
#include <fstream>
#include <chrono> #include <chrono>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
@@ -15,7 +13,6 @@
#include "Game/World/World.hpp" #include "Game/World/World.hpp"
#include "../Game/Actors/Mesh/Mesh.hpp" #include "../Game/Actors/Mesh/Mesh.hpp"
#include "DeviceFunctions/DeviceFunctions.hpp" #include "DeviceFunctions/DeviceFunctions.hpp"
#include "Log/Log.hpp"
RENDER_ENGINE_FACTORY_GENERATE(UwURenderEngine) RENDER_ENGINE_FACTORY_GENERATE(UwURenderEngine)
@@ -407,7 +404,7 @@ UwURenderEngine::~UwURenderEngine()
void UwURenderEngine::start() void UwURenderEngine::start()
{ {
World* world = core_.GetGameInstance()->GetWorld(); std::shared_ptr<World> world = core_.GetGameInstance()->GetWorld();
std::vector<std::weak_ptr<Mesh>> meshes = world->GetActorsByClass<Mesh>(); std::vector<std::weak_ptr<Mesh>> meshes = world->GetActorsByClass<Mesh>();
for (auto& i : meshes) for (auto& i : meshes)
{ {
@@ -4,11 +4,10 @@
#include "ModelManager.hpp" #include "ModelManager.hpp"
#include <vector> #include <vector>
#include <string>
#include <memory> #include <memory>
#include <mutex>
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
#include <mutex>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "VkObjects/DescriptorSetLayout.hpp" #include "VkObjects/DescriptorSetLayout.hpp"