feat(scene): add join game scene and UI

This commit is contained in:
2026-07-15 21:30:53 +08:00
parent b9a013a916
commit 138171410d
8 changed files with 181 additions and 1 deletions

View File

@@ -0,0 +1,28 @@
#pragma once
#include "Cubed/scene/scene.hpp"
#include "Cubed/ui/join_game_ui.hpp"
namespace Cubed {
class SceneManager;
class JoinGameScene : public Scene {
public:
JoinGameScene(const JoinGameScene&) = delete;
JoinGameScene(JoinGameScene&&) = delete;
JoinGameScene& operator=(const JoinGameScene&) = delete;
JoinGameScene& operator=(JoinGameScene&&) = delete;
JoinGameScene(SceneManager& scene_manager);
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;
JoinGameUI m_ui;
};
} // namespace Cubed

View File

@@ -3,7 +3,14 @@
namespace Cubed {
class Renderer;
enum class SceneType { MAIN_MENU, WORLD, CREDITS, SETTINGS, HOST_GAME };
enum class SceneType {
MAIN_MENU,
WORLD,
CREDITS,
SETTINGS,
HOST_GAME,
JOIN_GAME
};
class Scene {
public:

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Cubed/ui/ui_manager.hpp"
namespace Cubed {
class JoinGameScene;
class JoinGameUI : public UIManager {
public:
JoinGameUI(const JoinGameUI&) = delete;
JoinGameUI(JoinGameUI&&) = delete;
JoinGameUI& operator=(const JoinGameUI&) = delete;
JoinGameUI& operator=(JoinGameUI&&) = delete;
JoinGameUI(JoinGameScene& m_scene);
void init() override;
void on_re_enter();
private:
JoinGameScene& m_scene;
};
} // namespace Cubed

View File

@@ -81,4 +81,5 @@ target_sources(${PROJECT_NAME}
scene/host_game_scene.cpp
scene/join_game_scene.cpp
ui/host_game_ui.cpp
ui/join_game_ui.cpp
)

View File

@@ -0,0 +1,16 @@
#include "Cubed/scene/join_game_scene.hpp"
namespace Cubed {
JoinGameScene::JoinGameScene(SceneManager& scene_manager)
: m_scene_manager(scene_manager), m_ui(*this) {}
void JoinGameScene::update(float dt) { m_ui.update(dt); }
void JoinGameScene::render(Renderer& renderer) { m_ui.render(renderer); }
bool JoinGameScene::handle_event(const Event& e) {
return m_ui.handle_event(e);
}
void JoinGameScene::on_enter() { m_ui.init(); }
void JoinGameScene::on_leave() {}
void JoinGameScene::on_re_enter() { m_ui.on_re_enter(); }
SceneManager& JoinGameScene::scene_manager() { return m_scene_manager; }
} // namespace Cubed

View File

@@ -2,6 +2,7 @@
#include "Cubed/scene/credits_scene.hpp"
#include "Cubed/scene/host_game_scene.hpp"
#include "Cubed/scene/join_game_scene.hpp"
#include "Cubed/scene/main_menu_scene.hpp"
#include "Cubed/scene/settings_scene.hpp"
#include "Cubed/scene/world_scene.hpp"
@@ -100,6 +101,8 @@ std::unique_ptr<Scene> SceneManager::create_scene(SceneType type) {
return std::make_unique<SettingsScene>(*this);
case SceneType::HOST_GAME:
return std::make_unique<HostGameScene>(*this);
case SceneType::JOIN_GAME:
return std::make_unique<JoinGameScene>(*this);
}
std::string err = std::format("Unknown Scene");

93
src/ui/join_game_ui.cpp Normal file
View File

@@ -0,0 +1,93 @@
#include "Cubed/ui/join_game_ui.hpp"
#include "Cubed/app.hpp"
#include "Cubed/scene/join_game_scene.hpp"
#include "Cubed/ui/button.hpp"
#include "Cubed/ui/column_layout.hpp"
#include "Cubed/ui/text_field.hpp"
namespace Cubed {
JoinGameUI::JoinGameUI(JoinGameScene& scene) : m_scene(scene) {}
void JoinGameUI::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_ip = layout.add_child<TextField>();
text_ip.set_show_text("Server Ip");
text_ip.set_default_image(texture_manager);
text_ip.set_on_finish([this, &text_ip]() {
auto& ip = text_ip.input_text();
auto p = ip.find(":");
if (p == std::string::npos) {
Logger::error("Missing ':'");
return;
}
auto addr = ip.substr(0, p);
if (addr.empty()) {
Logger::error("Empty address");
return;
}
auto port_str = ip.substr(p + 1);
if (port_str.empty()) {
Logger::error("Missing port");
return;
}
int port = 25530;
auto r = std::from_chars(port_str.data(),
port_str.data() + port_str.size(), port);
if (r.ec != std::errc{} ||
r.ptr != port_str.data() + port_str.size()) {
Logger::error("Invalid port: {}", port_str);
return;
}
if (port > 65535 || port < 0) {
Logger::error("Port {} out of range", port);
return;
}
auto& param = m_scene.scene_manager().world_scene_param();
param.port = port;
param.ip = addr;
});
}
{
auto& button = layout.add_child<Button>();
button.set_default_image(texture_manager);
button.set_text("Join 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 JoinGameUI::on_re_enter() {}
} // namespace Cubed

View File

@@ -39,7 +39,18 @@ void MainMenuUIManager::init() {
});
m_pending_enable.emplace_back(&start_game_button);
}
{
auto& start_game_button = layout.add_child<Button>();
start_game_button.set_background_image("texture/ui/button001.png",
texture_manager);
start_game_button.set_text("Join Game");
start_game_button.set_clicked([this, &start_game_button]() {
start_game_button.set_enable(false);
m_scene.scene_manager().request_push(SceneType::JOIN_GAME);
});
m_pending_enable.emplace_back(&start_game_button);
}
{
auto& button = layout.add_child<Button>();
button.set_default_image(texture_manager);