Compare commits
No commits in common. "9d60dddcc2dfa2efaf182cb9bd655389fbcb16bb" and "90730990ca55de6544052ba76e821e66888e9461" have entirely different histories.
9d60dddcc2
...
90730990ca
@ -3,7 +3,7 @@ CXXFLAGS = -std=c++20 -Wall -Wextra -O2 -I.
|
|||||||
LDFLAGS = -lraylib -lboost_system -lpthread -lGL -lm -ldl -lrt -lX11
|
LDFLAGS = -lraylib -lboost_system -lpthread -lGL -lm -ldl -lrt -lX11
|
||||||
|
|
||||||
TARGET = game
|
TARGET = game
|
||||||
SOURCES = main.cpp entity/Entity.cpp entity/player/PlayerController.cpp net/NetworkManager.cpp sky/Sky.cpp
|
SOURCES = main.cpp entity/Entity.cpp entity/player/PlayerController.cpp net/NetworkManager.cpp
|
||||||
OBJECTS = $(SOURCES:.cpp=.o)
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|||||||
@ -12,10 +12,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
|
||||||
#include "entity/player/PlayerController.hpp"
|
#include "entity/player/PlayerController.hpp"
|
||||||
#include "net/NetworkManager.hpp"
|
#include "net/NetworkManager.hpp"
|
||||||
#include "sky/Sky.hpp"
|
|
||||||
|
|
||||||
constexpr int WORLD_SIZE = 100;
|
constexpr int WORLD_SIZE = 100;
|
||||||
constexpr float WORLD_SCALE = 10.0f;
|
constexpr float WORLD_SCALE = 10.0f;
|
||||||
@ -114,7 +112,6 @@ class Game {
|
|||||||
Model playerModel;
|
Model playerModel;
|
||||||
Heightmap heightmap;
|
Heightmap heightmap;
|
||||||
NetworkManager network;
|
NetworkManager network;
|
||||||
std::unique_ptr<Sky> sky;
|
|
||||||
Vector3 playerPos{0, 0, 0};
|
Vector3 playerPos{0, 0, 0};
|
||||||
Texture2D terrainTexture;
|
Texture2D terrainTexture;
|
||||||
std::unordered_map<std::string, Texture2D> playerTextures;
|
std::unordered_map<std::string, Texture2D> playerTextures;
|
||||||
@ -136,9 +133,6 @@ public:
|
|||||||
InitWindow(1280, 720, "Multiplayer Terrain Game");
|
InitWindow(1280, 720, "Multiplayer Terrain Game");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
// Initialize sky after window is created
|
|
||||||
sky = std::make_unique<Sky>();
|
|
||||||
|
|
||||||
// Load heightmap
|
// Load heightmap
|
||||||
if (!heightmap.load("../assets/heightmap.bin")) {
|
if (!heightmap.load("../assets/heightmap.bin")) {
|
||||||
std::cerr << "Failed to load heightmap\n";
|
std::cerr << "Failed to load heightmap\n";
|
||||||
@ -228,17 +222,6 @@ private:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sky
|
|
||||||
sky->update(GetFrameTime());
|
|
||||||
|
|
||||||
// Time of day controls (for testing)
|
|
||||||
if (IsKeyPressed(KEY_T)) {
|
|
||||||
float currentTime = sky->getTimeOfDay();
|
|
||||||
currentTime += 0.1f;
|
|
||||||
if (currentTime > 1.0f) currentTime -= 1.0f;
|
|
||||||
sky->setTimeOfDay(currentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get server position and update player controller
|
// Get server position and update player controller
|
||||||
playerPos = network.getPosition();
|
playerPos = network.getPosition();
|
||||||
playerController.setPlayerPosition(playerPos);
|
playerController.setPlayerPosition(playerPos);
|
||||||
@ -334,8 +317,6 @@ private:
|
|||||||
|
|
||||||
void render() {
|
void render() {
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|
||||||
// Clear with a default color first
|
|
||||||
ClearBackground(SKYBLUE);
|
ClearBackground(SKYBLUE);
|
||||||
|
|
||||||
switch (gameState) {
|
switch (gameState) {
|
||||||
@ -400,11 +381,6 @@ private:
|
|||||||
|
|
||||||
void renderGame() {
|
void renderGame() {
|
||||||
BeginMode3D(playerController.getCamera());
|
BeginMode3D(playerController.getCamera());
|
||||||
|
|
||||||
// Render skybox first (it will handle its own depth settings)
|
|
||||||
if (sky) {
|
|
||||||
sky->renderSkybox(playerController.getCamera());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw terrain
|
// Draw terrain
|
||||||
DrawModel(terrainModel, {0, 0, 0}, 1.0f, WHITE);
|
DrawModel(terrainModel, {0, 0, 0}, 1.0f, WHITE);
|
||||||
@ -428,19 +404,11 @@ private:
|
|||||||
DrawText(TextFormat("Logged in as: %s", currentUsername.c_str()), 10, 10, 20, WHITE);
|
DrawText(TextFormat("Logged in as: %s", currentUsername.c_str()), 10, 10, 20, WHITE);
|
||||||
DrawText("WASD: Move | Q/E: Strafe | Right-Click: Rotate Camera", 10, 35, 20, WHITE);
|
DrawText("WASD: Move | Q/E: Strafe | Right-Click: Rotate Camera", 10, 35, 20, WHITE);
|
||||||
DrawText("Left/Right Arrow: Change Color | Mouse Wheel: Zoom | ESC: Logout", 10, 60, 20, WHITE);
|
DrawText("Left/Right Arrow: Change Color | Mouse Wheel: Zoom | ESC: Logout", 10, 60, 20, WHITE);
|
||||||
DrawText("T: Change Time of Day", 10, 85, 20, WHITE);
|
|
||||||
if (network.isConnected()) {
|
if (network.isConnected()) {
|
||||||
std::string colorText = "Your color: " + network.getPlayerColor();
|
std::string colorText = "Your color: " + network.getPlayerColor();
|
||||||
DrawText(colorText.c_str(), 10, 110, 20, WHITE);
|
DrawText(colorText.c_str(), 10, 85, 20, WHITE);
|
||||||
}
|
}
|
||||||
|
DrawFPS(10, 110);
|
||||||
// Show time of day
|
|
||||||
float timeHour = sky->getTimeOfDay() * 24.0f;
|
|
||||||
int hour = (int)timeHour;
|
|
||||||
int minute = (int)((timeHour - hour) * 60);
|
|
||||||
DrawText(TextFormat("Time: %02d:%02d", hour, minute), 10, 135, 20, WHITE);
|
|
||||||
|
|
||||||
DrawFPS(10, 160);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,248 +0,0 @@
|
|||||||
#include "Sky.hpp"
|
|
||||||
#include <rlgl.h>
|
|
||||||
#include <cmath>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
Sky::Sky()
|
|
||||||
: fogDensity(0.01f)
|
|
||||||
, timeOfDay(0.25f) // Start at sunrise
|
|
||||||
, shaderLoaded(false) {
|
|
||||||
|
|
||||||
sun.intensity = 1.0f;
|
|
||||||
sun.angle = 0.0f;
|
|
||||||
|
|
||||||
createSkyDome();
|
|
||||||
updateColors();
|
|
||||||
|
|
||||||
// Try to load a custom shader if available
|
|
||||||
// For now we'll use basic rendering
|
|
||||||
}
|
|
||||||
|
|
||||||
Sky::~Sky() {
|
|
||||||
if (shaderLoaded) {
|
|
||||||
UnloadShader(skyShader);
|
|
||||||
}
|
|
||||||
UnloadModel(skyModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::createSkyDome() {
|
|
||||||
// Create a large inverted sphere for the sky dome
|
|
||||||
// The sphere is inverted so we see the inside surface
|
|
||||||
skyDome = GenMeshSphere(1000.0f, 32, 32);
|
|
||||||
|
|
||||||
// Invert the mesh normals to render the inside
|
|
||||||
for (int i = 0; i < skyDome.vertexCount * 3; i++) {
|
|
||||||
skyDome.normals[i] *= -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update mesh in GPU
|
|
||||||
UploadMesh(&skyDome, false);
|
|
||||||
skyModel = LoadModelFromMesh(skyDome);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::update(float) {
|
|
||||||
// Optional: auto-advance time of day for testing
|
|
||||||
// timeOfDay += deltaTime * 0.01f; // Very slow day cycle
|
|
||||||
// if (timeOfDay > 1.0f) timeOfDay -= 1.0f;
|
|
||||||
|
|
||||||
updateColors();
|
|
||||||
sun.updatePosition(timeOfDay);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::Sun::updatePosition(float timeOfDay) {
|
|
||||||
// Convert time of day to angle (0.25 = sunrise at 6am, 0.75 = sunset at 6pm)
|
|
||||||
// Adjust so that 0.25 (6am) = 0 degrees, 0.75 (6pm) = 180 degrees
|
|
||||||
float adjustedTime = timeOfDay - 0.25f;
|
|
||||||
if (adjustedTime < 0) adjustedTime += 1.0f;
|
|
||||||
|
|
||||||
// Only show sun during daytime (6am to 6pm)
|
|
||||||
if (timeOfDay >= 0.25f && timeOfDay <= 0.75f) {
|
|
||||||
float dayProgress = (timeOfDay - 0.25f) / 0.5f; // 0 to 1 during day
|
|
||||||
angle = dayProgress * PI; // 0 to PI (sunrise to sunset)
|
|
||||||
|
|
||||||
// Calculate sun position in an arc
|
|
||||||
float sunX = cosf(angle) * 150.0f; // East to West
|
|
||||||
float sunY = sinf(angle) * 100.0f + 20.0f; // Height arc, minimum 20 units up
|
|
||||||
float sunZ = 0.0f;
|
|
||||||
|
|
||||||
position = {sunX, sunY, sunZ};
|
|
||||||
} else {
|
|
||||||
// Sun is below horizon at night
|
|
||||||
position = {0.0f, -100.0f, 0.0f};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Direction is from sun to origin (for lighting)
|
|
||||||
direction = Vector3Normalize(Vector3Scale(position, -1.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::updateColors() {
|
|
||||||
float t = timeOfDay;
|
|
||||||
|
|
||||||
// Define key times
|
|
||||||
const float nightEnd = 0.2f; // 4:48 AM
|
|
||||||
const float sunrise = 0.25f; // 6:00 AM
|
|
||||||
const float noon = 0.5f; // 12:00 PM
|
|
||||||
const float sunset = 0.75f; // 6:00 PM
|
|
||||||
const float nightStart = 0.8f; // 7:12 PM
|
|
||||||
|
|
||||||
Color nightHorizon = {10, 15, 30, 255};
|
|
||||||
Color nightZenith = {5, 10, 20, 255};
|
|
||||||
Color sunriseHorizon = {255, 150, 100, 255};
|
|
||||||
Color sunriseZenith = {100, 150, 200, 255};
|
|
||||||
Color dayHorizon = {150, 200, 255, 255};
|
|
||||||
Color dayZenith = {100, 150, 255, 255};
|
|
||||||
Color sunsetHorizon = {255, 100, 50, 255};
|
|
||||||
Color sunsetZenith = {100, 100, 150, 255};
|
|
||||||
|
|
||||||
if (t < nightEnd) {
|
|
||||||
// Night
|
|
||||||
horizonColor = nightHorizon;
|
|
||||||
zenithColor = nightZenith;
|
|
||||||
sun.color = {50, 50, 70, 255};
|
|
||||||
sun.intensity = 0.1f;
|
|
||||||
} else if (t < sunrise) {
|
|
||||||
// Night to sunrise transition
|
|
||||||
float blend = (t - nightEnd) / (sunrise - nightEnd);
|
|
||||||
horizonColor = interpolateColor(nightHorizon, sunriseHorizon, blend);
|
|
||||||
zenithColor = interpolateColor(nightZenith, sunriseZenith, blend);
|
|
||||||
sun.color = interpolateColor({50, 50, 70, 255}, {255, 200, 150, 255}, blend);
|
|
||||||
sun.intensity = 0.1f + blend * 0.4f;
|
|
||||||
} else if (t < noon) {
|
|
||||||
// Sunrise to noon
|
|
||||||
float blend = (t - sunrise) / (noon - sunrise);
|
|
||||||
horizonColor = interpolateColor(sunriseHorizon, dayHorizon, blend);
|
|
||||||
zenithColor = interpolateColor(sunriseZenith, dayZenith, blend);
|
|
||||||
sun.color = interpolateColor({255, 200, 150, 255}, {255, 255, 250, 255}, blend);
|
|
||||||
sun.intensity = 0.5f + blend * 0.5f;
|
|
||||||
} else if (t < sunset) {
|
|
||||||
// Noon to sunset
|
|
||||||
float blend = (t - noon) / (sunset - noon);
|
|
||||||
horizonColor = interpolateColor(dayHorizon, sunsetHorizon, blend);
|
|
||||||
zenithColor = interpolateColor(dayZenith, sunsetZenith, blend);
|
|
||||||
sun.color = interpolateColor({255, 255, 250, 255}, {255, 180, 100, 255}, blend);
|
|
||||||
sun.intensity = 1.0f - blend * 0.3f;
|
|
||||||
} else if (t < nightStart) {
|
|
||||||
// Sunset to night transition
|
|
||||||
float blend = (t - sunset) / (nightStart - sunset);
|
|
||||||
horizonColor = interpolateColor(sunsetHorizon, nightHorizon, blend);
|
|
||||||
zenithColor = interpolateColor(sunsetZenith, nightZenith, blend);
|
|
||||||
sun.color = interpolateColor({255, 180, 100, 255}, {50, 50, 70, 255}, blend);
|
|
||||||
sun.intensity = 0.7f - blend * 0.6f;
|
|
||||||
} else {
|
|
||||||
// Night
|
|
||||||
horizonColor = nightHorizon;
|
|
||||||
zenithColor = nightZenith;
|
|
||||||
sun.color = {50, 50, 70, 255};
|
|
||||||
sun.intensity = 0.1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fog color follows horizon color but slightly desaturated
|
|
||||||
fogColor = interpolateColor(horizonColor, {200, 200, 200, 255}, 0.3f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color Sky::interpolateColor(const Color& a, const Color& b, float t) const {
|
|
||||||
t = std::clamp(t, 0.0f, 1.0f);
|
|
||||||
return {
|
|
||||||
(unsigned char)(a.r + (b.r - a.r) * t),
|
|
||||||
(unsigned char)(a.g + (b.g - a.g) * t),
|
|
||||||
(unsigned char)(a.b + (b.b - a.b) * t),
|
|
||||||
(unsigned char)(a.a + (b.a - a.a) * t)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::render(const Camera3D& camera) {
|
|
||||||
// Legacy function - just calls renderSkybox
|
|
||||||
renderSkybox(camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::renderSkybox(const Camera3D& camera) {
|
|
||||||
// Save current depth state
|
|
||||||
rlPushMatrix();
|
|
||||||
|
|
||||||
// Disable depth write but keep depth test for proper rendering order
|
|
||||||
rlDisableDepthMask();
|
|
||||||
|
|
||||||
// Position skybox at camera position so it moves with the camera
|
|
||||||
// This ensures the skybox is always centered on the viewer
|
|
||||||
rlTranslatef(camera.position.x, camera.position.y, camera.position.z);
|
|
||||||
|
|
||||||
// Draw the sky dome with gradient color
|
|
||||||
// We'll use vertex colors or a simple colored material
|
|
||||||
Color topColor = zenithColor;
|
|
||||||
Color bottomColor = horizonColor;
|
|
||||||
|
|
||||||
// For now, draw with a blended color
|
|
||||||
Color skyColor = interpolateColor(bottomColor, topColor, 0.5f);
|
|
||||||
DrawModel(skyModel, {0, 0, 0}, 1.0f, skyColor);
|
|
||||||
|
|
||||||
// Draw sun as a sphere on the skybox
|
|
||||||
if (sun.intensity > 0.2f && sun.position.y > 0) {
|
|
||||||
// Calculate sun direction from camera
|
|
||||||
Vector3 sunDir = Vector3Normalize(sun.position);
|
|
||||||
Vector3 sunPosOnSphere = Vector3Scale(sunDir, 900.0f); // Just inside the skybox
|
|
||||||
|
|
||||||
// Draw sun as a sphere
|
|
||||||
DrawSphere(sunPosOnSphere, 50.0f, sun.color);
|
|
||||||
|
|
||||||
// Draw sun glow layers
|
|
||||||
Color glowColor = sun.color;
|
|
||||||
glowColor.a = 80;
|
|
||||||
DrawSphere(sunPosOnSphere, 70.0f, glowColor);
|
|
||||||
|
|
||||||
glowColor.a = 40;
|
|
||||||
DrawSphere(sunPosOnSphere, 90.0f, glowColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore depth state
|
|
||||||
rlEnableDepthMask();
|
|
||||||
rlPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::drawGradientSky() const {
|
|
||||||
// Draw a simple gradient from horizon to zenith
|
|
||||||
int screenHeight = GetScreenHeight();
|
|
||||||
int screenWidth = GetScreenWidth();
|
|
||||||
|
|
||||||
// Draw gradient rectangles
|
|
||||||
for (int y = 0; y < screenHeight; y++) {
|
|
||||||
float t = (float)y / (float)screenHeight;
|
|
||||||
Color gradientColor = interpolateColor(zenithColor, horizonColor, t);
|
|
||||||
DrawRectangle(0, y, screenWidth, 1, gradientColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::drawSun(const Camera3D& camera) const {
|
|
||||||
// Only draw sun during day time
|
|
||||||
if (sun.intensity > 0.2f) {
|
|
||||||
// Calculate sun screen position
|
|
||||||
Vector2 sunScreenPos = GetWorldToScreen(sun.position, camera);
|
|
||||||
|
|
||||||
// Check if sun is in view
|
|
||||||
if (sunScreenPos.x >= 0 && sunScreenPos.x <= GetScreenWidth() &&
|
|
||||||
sunScreenPos.y >= 0 && sunScreenPos.y <= GetScreenHeight()) {
|
|
||||||
|
|
||||||
// Draw sun glow
|
|
||||||
float glowRadius = 60.0f * sun.intensity;
|
|
||||||
Color glowColor = sun.color;
|
|
||||||
glowColor.a = 50;
|
|
||||||
DrawCircleGradient(sunScreenPos.x, sunScreenPos.y, glowRadius,
|
|
||||||
glowColor, {glowColor.r, glowColor.g, glowColor.b, 0});
|
|
||||||
|
|
||||||
// Draw sun disc
|
|
||||||
float sunRadius = 20.0f;
|
|
||||||
DrawCircle(sunScreenPos.x, sunScreenPos.y, sunRadius, sun.color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sky::setTimeOfDay(float time) {
|
|
||||||
timeOfDay = std::clamp(time, 0.0f, 1.0f);
|
|
||||||
updateColors();
|
|
||||||
sun.updatePosition(timeOfDay);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color Sky::getAmbientLight() const {
|
|
||||||
// Ambient light based on time of day
|
|
||||||
float ambientIntensity = 0.2f + sun.intensity * 0.3f;
|
|
||||||
return interpolateColor({20, 20, 30, 255}, zenithColor, ambientIntensity);
|
|
||||||
}
|
|
||||||
@ -1,58 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <raylib.h>
|
|
||||||
#include <raymath.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class Sky {
|
|
||||||
private:
|
|
||||||
struct Sun {
|
|
||||||
Vector3 position;
|
|
||||||
Vector3 direction;
|
|
||||||
Color color;
|
|
||||||
float intensity;
|
|
||||||
float angle; // Sun angle for day/night cycle
|
|
||||||
|
|
||||||
void updatePosition(float timeOfDay);
|
|
||||||
Vector3 getLightDirection() const { return direction; }
|
|
||||||
};
|
|
||||||
|
|
||||||
Sun sun;
|
|
||||||
Color horizonColor;
|
|
||||||
Color zenithColor;
|
|
||||||
Color fogColor;
|
|
||||||
float fogDensity;
|
|
||||||
float timeOfDay; // 0.0 to 1.0 (0 = midnight, 0.5 = noon)
|
|
||||||
|
|
||||||
Shader skyShader;
|
|
||||||
Mesh skyDome;
|
|
||||||
Model skyModel;
|
|
||||||
bool shaderLoaded;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Sky();
|
|
||||||
~Sky();
|
|
||||||
|
|
||||||
void update(float deltaTime);
|
|
||||||
void render(const Camera3D& camera);
|
|
||||||
void renderSkybox(const Camera3D& camera); // Render skybox that follows camera
|
|
||||||
|
|
||||||
void setTimeOfDay(float time);
|
|
||||||
float getTimeOfDay() const { return timeOfDay; }
|
|
||||||
|
|
||||||
Vector3 getSunDirection() const { return sun.direction; }
|
|
||||||
Color getSunColor() const { return sun.color; }
|
|
||||||
float getSunIntensity() const { return sun.intensity; }
|
|
||||||
|
|
||||||
Color getFogColor() const { return fogColor; }
|
|
||||||
float getFogDensity() const { return fogDensity; }
|
|
||||||
|
|
||||||
Color getAmbientLight() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateColors();
|
|
||||||
void createSkyDome();
|
|
||||||
Color interpolateColor(const Color& a, const Color& b, float t) const;
|
|
||||||
void drawGradientSky() const;
|
|
||||||
void drawSun(const Camera3D& camera) const;
|
|
||||||
};
|
|
||||||
Loading…
x
Reference in New Issue
Block a user