Compare commits

..

2 Commits

Author SHA1 Message Date
ca82d6a447 feat: add Spectator Mode 2026-04-18 20:01:29 +08:00
0a0024361d fix: negative seed values 2026-04-18 19:11:58 +08:00
7 changed files with 101 additions and 17 deletions

View File

@@ -17,6 +17,7 @@ public:
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods); static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods);
static void window_focus_callback(GLFWwindow* window, int focused); static void window_focus_callback(GLFWwindow* window, int focused);
static void window_reshape_callback(GLFWwindow* window, int new_width, int new_height); static void window_reshape_callback(GLFWwindow* window, int new_width, int new_height);
static void mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
static int start_cubed_application(int argc, char** argv); static int start_cubed_application(int argc, char** argv);
static unsigned int seed(); static unsigned int seed();

View File

@@ -0,0 +1,19 @@
#pragma once
#include <stdexcept>
#include <string>
enum class GameMode {
CREATIVE,
SPECTATOR
};
inline std::string to_str(GameMode mode) {
using enum GameMode;
switch (mode) {
case CREATIVE:
return {"Creative"};
case SPECTATOR:
return {"Spective"};
}
throw std::invalid_argument{"GameMode is invaild"};
}

View File

@@ -5,6 +5,7 @@
#include <Cubed/config.hpp> #include <Cubed/config.hpp>
#include <Cubed/gameplay/block.hpp> #include <Cubed/gameplay/block.hpp>
#include <Cubed/gameplay/chunk_pos.hpp> #include <Cubed/gameplay/chunk_pos.hpp>
#include <Cubed/gameplay/game_mode.hpp>
#include <Cubed/input.hpp> #include <Cubed/input.hpp>
#include <optional> #include <optional>
@@ -19,6 +20,7 @@ class World;
class Player { class Player {
private: private:
using enum GameMode;
constexpr static float WALK_SPEED = 4.5f; constexpr static float WALK_SPEED = 4.5f;
constexpr static float RUN_SPEED = 7.0f; constexpr static float RUN_SPEED = 7.0f;
constexpr static float ACCELERATION = 10.0f; constexpr static float ACCELERATION = 10.0f;
@@ -54,7 +56,7 @@ private:
Gait m_gait = Gait::WALK; Gait m_gait = Gait::WALK;
MoveState m_move_state {}; MoveState m_move_state {};
GameMode m_game_mode = CREATIVE;
std::optional<LookBlock> m_look_block = std::nullopt; std::optional<LookBlock> m_look_block = std::nullopt;
std::string m_name {}; std::string m_name {};
World& m_world; World& m_world;
@@ -79,10 +81,11 @@ public:
const glm::vec3& get_player_pos() const; const glm::vec3& get_player_pos() const;
const MoveState& get_move_state() const; const MoveState& get_move_state() const;
void change_mode(GameMode mode);
void set_player_pos(const glm::vec3& pos); void set_player_pos(const glm::vec3& pos);
void update(float delta_time); void update(float delta_time);
void update_front_vec(float offset_x, float offset_y); void update_front_vec(float offset_x, float offset_y);
void update_player_move_state(int key, int action); void update_player_move_state(int key, int action);
void update_scroll(double yoffset);
}; };

View File

@@ -39,7 +39,7 @@ void App::init() {
glfwSetWindowFocusCallback(m_window.get_glfw_window(), window_focus_callback); glfwSetWindowFocusCallback(m_window.get_glfw_window(), window_focus_callback);
glfwSetWindowSizeCallback(m_window.get_glfw_window(), window_reshape_callback); glfwSetWindowSizeCallback(m_window.get_glfw_window(), window_reshape_callback);
glfwSetKeyCallback(m_window.get_glfw_window(), key_callback); glfwSetKeyCallback(m_window.get_glfw_window(), key_callback);
glfwSetScrollCallback(m_window.get_glfw_window(), mouse_scroll_callback);
PerlinNoise::init(); PerlinNoise::init();
m_renderer.init(); m_renderer.init();
@@ -132,7 +132,11 @@ void App::window_reshape_callback(GLFWwindow* window, int new_width, int new_hei
app->m_window.update_viewport(); app->m_window.update_viewport();
} }
void App::mouse_scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
App* app = static_cast<App*>(glfwGetWindowUserPointer(window));
auto& player = app->m_world.get_player("TestPlayer");
player.update_scroll(yoffset);
}
void App::render() { void App::render() {

View File

@@ -22,6 +22,7 @@ void DebugCollector::init_text() {
Text gpu_text("gpu"); Text gpu_text("gpu");
Text opengl_version_text("opengl_version"); Text opengl_version_text("opengl_version");
Text biome_text("biome"); Text biome_text("biome");
Text speed_text("speed");
version_text version_text
.position(0.0f, 100.0f) .position(0.0f, 100.0f)
.scale(0.8f) .scale(0.8f)
@@ -73,6 +74,10 @@ void DebugCollector::init_text() {
.text("Biome: ") .text("Biome: ")
.scale(0.8f) .scale(0.8f)
.position(0.0f, 500.0f); .position(0.0f, 500.0f);
speed_text
.text("Speed: 0 m/s")
.scale(0.8f)
.position(0.0f, 550.0f);
m_texts.insert({version_text.uuid(), std::move(version_text)}); m_texts.insert({version_text.uuid(), std::move(version_text)});
m_texts.insert({fps_text.uuid(), std::move(fps_text)}); m_texts.insert({fps_text.uuid(), std::move(fps_text)});
m_texts.insert({player_pos_text.uuid(), std::move(player_pos_text)}); m_texts.insert({player_pos_text.uuid(), std::move(player_pos_text)});
@@ -83,6 +88,7 @@ void DebugCollector::init_text() {
m_texts.insert({gpu_text.uuid(), std::move(gpu_text)}); m_texts.insert({gpu_text.uuid(), std::move(gpu_text)});
m_texts.insert({opengl_version_text.uuid(), std::move(opengl_version_text)}); m_texts.insert({opengl_version_text.uuid(), std::move(opengl_version_text)});
m_texts.insert({biome_text.uuid(), std::move(biome_text)}); m_texts.insert({biome_text.uuid(), std::move(biome_text)});
m_texts.insert({speed_text.uuid(), std::move(speed_text)});
} }
std::unordered_map<std::size_t, Text>& DebugCollector::all_texts() { std::unordered_map<std::size_t, Text>& DebugCollector::all_texts() {

View File

@@ -7,7 +7,6 @@
#include <Cubed/tools/log.hpp> #include <Cubed/tools/log.hpp>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
Player::Player(World& world, const std::string& name) : Player::Player(World& world, const std::string& name) :
m_world(world), m_world(world),
m_name(name) m_name(name)
@@ -131,19 +130,34 @@ bool Player::ray_cast(const glm::vec3& start, const glm::vec3& front, glm::ivec3
return false; return false;
} }
void Player::change_mode(GameMode mode) {
m_game_mode = mode;
Logger::info("Change GameMode to {}", to_str(mode));
if (mode == CREATIVE) {
is_fly = false;
m_gait = Gait::WALK;
} else if (mode == SPECTATOR) {
is_fly = true;
m_gait = Gait::RUN;
}
}
void Player::set_player_pos(const glm::vec3& pos) { void Player::set_player_pos(const glm::vec3& pos) {
m_player_pos = pos; m_player_pos = pos;
} }
void Player::update(float delta_time) { void Player::update(float delta_time) {
update_move(delta_time); update_move(delta_time);
update_lookup_block(); update_lookup_block();
check_player_chunk_transition(); check_player_chunk_transition();
std::string player_pos = std::format("x: {:.2f} y: {:.2f} z: {:.2f}", m_player_pos.x, m_player_pos.y, m_player_pos.z); DebugCollector::get().report("player_pos",
DebugCollector::get().report("player_pos", player_pos); std::format("x: {:.2f} y: {:.2f} z: {:.2f}",
m_player_pos.x, m_player_pos.y, m_player_pos.z
));
DebugCollector::get().report("speed", std::format("Speed: {:.2} m/s", speed));
} }
void Player::update_player_move_state(int key, int action) { void Player::update_player_move_state(int key, int action) {
@@ -154,8 +168,11 @@ void Player::update_player_move_state(int key, int action) {
} }
if (action == GLFW_RELEASE) { if (action == GLFW_RELEASE) {
m_move_state.forward = false; m_move_state.forward = false;
if (m_game_mode != SPECTATOR) {
m_gait = Gait::WALK; m_gait = Gait::WALK;
} }
}
break; break;
case GLFW_KEY_S: case GLFW_KEY_S:
if (action == GLFW_PRESS) { if (action == GLFW_PRESS) {
@@ -185,8 +202,10 @@ void Player::update_player_move_state(int key, int action) {
if (action == GLFW_PRESS) { if (action == GLFW_PRESS) {
m_move_state.up = true; m_move_state.up = true;
if (space_on) { if (space_on) {
if (m_game_mode == CREATIVE) {
is_fly = !is_fly ? true : false; is_fly = !is_fly ? true : false;
y_speed = 0.0f; y_speed = 0.0f;
}
space_on = false; space_on = false;
space_on_time = 0.0f; space_on_time = 0.0f;
} else { } else {
@@ -210,6 +229,15 @@ void Player::update_player_move_state(int key, int action) {
m_gait = Gait::RUN; m_gait = Gait::RUN;
} }
break; break;
case GLFW_KEY_F4:
if (action == GLFW_PRESS) {
if (m_game_mode == CREATIVE) {
change_mode(SPECTATOR);
} else {
change_mode(CREATIVE);
}
}
break;
} }
} }
@@ -318,12 +346,14 @@ void Player::update_move(float delta_time) {
if (delta_time > 1.0f) { if (delta_time > 1.0f) {
return; return;
} }
if (m_game_mode != SPECTATOR) {
if (m_gait == Gait::RUN) { if (m_gait == Gait::RUN) {
max_speed = RUN_SPEED; max_speed = RUN_SPEED;
} }
if (m_gait == Gait::WALK) { if (m_gait == Gait::WALK) {
max_speed = WALK_SPEED; max_speed = WALK_SPEED;
} }
}
if (space_on) { if (space_on) {
space_on_time += delta_time; space_on_time += delta_time;
@@ -391,6 +421,9 @@ void Player::update_move(float delta_time) {
void Player::update_x_move() { void Player::update_x_move() {
m_player_pos.x += move_distance.x; m_player_pos.x += move_distance.x;
if (m_game_mode == SPECTATOR) {
return;
}
AABB player_box = get_aabb(); AABB player_box = get_aabb();
int minx = std::floor(player_box.min.x); int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x); int maxx = std::floor(player_box.max.x);
@@ -420,6 +453,9 @@ void Player::update_x_move() {
void Player::update_y_move() { void Player::update_y_move() {
m_player_pos.y += move_distance.y; m_player_pos.y += move_distance.y;
if (m_game_mode == SPECTATOR) {
return;
}
AABB player_box = get_aabb(); AABB player_box = get_aabb();
int minx = std::floor(player_box.min.x); int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x); int maxx = std::floor(player_box.max.x);
@@ -453,6 +489,9 @@ void Player::update_y_move() {
void Player::update_z_move() { void Player::update_z_move() {
m_player_pos.z += move_distance.z; m_player_pos.z += move_distance.z;
if (m_game_mode == SPECTATOR) {
return;
}
AABB player_box = get_aabb(); AABB player_box = get_aabb();
int minx = std::floor(player_box.min.x); int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x); int maxx = std::floor(player_box.max.x);
@@ -479,3 +518,15 @@ void Player::update_z_move() {
} }
} }
} }
void Player::update_scroll(double yoffset) {
if (m_game_mode == SPECTATOR) {
if (yoffset > 0) {
max_speed += 1.0f;
} else {
if (max_speed > WALK_SPEED) {
max_speed -= 1.0f;
}
}
}
}

View File

@@ -10,7 +10,7 @@
void PerlinNoise::init() { void PerlinNoise::init() {
p.resize(256); p.resize(256);
std::iota(p.begin(), p.end(), 0); std::iota(p.begin(), p.end(), 0);
int seed = std::random_device{}(); auto seed = std::random_device{}();
Logger::info("Init Perlin Noise With Seed {}", seed); Logger::info("Init Perlin Noise With Seed {}", seed);
std::shuffle(p.begin(), p.end(), std::mt19937(seed)); std::shuffle(p.begin(), p.end(), std::mt19937(seed));