mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(scene): add host game scene and world parameter handling
This commit is contained in:
@@ -18,6 +18,7 @@ public:
|
||||
ChunkGenerator(ServerChunk& chunk);
|
||||
|
||||
static void init();
|
||||
static void init(unsigned seed);
|
||||
static void reload();
|
||||
static const unsigned& seed();
|
||||
static void seed(unsigned s);
|
||||
|
||||
29
include/Cubed/scene/host_game_scene.hpp
Normal file
29
include/Cubed/scene/host_game_scene.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/scene/scene.hpp"
|
||||
#include "Cubed/ui/host_game_ui.hpp"
|
||||
namespace Cubed {
|
||||
class SceneManager;
|
||||
class HostGameScene : public Scene {
|
||||
public:
|
||||
HostGameScene(SceneManager& scene_manager);
|
||||
~HostGameScene();
|
||||
|
||||
HostGameScene(const HostGameScene&) = delete;
|
||||
HostGameScene(HostGameScene&&) = delete;
|
||||
HostGameScene& operator=(const HostGameScene&) = delete;
|
||||
HostGameScene& operator=(HostGameScene&&) = delete;
|
||||
|
||||
void update(float dt) override;
|
||||
void render(Renderer& renderer) override;
|
||||
bool handle_event(const Event& e) override;
|
||||
void on_enter() override;
|
||||
void on_leave() override;
|
||||
void on_re_enter() override;
|
||||
SceneManager& scene_manager();
|
||||
|
||||
private:
|
||||
SceneManager& m_scene_manager;
|
||||
HostGameUI m_ui;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Cubed {
|
||||
class Renderer;
|
||||
|
||||
enum class SceneType { MAIN_MENU, WORLD, CREDITS, SETTINGS };
|
||||
enum class SceneType { MAIN_MENU, WORLD, CREDITS, SETTINGS, HOST_GAME };
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
class App;
|
||||
|
||||
struct WorldSceneParam {
|
||||
bool host_game = true;
|
||||
std::optional<unsigned> seed = std::nullopt;
|
||||
std::string ip{"127.0.0.1"};
|
||||
int port = 25530;
|
||||
};
|
||||
|
||||
class SceneManager {
|
||||
public:
|
||||
SceneManager(const SceneManager&) = delete;
|
||||
@@ -25,6 +33,7 @@ public:
|
||||
void request_pop();
|
||||
|
||||
App& app();
|
||||
WorldSceneParam& world_scene_param();
|
||||
|
||||
private:
|
||||
enum class OperationType { PUSH, POP, CHANGE };
|
||||
@@ -34,6 +43,7 @@ private:
|
||||
};
|
||||
|
||||
App& m_app;
|
||||
WorldSceneParam m_world_param;
|
||||
std::vector<std::unique_ptr<Scene>> m_pending_delete_scene;
|
||||
std::optional<SceneOperation> m_operation;
|
||||
std::stack<std::unique_ptr<Scene>> m_scenes;
|
||||
|
||||
16
include/Cubed/ui/host_game_ui.hpp
Normal file
16
include/Cubed/ui/host_game_ui.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/ui/ui_manager.hpp"
|
||||
namespace Cubed {
|
||||
class HostGameScene;
|
||||
class HostGameUI : public UIManager {
|
||||
public:
|
||||
HostGameUI(HostGameScene& scene);
|
||||
|
||||
void init() override;
|
||||
void on_re_enter();
|
||||
|
||||
private:
|
||||
HostGameScene& m_scene;
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -78,4 +78,7 @@ target_sources(${PROJECT_NAME}
|
||||
scene/settings_scene.cpp
|
||||
ui/combo_button.cpp
|
||||
ui/text_field.cpp
|
||||
scene/host_game_scene.cpp
|
||||
scene/join_game_scene.cpp
|
||||
ui/host_game_ui.cpp
|
||||
)
|
||||
@@ -109,7 +109,11 @@ ChunkGenerator::ChunkGenerator(ServerChunk& chunk) : m_chunk(chunk) {
|
||||
|
||||
void ChunkGenerator::init() {
|
||||
std::random_device d;
|
||||
m_generator_seed = d();
|
||||
init(d());
|
||||
}
|
||||
|
||||
void ChunkGenerator::init(unsigned seed) {
|
||||
m_generator_seed = seed;
|
||||
Logger::info("Chunk Generator Seed {}", m_generator_seed);
|
||||
PerlinNoise3D::init(m_generator_seed);
|
||||
PerlinNoise2D::init(m_generator_seed);
|
||||
|
||||
18
src/scene/host_game_scene.cpp
Normal file
18
src/scene/host_game_scene.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "Cubed/scene/host_game_scene.hpp"
|
||||
|
||||
namespace Cubed {
|
||||
HostGameScene::HostGameScene(SceneManager& scene_manager)
|
||||
: m_scene_manager(scene_manager), m_ui(*this) {}
|
||||
HostGameScene::~HostGameScene() {}
|
||||
|
||||
void HostGameScene::update(float dt) { m_ui.update(dt); }
|
||||
void HostGameScene::render(Renderer& renderer) { m_ui.render(renderer); }
|
||||
bool HostGameScene::handle_event(const Event& e) {
|
||||
return m_ui.handle_event(e);
|
||||
}
|
||||
void HostGameScene::on_enter() { m_ui.init(); }
|
||||
void HostGameScene::on_leave() {}
|
||||
void HostGameScene::on_re_enter() { m_ui.on_re_enter(); }
|
||||
SceneManager& HostGameScene::scene_manager() { return m_scene_manager; }
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
|
||||
#include "Cubed/scene/credits_scene.hpp"
|
||||
#include "Cubed/scene/host_game_scene.hpp"
|
||||
#include "Cubed/scene/main_menu_scene.hpp"
|
||||
#include "Cubed/scene/settings_scene.hpp"
|
||||
#include "Cubed/scene/world_scene.hpp"
|
||||
@@ -97,6 +98,8 @@ std::unique_ptr<Scene> SceneManager::create_scene(SceneType type) {
|
||||
return std::make_unique<CreditsScene>(*this);
|
||||
case SceneType::SETTINGS:
|
||||
return std::make_unique<SettingsScene>(*this);
|
||||
case SceneType::HOST_GAME:
|
||||
return std::make_unique<HostGameScene>(*this);
|
||||
}
|
||||
|
||||
std::string err = std::format("Unknown Scene");
|
||||
@@ -105,4 +108,5 @@ std::unique_ptr<Scene> SceneManager::create_scene(SceneType type) {
|
||||
}
|
||||
|
||||
App& SceneManager::app() { return m_app; }
|
||||
WorldSceneParam& SceneManager::world_scene_param() { return m_world_param; }
|
||||
} // namespace Cubed
|
||||
@@ -97,15 +97,20 @@ bool WorldScene::handle_event(const Event& e) {
|
||||
e);
|
||||
}
|
||||
void WorldScene::on_enter() {
|
||||
|
||||
auto& param = m_scene_manager.world_scene_param();
|
||||
if (param.seed) {
|
||||
ChunkGenerator::init(*param.seed);
|
||||
param.seed = std::nullopt;
|
||||
} else {
|
||||
ChunkGenerator::init();
|
||||
}
|
||||
|
||||
if (!m_argument.is_client) {
|
||||
m_server.start_server(m_argument.port);
|
||||
if (param.host_game) {
|
||||
m_server.start_server(param.port);
|
||||
}
|
||||
m_client = std::make_shared<NetworkClient>(m_client_world);
|
||||
|
||||
m_client->start(m_argument.ip, m_argument.port);
|
||||
m_client->start(param.ip, param.port);
|
||||
// init will send packet
|
||||
m_client_world.init(m_argument.player, m_client);
|
||||
|
||||
|
||||
92
src/ui/host_game_ui.cpp
Normal file
92
src/ui/host_game_ui.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "Cubed/ui/host_game_ui.hpp"
|
||||
|
||||
#include "Cubed/app.hpp"
|
||||
#include "Cubed/scene/host_game_scene.hpp"
|
||||
#include "Cubed/scene/scene_manager.hpp"
|
||||
#include "Cubed/ui/button.hpp"
|
||||
#include "Cubed/ui/column_layout.hpp"
|
||||
#include "Cubed/ui/image.hpp"
|
||||
#include "Cubed/ui/text_field.hpp"
|
||||
namespace Cubed {
|
||||
HostGameUI::HostGameUI(HostGameScene& scene) : m_scene(scene) {}
|
||||
void HostGameUI::init() {
|
||||
auto bi = std::make_unique<Image>(nullptr);
|
||||
auto& renderer = m_scene.scene_manager().app().renderer();
|
||||
auto& texture_manager = m_scene.scene_manager().app().texture_manager();
|
||||
|
||||
bi->set_window_size(renderer.window_width(), renderer.window_height());
|
||||
bi->set_anchor(Anchor::TOP_LEFT);
|
||||
bi->set_image("texture/ui/background.png", texture_manager);
|
||||
bi->set_fill(true);
|
||||
|
||||
auto& rect = bi->add_child<Rect>();
|
||||
rect.set_fill(true);
|
||||
rect.set_alpha(0.7f);
|
||||
rect.set_color(Color::BLACK);
|
||||
|
||||
auto& layout = rect.add_child<ColumnLayout>();
|
||||
layout.set_anchor(Anchor::CENTER);
|
||||
layout.set_offset({0, 20});
|
||||
layout.set_spacing(20.0f);
|
||||
auto& param = m_scene.scene_manager().world_scene_param();
|
||||
param.host_game = true;
|
||||
{
|
||||
auto& text_seed = layout.add_child<TextField>();
|
||||
text_seed.set_show_text("WorldSeed");
|
||||
text_seed.set_default_image(texture_manager);
|
||||
text_seed.set_on_finish([this, &text_seed]() {
|
||||
unsigned seed = 0;
|
||||
auto& text = text_seed.input_text();
|
||||
auto r =
|
||||
std::from_chars(text.data(), text.data() + text.size(), seed);
|
||||
|
||||
if (r.ec != std::errc{} || r.ptr != text.data() + text.size()) {
|
||||
Logger::error("Invalid seed: {}", text);
|
||||
return;
|
||||
}
|
||||
m_scene.scene_manager().world_scene_param().seed = seed;
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& text_port = layout.add_child<TextField>();
|
||||
text_port.set_default_image(texture_manager);
|
||||
text_port.set_show_text("Port");
|
||||
text_port.set_on_finish([this, &text_port]() {
|
||||
int port = 25530;
|
||||
auto& text = text_port.input_text();
|
||||
auto r =
|
||||
std::from_chars(text.data(), text.data() + text.size(), port);
|
||||
if (r.ec != std::errc{} || r.ptr != text.data() + text.size()) {
|
||||
Logger::error("Invalid port: {}", text);
|
||||
return;
|
||||
}
|
||||
if (port > 65535 || port < 0) {
|
||||
|
||||
Logger::error("Port {} out of range", port);
|
||||
return;
|
||||
}
|
||||
m_scene.scene_manager().world_scene_param().port = port;
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& button = layout.add_child<Button>();
|
||||
button.set_default_image(texture_manager);
|
||||
button.set_text("Start Game");
|
||||
button.set_clicked([this, &button]() {
|
||||
button.set_enable(false);
|
||||
m_scene.scene_manager().request_change(SceneType::WORLD);
|
||||
});
|
||||
}
|
||||
{
|
||||
auto& button = layout.add_child<Button>();
|
||||
button.set_default_image(texture_manager);
|
||||
button.set_text("Return");
|
||||
button.set_clicked([this, &button]() {
|
||||
button.set_enable(false);
|
||||
m_scene.scene_manager().request_pop();
|
||||
});
|
||||
}
|
||||
m_root_widget = std::move(bi);
|
||||
}
|
||||
void HostGameUI::on_re_enter() {}
|
||||
} // namespace Cubed
|
||||
@@ -32,10 +32,10 @@ void MainMenuUIManager::init() {
|
||||
|
||||
start_game_button.set_background_image("texture/ui/button001.png",
|
||||
texture_manager);
|
||||
start_game_button.set_text("Start Game");
|
||||
start_game_button.set_text("Host Game");
|
||||
start_game_button.set_clicked([this, &start_game_button]() {
|
||||
start_game_button.set_enable(false);
|
||||
m_scene.scene_manager().request_push(SceneType::WORLD);
|
||||
m_scene.scene_manager().request_push(SceneType::HOST_GAME);
|
||||
});
|
||||
m_pending_enable.emplace_back(&start_game_button);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ void MainMenuUIManager::init() {
|
||||
auto& exit_game = layout.add_child<Button>();
|
||||
exit_game.set_background_image("texture/ui/button001.png",
|
||||
texture_manager);
|
||||
exit_game.set_text("Exit");
|
||||
exit_game.set_text("Quit");
|
||||
|
||||
exit_game.set_clicked([this]() {
|
||||
m_scene.scene_manager().app().window().should_close_window();
|
||||
@@ -76,11 +76,18 @@ void MainMenuUIManager::init() {
|
||||
m_widgets.try_emplace("background", image.get());
|
||||
m_widgets.try_emplace("main menu layout", &layout);
|
||||
{
|
||||
constexpr float SCALE = 0.5f;
|
||||
auto& info_layout = image->add_child<ColumnLayout>();
|
||||
info_layout.set_anchor(Anchor::BOTTOM_LEFT);
|
||||
info_layout.set_spacing(10);
|
||||
info_layout.set_child_anchor(ColumnLayoutAnchor::LEFT);
|
||||
auto& player_name = info_layout.add_child<Label>();
|
||||
player_name.set_scale(SCALE);
|
||||
player_name.set_text(std::format(
|
||||
"Player: {}", m_scene.scene_manager().app().argument().player));
|
||||
|
||||
auto& version = info_layout.add_child<Label>();
|
||||
version.set_scale(0.5f);
|
||||
version.set_scale(SCALE);
|
||||
std::string version_str = "Cubed: " CUBED_VERSION;
|
||||
#ifdef DEBUG_MODE
|
||||
version_str.append("-debug");
|
||||
|
||||
Reference in New Issue
Block a user