stuff
This commit is contained in:
parent
1006b231f0
commit
0c0cfef186
28 changed files with 220 additions and 331 deletions
|
|
@ -1,24 +1,22 @@
|
|||
#!/bin/bash
|
||||
# Build the game client using the split modules
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Get raylib compile and link flags
|
||||
RAYLIB_CFLAGS=$(pkg-config --cflags raylib 2>/dev/null || echo "-I/usr/include")
|
||||
RAYLIB_LIBS=$(pkg-config --libs raylib 2>/dev/null || echo "-lraylib -lm")
|
||||
|
||||
echo "Compiling game modules..."
|
||||
gcc -c suic_math.c -I../libsuicmez $RAYLIB_CFLAGS -o suic_math.o
|
||||
gcc -c suic_terrain.c -I../libsuicmez $RAYLIB_CFLAGS -o suic_terrain.o
|
||||
gcc -c suic_lighting.c -I../libsuicmez $RAYLIB_CFLAGS -o suic_lighting.o
|
||||
gcc -c suic_net.c -I../libsuicmez $RAYLIB_CFLAGS -o suic_net.o
|
||||
gcc -c suic_ui.c -I../libsuicmez $RAYLIB_CFLAGS -o suic_ui.o
|
||||
gcc -c suic_game_client.c -I../libsuicmez $RAYLIB_CFLAGS -o suic_game_client.o
|
||||
gcc -c inc/suic_math.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o suic_math.o
|
||||
gcc -c inc/suic_terrain.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o suic_terrain.o
|
||||
gcc -c inc/suic_lighting.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o suic_lighting.o
|
||||
gcc -c inc/suic_net.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o suic_net.o
|
||||
gcc -c inc/suic_ui.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o suic_ui.o
|
||||
gcc -c inc/suic_game_client.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o suic_game_client.o
|
||||
|
||||
echo "Compiling main entry point..."
|
||||
gcc -c main.c -I../libsuicmez $RAYLIB_CFLAGS -o main.o
|
||||
gcc -c main.c -Iinc -I../libsuicmez $RAYLIB_CFLAGS -o main.o
|
||||
|
||||
echo "Linking..."
|
||||
gcc main.o suic_math.o suic_terrain.o suic_lighting.o suic_net.o suic_ui.o suic_game_client.o \
|
||||
|
|
|
|||
1
game/clean.sh
Executable file
1
game/clean.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
rm *.o
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
#include "libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
void* gc_alloc(const TypeInfo* type, size_t size);
|
||||
void gc_init(void);
|
||||
void gc_shutdown(void);
|
||||
|
||||
// Helper for allocating arrays
|
||||
static void* suic_alloc_array(const TypeInfo* type, size_t elem_size, size_t len, void* init_data) {
|
||||
void* ptr = gc_alloc(type, elem_size * len);
|
||||
if (init_data) memcpy(ptr, init_data, elem_size * len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Helper for allocating structs
|
||||
static void* suic_alloc_struct(const TypeInfo* type, size_t size, void* init_data) {
|
||||
void* ptr = gc_alloc(type, size);
|
||||
if (init_data) memcpy(ptr, init_data, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
;
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
int suic_main(void);
|
||||
|
||||
|
||||
int suic_main(void) {
|
||||
suic_init_window(1280, 720, suic_alloc_array(NULL, sizeof(char), 21, "Voxel Shooter Client"));
|
||||
suic_set_target_fps(120);
|
||||
suic_disable_cursor();
|
||||
while ((suic_window_should_close() == false)) {
|
||||
float dt = suic_get_frame_time();
|
||||
suic_begin_drawing();
|
||||
suic_clear_background(135, 206, 235, 255);
|
||||
DrawFPS(10, 10);
|
||||
suic_end_drawing();
|
||||
}
|
||||
suic_close_window();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Initialize GC
|
||||
gc_init();
|
||||
// init globals
|
||||
// init event loop
|
||||
int result = suic_main();
|
||||
// Shutdown GC
|
||||
gc_shutdown();
|
||||
return result;
|
||||
}
|
||||
|
||||
BIN
game/game_client
BIN
game/game_client
Binary file not shown.
19
game/inc/suic_app.h
Normal file
19
game/inc/suic_app.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void suic_runtime_init(void);
|
||||
void suic_runtime_shutdown(void);
|
||||
|
||||
void suic_app_init(int width, int height, const char *title);
|
||||
bool suic_app_should_close(void);
|
||||
void suic_app_frame_begin(void);
|
||||
void suic_app_frame_end(void);
|
||||
void suic_app_shutdown(void);
|
||||
|
||||
void suic_draw_hello(void);
|
||||
|
||||
const char *suic_item_name(uint8_t t);
|
||||
struct Color *suic_apply_directional_lighting(struct Color *baseColor,
|
||||
struct Vector3 *normal,
|
||||
struct DirectionalLight *light);
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ===== GAME STATE ===== */
|
||||
|
||||
static SuicVec3 g_camPos = {0, 5.0f, 6};
|
||||
static float g_yaw = 0.0f, g_pitch = 0.0f;
|
||||
static SuicVec3 g_prevBodyPos = {0, 5.0f, 6};
|
||||
|
|
@ -29,8 +27,6 @@ static const float PISTOL_CROSS_KICK = 2.0f, RIFLE_CROSS_KICK = 4.0f;
|
|||
static const float PISTOL_SPRAY_GROW = 0.4f, RIFLE_SPRAY_GROW = 1.2f;
|
||||
static const float BURST_RESET_TIME = 0.18f;
|
||||
|
||||
/* ===== LIFECYCLE ===== */
|
||||
|
||||
void suic_game_init(const char* username, const char* serverIp, int port) {
|
||||
suic_terrain_init();
|
||||
suic_net_init(serverIp, port);
|
||||
|
|
@ -47,8 +43,6 @@ void suic_game_shutdown(void) {
|
|||
suic_net_shutdown();
|
||||
}
|
||||
|
||||
/* ===== INPUT HANDLING ===== */
|
||||
|
||||
void suic_game_handle_input(float dt) {
|
||||
g_clientTick++;
|
||||
|
||||
|
|
@ -126,8 +120,6 @@ void suic_game_handle_input(float dt) {
|
|||
}
|
||||
}
|
||||
|
||||
/* ===== UPDATE ===== */
|
||||
|
||||
void suic_game_update(float dt) {
|
||||
suic_net_poll();
|
||||
|
||||
|
|
@ -156,19 +148,19 @@ void suic_game_update(float dt) {
|
|||
g_interpTimer += dt;
|
||||
|
||||
/* Forward offset */
|
||||
float viewYaw = g_yaw + g_recoilYaw;
|
||||
float viewPitch = g_pitch + g_recoilPitch;
|
||||
SuicVec3 forward = suic_v3(sinf(viewYaw) * cosf(viewPitch), sinf(viewPitch),
|
||||
cosf(viewYaw) * cosf(viewPitch));
|
||||
g_camPos = suic_v3_add(g_camPos, suic_v3_mul(forward, 0.3f));
|
||||
g_camPos.y -= 0.2f;
|
||||
if (myId != 255) {
|
||||
float viewYaw = g_yaw + g_recoilYaw;
|
||||
float viewPitch = g_pitch + g_recoilPitch;
|
||||
SuicVec3 forward = suic_v3(sinf(viewYaw) * cosf(viewPitch), sinf(viewPitch),
|
||||
cosf(viewYaw) * cosf(viewPitch));
|
||||
g_camPos = suic_v3_add(g_camPos, suic_v3_mul(forward, 0.3f));
|
||||
g_camPos.y -= 0.2f;
|
||||
}
|
||||
|
||||
float terrain_h = suic_terrain_height(g_camPos.x, g_camPos.z);
|
||||
g_camPos.y = fmaxf(g_camPos.y, terrain_h + 1.5f);
|
||||
}
|
||||
|
||||
/* ===== RENDERING ===== */
|
||||
|
||||
void suic_game_render(void) {
|
||||
int sw = GetScreenWidth();
|
||||
int sh = GetScreenHeight();
|
||||
|
|
@ -252,7 +244,7 @@ void suic_game_render(void) {
|
|||
|
||||
/* HUD */
|
||||
if (myId == 255 || !suic_net_player_present(myId)) {
|
||||
DrawText("Connecting...", 10, 10, 20, RAYWHITE);
|
||||
DrawText("Offline", 10, 10, 20, RAYWHITE);
|
||||
} else {
|
||||
int weapon = suic_net_player_weapon(myId);
|
||||
int mag = (weapon == SUIC_WEAPON_PISTOL) ? suic_net_player_pistol_mag(myId)
|
||||
|
|
@ -272,8 +264,6 @@ void suic_game_render(void) {
|
|||
suic_ui_draw_crosshair(sw, sh, g_crossSpread, g_scoped);
|
||||
}
|
||||
|
||||
/* ===== ACCESSORS ===== */
|
||||
|
||||
SuicVec3 suic_game_get_camera_pos(void) { return g_camPos; }
|
||||
float suic_game_get_yaw(void) { return g_yaw; }
|
||||
float suic_game_get_pitch(void) { return g_pitch; }
|
||||
153
game/inc/suic_lighting.c
Normal file
153
game/inc/suic_lighting.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#include "suic_lighting.h"
|
||||
#include "suic_terrain.h"
|
||||
#include <math.h>
|
||||
|
||||
SuicDirectionalLight suic_light_create(float dir_x, float dir_y, float dir_z,
|
||||
float intensity, float ambient) {
|
||||
SuicDirectionalLight light = {0};
|
||||
light.direction = suic_v3_norm(suic_v3(dir_x, dir_y, dir_z));
|
||||
light.color = suic_v3(1.0f, 1.0f, 1.0f);
|
||||
light.intensity = intensity;
|
||||
light.ambientIntensity = ambient;
|
||||
light.shadowBias = 0.005f;
|
||||
light.shadowIntensity = 0.4f;
|
||||
return light;
|
||||
}
|
||||
|
||||
SuicDirectionalLight suic_light_create_default(void) {
|
||||
return suic_light_create(-0.8f, -1.0f, -0.6f, 1.2f, 0.3f);
|
||||
}
|
||||
|
||||
SuicColor suic_light_apply(SuicColor base, SuicVec3 normal,
|
||||
SuicDirectionalLight *light) {
|
||||
SuicVec3 lightDir = light->direction;
|
||||
|
||||
/* Diffuse: Lambertian */
|
||||
float diff = fmaxf(0.0f, -(lightDir.x * normal.x + lightDir.y * normal.y +
|
||||
lightDir.z * normal.z));
|
||||
|
||||
float brightness =
|
||||
light->ambientIntensity +
|
||||
(diff * light->intensity * (1.0f - light->ambientIntensity));
|
||||
|
||||
int r = (int)(base.r * brightness);
|
||||
int g = (int)(base.g * brightness);
|
||||
int b = (int)(base.b * brightness);
|
||||
|
||||
if (r > 255)
|
||||
r = 255;
|
||||
if (g > 255)
|
||||
g = 255;
|
||||
if (b > 255)
|
||||
b = 255;
|
||||
|
||||
return (SuicColor){r, g, b, base.a};
|
||||
}
|
||||
|
||||
float suic_shadow_factor(SuicVec3 worldPos, SuicVec3 lightDir, float maxDist) {
|
||||
float distFromLight = fmaxf(0.0f, worldPos.y - 2.0f);
|
||||
float shadowIntensity = fmaxf(0.0f, 1.0f - (distFromLight / maxDist));
|
||||
return 1.0f - (shadowIntensity * 0.15f);
|
||||
}
|
||||
|
||||
float suic_shadow_temporal(SuicVec3 worldPos, float timePhase) {
|
||||
float noiseVal =
|
||||
sinf(worldPos.x * 0.5f + timePhase) * cosf(worldPos.z * 0.5f + timePhase);
|
||||
return 1.0f + (noiseVal * 0.02f);
|
||||
}
|
||||
|
||||
SuicColor suic_light_apply_shadows(SuicColor base, SuicVec3 normal,
|
||||
SuicVec3 worldPos,
|
||||
SuicDirectionalLight *light) {
|
||||
float shadowFactor = suic_shadow_factor(worldPos, light->direction, 10.0f);
|
||||
float adjustedIntensity = light->intensity * shadowFactor;
|
||||
|
||||
SuicVec3 lightDir = light->direction;
|
||||
float diff = fmaxf(0.0f, -(lightDir.x * normal.x + lightDir.y * normal.y +
|
||||
lightDir.z * normal.z));
|
||||
|
||||
float brightness =
|
||||
light->ambientIntensity +
|
||||
(diff * adjustedIntensity * (1.0f - light->ambientIntensity));
|
||||
|
||||
int r = (int)(base.r * brightness);
|
||||
int g = (int)(base.g * brightness);
|
||||
int b = (int)(base.b * brightness);
|
||||
|
||||
if (r > 255)
|
||||
r = 255;
|
||||
if (g > 255)
|
||||
g = 255;
|
||||
if (b > 255)
|
||||
b = 255;
|
||||
|
||||
return (SuicColor){r, g, b, base.a};
|
||||
}
|
||||
|
||||
float suic_ao_calculate(SuicVec3 worldPos, SuicVec3 normal) {
|
||||
float sampleRadius = 3.0f;
|
||||
float aoAccum = 0.0f;
|
||||
int numSamples = 8;
|
||||
float centerHeight = worldPos.y;
|
||||
float pi = 3.14159265f;
|
||||
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
float angle = (2.0f * pi * (float)i) / (float)numSamples;
|
||||
float sx = worldPos.x + cosf(angle) * sampleRadius;
|
||||
float sz = worldPos.z + sinf(angle) * sampleRadius;
|
||||
float sh = suic_terrain_height(sx, sz);
|
||||
|
||||
float heightDiff = sh - centerHeight;
|
||||
if (heightDiff > 0.1f) {
|
||||
float aoAmount = fminf(1.0f, heightDiff / 2.0f);
|
||||
aoAccum += aoAmount;
|
||||
}
|
||||
}
|
||||
|
||||
float aoFactor = 1.0f - (aoAccum / (float)numSamples) * 0.6f;
|
||||
return fmaxf(0.2f, aoFactor);
|
||||
}
|
||||
|
||||
SuicColor suic_light_apply_phong(SuicColor base, SuicVec3 normal,
|
||||
SuicVec3 worldPos, SuicVec3 camPos,
|
||||
SuicDirectionalLight *light) {
|
||||
SuicVec3 lightDir = suic_v3_norm(light->direction);
|
||||
SuicVec3 normal_n = suic_v3_norm(normal);
|
||||
SuicVec3 viewDir = suic_v3_norm(suic_v3_sub(camPos, worldPos));
|
||||
|
||||
/* Diffuse */
|
||||
float diffuse = fmaxf(0.0f, -suic_v3_dot(lightDir, normal_n));
|
||||
|
||||
/* Specular: Blinn-Phong */
|
||||
SuicVec3 negLight = suic_v3(-lightDir.x, -lightDir.y, -lightDir.z);
|
||||
SuicVec3 halfVec = suic_v3_norm(suic_v3_add(suic_v3_norm(negLight), viewDir));
|
||||
float specular =
|
||||
powf(fmaxf(0.0f, suic_v3_dot(halfVec, normal_n)), 32.0f) * 0.5f;
|
||||
|
||||
/* Ambient occlusion */
|
||||
float ao = suic_ao_calculate(worldPos, normal_n);
|
||||
|
||||
/* Shadow */
|
||||
float shadowFactor = suic_shadow_factor(worldPos, light->direction, 10.0f);
|
||||
|
||||
/* Combine */
|
||||
float brightness = light->ambientIntensity * ao;
|
||||
brightness += diffuse * light->intensity * shadowFactor *
|
||||
(1.0f - light->ambientIntensity) * ao;
|
||||
brightness += specular * light->intensity * shadowFactor * 0.6f;
|
||||
|
||||
brightness = fminf(1.0f, brightness);
|
||||
|
||||
int r = (int)(base.r * brightness);
|
||||
int g = (int)(base.g * brightness);
|
||||
int b = (int)(base.b * brightness);
|
||||
|
||||
if (r > 255)
|
||||
r = 255;
|
||||
if (g > 255)
|
||||
g = 255;
|
||||
if (b > 255)
|
||||
b = 255;
|
||||
|
||||
return (SuicColor){r, g, b, base.a};
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* ===== SIMPLEX NOISE IMPLEMENTATION ===== */
|
||||
|
||||
|
|
@ -208,8 +209,12 @@ void suic_terrain_init(void) {
|
|||
g_terrainModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].color = (Color){80, 140, 70, 255};
|
||||
|
||||
g_terrainShader = suic_terrain_shader_load();
|
||||
if (g_terrainShader.shaderId != 0) {
|
||||
g_terrainModel.materials[0].shader.id = g_terrainShader.shaderId;
|
||||
if (g_terrainShader.shader.id != 0) {
|
||||
g_terrainModel.materials[0].shader = g_terrainShader.shader;
|
||||
fprintf(stderr, "Terrain shader loaded successfully!\n");
|
||||
} else {
|
||||
fprintf(stderr, "Warning: Failed to load terrain shader, using default rendering\n");
|
||||
g_terrainModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].color = (Color){255, 100, 100, 255};
|
||||
}
|
||||
|
||||
g_terrainInitialized = true;
|
||||
|
|
@ -219,7 +224,7 @@ void suic_terrain_draw(SuicVec3 cameraPos) {
|
|||
if (!g_terrainInitialized) return;
|
||||
|
||||
/* Set shader uniforms if shader is loaded */
|
||||
if (g_terrainShader.shaderId != 0) {
|
||||
if (g_terrainShader.shader.id != 0) {
|
||||
SuicVec3 lightDir = suic_v3_norm(suic_v3(-0.8f, -1.0f, -0.6f));
|
||||
SuicVec3 lightColor = suic_v3(1.0f, 1.0f, 1.0f);
|
||||
suic_terrain_shader_set_uniforms(&g_terrainShader, cameraPos, lightDir, lightColor, 1.2f, 0.3f);
|
||||
|
|
@ -240,44 +245,41 @@ void suic_terrain_cleanup(void) {
|
|||
|
||||
SuicTerrainShader suic_terrain_shader_load(void) {
|
||||
SuicTerrainShader ts = {0};
|
||||
Shader shader = LoadShader("terrain.vs", "terrain.fs");
|
||||
ts.shaderId = shader.id;
|
||||
ts.shader = LoadShader("terrain.vs", "terrain.fs");
|
||||
|
||||
if (shader.id != 0) {
|
||||
ts.locViewPos = GetShaderLocation(shader, "viewPos");
|
||||
ts.locLightDir = GetShaderLocation(shader, "lightDir");
|
||||
ts.locLightColor = GetShaderLocation(shader, "lightColor");
|
||||
ts.locLightIntensity = GetShaderLocation(shader, "lightIntensity");
|
||||
ts.locAmbientIntensity = GetShaderLocation(shader, "ambientIntensity");
|
||||
ts.locTerrainColor = GetShaderLocation(shader, "terrainColor");
|
||||
if (ts.shader.id != 0) {
|
||||
ts.locViewPos = GetShaderLocation(ts.shader, "viewPos");
|
||||
ts.locLightDir = GetShaderLocation(ts.shader, "lightDir");
|
||||
ts.locLightColor = GetShaderLocation(ts.shader, "lightColor");
|
||||
ts.locLightIntensity = GetShaderLocation(ts.shader, "lightIntensity");
|
||||
ts.locAmbientIntensity = GetShaderLocation(ts.shader, "ambientIntensity");
|
||||
ts.locTerrainColor = GetShaderLocation(ts.shader, "terrainColor");
|
||||
}
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
void suic_terrain_shader_unload(SuicTerrainShader* ts) {
|
||||
if (ts && ts->shaderId != 0) {
|
||||
Shader s = {ts->shaderId, NULL};
|
||||
UnloadShader(s);
|
||||
ts->shaderId = 0;
|
||||
if (ts && ts->shader.id != 0) {
|
||||
UnloadShader(ts->shader);
|
||||
ts->shader.id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void suic_terrain_shader_set_uniforms(SuicTerrainShader* ts, SuicVec3 viewPos,
|
||||
SuicVec3 lightDir, SuicVec3 lightColor,
|
||||
float intensity, float ambient) {
|
||||
if (!ts || ts->shaderId == 0) return;
|
||||
if (!ts || ts->shader.id == 0) return;
|
||||
|
||||
Shader shader = {ts->shaderId, NULL};
|
||||
float viewPosArray[3] = {viewPos.x, viewPos.y, viewPos.z};
|
||||
float lightDirArray[3] = {-lightDir.x, -lightDir.y, -lightDir.z};
|
||||
float lightColorArray[3] = {lightColor.x, lightColor.y, lightColor.z};
|
||||
float terrainColorArray[3] = {80.0f / 255.0f, 140.0f / 255.0f, 70.0f / 255.0f};
|
||||
|
||||
SetShaderValue(shader, ts->locViewPos, viewPosArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(shader, ts->locLightDir, lightDirArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(shader, ts->locLightColor, lightColorArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(shader, ts->locLightIntensity, &intensity, SHADER_UNIFORM_FLOAT);
|
||||
SetShaderValue(shader, ts->locAmbientIntensity, &ambient, SHADER_UNIFORM_FLOAT);
|
||||
SetShaderValue(shader, ts->locTerrainColor, terrainColorArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(ts->shader, ts->locViewPos, viewPosArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(ts->shader, ts->locLightDir, lightDirArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(ts->shader, ts->locLightColor, lightColorArray, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(ts->shader, ts->locLightIntensity, &intensity, SHADER_UNIFORM_FLOAT);
|
||||
SetShaderValue(ts->shader, ts->locAmbientIntensity, &ambient, SHADER_UNIFORM_FLOAT);
|
||||
SetShaderValue(ts->shader, ts->locTerrainColor, terrainColorArray, SHADER_UNIFORM_VEC3);
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "suic_math.h"
|
||||
#include "raylib.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
|
|
@ -27,7 +28,7 @@ void suic_terrain_cleanup(void);
|
|||
|
||||
/* Shader management */
|
||||
typedef struct SuicTerrainShader {
|
||||
unsigned int shaderId;
|
||||
Shader shader;
|
||||
int locViewPos;
|
||||
int locLightDir;
|
||||
int locLightColor;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
gcc -O3 client.c -o client -lm -lraylib
|
||||
./build_client.sh
|
||||
gcc -O3 server.c -o server -lm -lraylib -lode
|
||||
|
||||
./server &
|
||||
server_pid=$!
|
||||
./client
|
||||
./game_client
|
||||
kill $server_pid
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../libsuicmez/suicmez_gc.h"
|
||||
|
||||
void* gc_alloc(const TypeInfo* type, size_t size);
|
||||
void gc_init(void);
|
||||
void gc_shutdown(void);
|
||||
|
||||
// Helper for allocating arrays
|
||||
void* suic_alloc_array(const TypeInfo* type, size_t elem_size, size_t len, void* init_data) {
|
||||
void* ptr = gc_alloc(type, elem_size * len);
|
||||
if (init_data) memcpy(ptr, init_data, elem_size * len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Helper for allocating structs
|
||||
void* suic_alloc_struct(const TypeInfo* type, size_t size, void* init_data) {
|
||||
void* ptr = gc_alloc(type, size);
|
||||
if (init_data) memcpy(ptr, init_data, size);
|
||||
return ptr;
|
||||
}
|
||||
Binary file not shown.
BIN
game/server
BIN
game/server
Binary file not shown.
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* ---- Lifecycle ---- */
|
||||
void suic_runtime_init(void);
|
||||
void suic_runtime_shutdown(void);
|
||||
|
||||
/* ---- Window / Loop ---- */
|
||||
void suic_app_init(int width, int height, const char* title);
|
||||
bool suic_app_should_close(void);
|
||||
void suic_app_frame_begin(void);
|
||||
void suic_app_frame_end(void);
|
||||
void suic_app_shutdown(void);
|
||||
|
||||
/* ---- Drawing ---- */
|
||||
void suic_draw_hello(void);
|
||||
|
||||
/* ---- Gameplay helpers ---- */
|
||||
const char* suic_item_name(uint8_t t);
|
||||
struct Color* suic_apply_directional_lighting(
|
||||
struct Color* baseColor,
|
||||
struct Vector3* normal,
|
||||
struct DirectionalLight* light
|
||||
);
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
fn main() -> int do
|
||||
suic_runtime_init()
|
||||
defer suic_runtime_shutdown()
|
||||
|
||||
# Initialize application / window
|
||||
suic_app_init(1280, 720, "Voxel Shooter - Client")
|
||||
defer suic_app_shutdown()
|
||||
|
||||
# Main loop
|
||||
while not suic_app_should_close() do
|
||||
suic_app_frame_begin()
|
||||
|
||||
suic_draw_hello()
|
||||
|
||||
suic_app_frame_end()
|
||||
end
|
||||
|
||||
0
|
||||
end
|
||||
Binary file not shown.
|
|
@ -1,150 +0,0 @@
|
|||
#include "suic_lighting.h"
|
||||
#include "suic_terrain.h"
|
||||
#include <math.h>
|
||||
|
||||
/* ===== LIGHT CREATION ===== */
|
||||
|
||||
SuicDirectionalLight suic_light_create(float dir_x, float dir_y, float dir_z,
|
||||
float intensity, float ambient) {
|
||||
SuicDirectionalLight light = {0};
|
||||
light.direction = suic_v3_norm(suic_v3(dir_x, dir_y, dir_z));
|
||||
light.color = suic_v3(1.0f, 1.0f, 1.0f);
|
||||
light.intensity = intensity;
|
||||
light.ambientIntensity = ambient;
|
||||
light.shadowBias = 0.005f;
|
||||
light.shadowIntensity = 0.4f;
|
||||
return light;
|
||||
}
|
||||
|
||||
SuicDirectionalLight suic_light_create_default(void) {
|
||||
return suic_light_create(-0.8f, -1.0f, -0.6f, 1.2f, 0.3f);
|
||||
}
|
||||
|
||||
/* ===== BASIC LIGHTING ===== */
|
||||
|
||||
SuicColor suic_light_apply(SuicColor base, SuicVec3 normal, SuicDirectionalLight* light) {
|
||||
SuicVec3 lightDir = light->direction;
|
||||
|
||||
/* Diffuse: Lambertian */
|
||||
float diff = fmaxf(0.0f, -(lightDir.x * normal.x + lightDir.y * normal.y +
|
||||
lightDir.z * normal.z));
|
||||
|
||||
float brightness = light->ambientIntensity +
|
||||
(diff * light->intensity * (1.0f - light->ambientIntensity));
|
||||
|
||||
int r = (int)(base.r * brightness);
|
||||
int g = (int)(base.g * brightness);
|
||||
int b = (int)(base.b * brightness);
|
||||
|
||||
if (r > 255) r = 255;
|
||||
if (g > 255) g = 255;
|
||||
if (b > 255) b = 255;
|
||||
|
||||
return (SuicColor){r, g, b, base.a};
|
||||
}
|
||||
|
||||
/* ===== SHADOW CALCULATIONS ===== */
|
||||
|
||||
float suic_shadow_factor(SuicVec3 worldPos, SuicVec3 lightDir, float maxDist) {
|
||||
float distFromLight = fmaxf(0.0f, worldPos.y - 2.0f);
|
||||
float shadowIntensity = fmaxf(0.0f, 1.0f - (distFromLight / maxDist));
|
||||
return 1.0f - (shadowIntensity * 0.15f);
|
||||
}
|
||||
|
||||
float suic_shadow_temporal(SuicVec3 worldPos, float timePhase) {
|
||||
float noiseVal = sinf(worldPos.x * 0.5f + timePhase) *
|
||||
cosf(worldPos.z * 0.5f + timePhase);
|
||||
return 1.0f + (noiseVal * 0.02f);
|
||||
}
|
||||
|
||||
/* ===== LIGHTING WITH SHADOWS ===== */
|
||||
|
||||
SuicColor suic_light_apply_shadows(SuicColor base, SuicVec3 normal, SuicVec3 worldPos,
|
||||
SuicDirectionalLight* light) {
|
||||
float shadowFactor = suic_shadow_factor(worldPos, light->direction, 10.0f);
|
||||
float adjustedIntensity = light->intensity * shadowFactor;
|
||||
|
||||
SuicVec3 lightDir = light->direction;
|
||||
float diff = fmaxf(0.0f, -(lightDir.x * normal.x + lightDir.y * normal.y +
|
||||
lightDir.z * normal.z));
|
||||
|
||||
float brightness = light->ambientIntensity +
|
||||
(diff * adjustedIntensity * (1.0f - light->ambientIntensity));
|
||||
|
||||
int r = (int)(base.r * brightness);
|
||||
int g = (int)(base.g * brightness);
|
||||
int b = (int)(base.b * brightness);
|
||||
|
||||
if (r > 255) r = 255;
|
||||
if (g > 255) g = 255;
|
||||
if (b > 255) b = 255;
|
||||
|
||||
return (SuicColor){r, g, b, base.a};
|
||||
}
|
||||
|
||||
/* ===== AMBIENT OCCLUSION ===== */
|
||||
|
||||
float suic_ao_calculate(SuicVec3 worldPos, SuicVec3 normal) {
|
||||
float sampleRadius = 3.0f;
|
||||
float aoAccum = 0.0f;
|
||||
int numSamples = 8;
|
||||
float centerHeight = worldPos.y;
|
||||
float pi = 3.14159265f;
|
||||
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
float angle = (2.0f * pi * (float)i) / (float)numSamples;
|
||||
float sx = worldPos.x + cosf(angle) * sampleRadius;
|
||||
float sz = worldPos.z + sinf(angle) * sampleRadius;
|
||||
float sh = suic_terrain_height(sx, sz);
|
||||
|
||||
float heightDiff = sh - centerHeight;
|
||||
if (heightDiff > 0.1f) {
|
||||
float aoAmount = fminf(1.0f, heightDiff / 2.0f);
|
||||
aoAccum += aoAmount;
|
||||
}
|
||||
}
|
||||
|
||||
float aoFactor = 1.0f - (aoAccum / (float)numSamples) * 0.6f;
|
||||
return fmaxf(0.2f, aoFactor);
|
||||
}
|
||||
|
||||
/* ===== PHONG LIGHTING ===== */
|
||||
|
||||
SuicColor suic_light_apply_phong(SuicColor base, SuicVec3 normal, SuicVec3 worldPos,
|
||||
SuicVec3 camPos, SuicDirectionalLight* light) {
|
||||
SuicVec3 lightDir = suic_v3_norm(light->direction);
|
||||
SuicVec3 normal_n = suic_v3_norm(normal);
|
||||
SuicVec3 viewDir = suic_v3_norm(suic_v3_sub(camPos, worldPos));
|
||||
|
||||
/* Diffuse */
|
||||
float diffuse = fmaxf(0.0f, -suic_v3_dot(lightDir, normal_n));
|
||||
|
||||
/* Specular: Blinn-Phong */
|
||||
SuicVec3 negLight = suic_v3(-lightDir.x, -lightDir.y, -lightDir.z);
|
||||
SuicVec3 halfVec = suic_v3_norm(suic_v3_add(suic_v3_norm(negLight), viewDir));
|
||||
float specular = powf(fmaxf(0.0f, suic_v3_dot(halfVec, normal_n)), 32.0f) * 0.5f;
|
||||
|
||||
/* Ambient occlusion */
|
||||
float ao = suic_ao_calculate(worldPos, normal_n);
|
||||
|
||||
/* Shadow */
|
||||
float shadowFactor = suic_shadow_factor(worldPos, light->direction, 10.0f);
|
||||
|
||||
/* Combine */
|
||||
float brightness = light->ambientIntensity * ao;
|
||||
brightness += diffuse * light->intensity * shadowFactor *
|
||||
(1.0f - light->ambientIntensity) * ao;
|
||||
brightness += specular * light->intensity * shadowFactor * 0.6f;
|
||||
|
||||
brightness = fminf(1.0f, brightness);
|
||||
|
||||
int r = (int)(base.r * brightness);
|
||||
int g = (int)(base.g * brightness);
|
||||
int b = (int)(base.b * brightness);
|
||||
|
||||
if (r > 255) r = 255;
|
||||
if (g > 255) g = 255;
|
||||
if (b > 255) b = 255;
|
||||
|
||||
return (SuicColor){r, g, b, base.a};
|
||||
}
|
||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue