feat(world): add day/night cycle with server tick system

This commit is contained in:
2026-06-16 16:17:47 +08:00
parent f43ef64691
commit a4f92e3659
9 changed files with 175 additions and 6 deletions

View File

@@ -263,6 +263,29 @@ void DevPanel::show_biome_table_bar() {
}
}
void DevPanel::show_time_table_bar() {
World& world = m_app.world();
ImGui::Text("Game Tick %lld", world.game_tick());
ImGui::Text("Day Tick %lld", world.day_tick());
ImGui::Text("Set Day Tick");
ImGui::SameLine();
if (ImGui::SliderInt("DayTick", &m_pre_set_day_tick, 0, DAY_TIME)) {
}
ImGui::SameLine();
if (ImGui::Button("Save##DayTick")) {
world.day_tick(static_cast<TickType>(m_pre_set_day_tick));
}
ImGui::Text("MSPT %d", world.per_tick_time());
ImGui::Text("Set MSPT");
ImGui::SameLine();
if (ImGui::SliderInt("SetMSPT", &m_pre_set_tick_speed, 0, 200)) {
}
ImGui::SameLine();
if (ImGui::Button("Save##MSPT")) {
world.per_tick_time(m_pre_set_tick_speed);
}
}
void DevPanel::show_cave_table_bar() {
auto& cave_carcer = m_app.world().cave_carcer();
@@ -457,6 +480,10 @@ void DevPanel::show_world_tab_item() {
ImGui::Text("Chunk Build Progress\n");
ImGui::ProgressBar(m_app.world().chunk_gen_fraction());
if (ImGui::BeginTabBar("World Settings")) {
if (ImGui::BeginTabItem("Time")) {
show_time_table_bar();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Cave")) {
show_cave_table_bar();
ImGui::EndTabItem();

View File

@@ -7,6 +7,8 @@
#include <execution>
using namespace std::chrono;
namespace Cubed {
struct ChunkRenderData {
@@ -18,6 +20,7 @@ World::World() {}
World::~World() {
stop_gen_thread();
stop_server_thread();
m_chunks.clear();
{
std::lock_guard lk(m_delete_vbo_mutex);
@@ -86,6 +89,8 @@ void World::init_world() {
auto d = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
Logger::info("Chunk Block Init Finish, Time Consuming: {}", d);
start_server_thread();
Logger::info("TestPlayer Create Finish");
}
void World::init_chunks() {
@@ -727,6 +732,11 @@ void World::start_gen_thread() {
});
}
void World::start_server_thread() {
m_server_thread = std::thread(
[this]() { serever_run(m_server_stop_source.get_token()); });
}
void World::stop_gen_thread() {
m_gen_running = false;
m_gen_cv.notify_all();
@@ -736,6 +746,23 @@ void World::stop_gen_thread() {
Logger::info("Gen Thread Stopped");
}
void World::stop_server_thread() {
m_server_stop_source.request_stop();
if (m_server_thread.joinable()) {
m_server_thread.join();
}
}
void World::serever_run(std::stop_token stoken) {
Logger::info("Server Thread Started!");
while (!stoken.stop_requested()) {
std::this_thread::sleep_for(milliseconds(m_per_tick_time));
++m_game_ticks;
m_day_tick = (++m_day_tick) % DAY_TIME;
}
Logger::info("Server Thread Stopped!");
}
void World::need_gen() {
if (!m_could_gen) {
Logger::warn("It is generating or consuming new chunks");
@@ -1006,6 +1033,47 @@ std::vector<glm::vec4>& World::planes() { return m_planes; }
std::vector<ChunkRenderSnapshot>& World::render_snapshots() {
return m_render_snapshots;
};
glm::vec3 World::sunlight_dir() const { return m_sunlight_dir; }
/*
glm::vec3 World::sunlight_dir() const {
float t = static_cast<float>(m_day_tick) / DAY_TIME;
float azimuth = glm::radians(90.0f - t * 360.0f);
float altitude =
glm::half_pi<float>() * sin((t - 0.25f) * glm::two_pi<float>());
glm::vec3 dir{cos(altitude) * cos(azimuth), sin(altitude),
cos(altitude) * sin(azimuth)};
return glm::normalize(dir);
}
*/
glm::vec3 World::sunlight_dir() const {
float altitude = sin((m_day_tick - 6 * PER_HOUR) /
static_cast<float>(DAY_TIME / 2) * std::numbers::pi) *
90.0f;
float t = static_cast<float>(m_day_tick) / DAY_TIME;
float azimuth = 90.0f - 360.0f * (t - 0.25f);
float alt = glm::radians(altitude);
float az = glm::radians(azimuth);
glm::vec3 dir;
dir.x = cos(alt) * sin(az);
dir.y = sin(alt);
dir.z = cos(alt) * cos(az);
return glm::normalize(-dir);
}
TickType World::game_tick() const { return m_game_ticks.load(); }
TickType World::day_tick() const { return m_day_tick.load(); }
void World::day_tick(TickType tick) {
tick %= DAY_TIME;
m_day_tick = tick;
}
int World::per_tick_time() const { return m_per_tick_time.load(); }
void World::per_tick_time(int ms) { m_per_tick_time = ms; }
} // namespace Cubed

View File

@@ -257,13 +257,44 @@ void Renderer::render_sky() {
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
glUniform3fv(shader.loc("color"), 1, glm::value_ptr(SKY_COLOR));
glBindVertexArray(m_vao[1]);
glDisable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLES, 0, 36);
glEnable(GL_DEPTH_TEST);
// draw sun and moon
glDepthMask(GL_FALSE);
glBindVertexArray(m_vao[0]);
// draw sum
glm::vec3 sun_pos = m_camera.get_camera_pos() +
normalize(-m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
glm::vec3 sun_view_pos = glm::vec3(m_v_mat * glm::vec4(sun_pos, 1.0f));
m_mv_mat = glm::translate(glm::mat4(1.0f), sun_view_pos) *
glm::scale(glm::mat4(1.0f), glm::vec3(SUN_SIZE)) *
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
glUniform3fv(shader.loc("color"), 1, glm::value_ptr(SUN_COLOR));
glDrawArrays(GL_TRIANGLES, 0, 6);
glm::vec3 moon_pos = m_camera.get_camera_pos() +
normalize(m_world.sunlight_dir()) * (FAR_PLANE * 0.9f);
glm::vec3 moon_view_pos = glm::vec3(m_v_mat * glm::vec4(moon_pos, 1.0f));
m_mv_mat = glm::translate(glm::mat4(1.0f), moon_view_pos) *
glm::scale(glm::mat4(1.0f), glm::vec3(MOON_SIZE)) *
glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, -0.5f, 0.0f));
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_mv_mat));
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_p_mat));
glUniform3fv(shader.loc("color"), 1, glm::value_ptr(MOON_COLOR));
glDrawArrays(GL_TRIANGLES, 0, 6);
glDepthMask(GL_TRUE);
}
void Renderer::render_text() {
@@ -343,7 +374,8 @@ void Renderer::update_fov(float fov) {
void Renderer::update_proj_matrix(float aspect, float width, float height) {
m_aspect = aspect;
m_p_mat = glm::perspective(glm::radians(m_fov), aspect, 0.1f, 1000.0f);
m_p_mat =
glm::perspective(glm::radians(m_fov), aspect, NEAR_PLANE, FAR_PLANE);
m_ui_proj = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
// scale and then translate
m_ui_m_matrix =