Compare commits
No commits in common. "2d9857483035bdb1674daba913a2b3bff78b742d" and "57d8c7a2b7708838ba59c96f51ee5806868ef7a6" have entirely different histories.
2d98574830
...
57d8c7a2b7
6 changed files with 37 additions and 127 deletions
BIN
game/client
BIN
game/client
Binary file not shown.
|
|
@ -1,3 +1,4 @@
|
|||
// game/client.c - SMOOTH TERRAIN VERSION WITH DIRECTIONAL LIGHT & SHADOWS
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -179,8 +180,6 @@ float get_terrain_height(float x, float z) {
|
|||
|
||||
#define TERRAIN_SIZE 256
|
||||
#define TERRAIN_SCALE 1.0f
|
||||
#define TERRAIN_MIN (-TERRAIN_SIZE * TERRAIN_SCALE / 2.0f)
|
||||
#define TERRAIN_MAX (TERRAIN_SIZE * TERRAIN_SCALE / 2.0f)
|
||||
|
||||
static Mesh generate_terrain_mesh(void) {
|
||||
int size = TERRAIN_SIZE;
|
||||
|
|
@ -395,9 +394,6 @@ static Vector3 v3_add(Vector3 a, Vector3 b) {
|
|||
static Vector3 v3_sub(Vector3 a, Vector3 b) {
|
||||
return v3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
}
|
||||
static Vector3 v3_mul(Vector3 a, float s) {
|
||||
return v3(a.x * s, a.y * s, a.z * s);
|
||||
}
|
||||
static float v3_dot(Vector3 a, Vector3 b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
|
@ -589,7 +585,6 @@ typedef struct MsgRoomState {
|
|||
typedef struct RemotePlayer {
|
||||
int present, alive, hp;
|
||||
Vector3 pos;
|
||||
Vector3 prevPos;
|
||||
float yaw, pitch;
|
||||
uint8_t weapon;
|
||||
int16_t pistolMag, rifleMag, pistolAmmo, rifleAmmo, medkits;
|
||||
|
|
@ -722,10 +717,6 @@ int main(void) {
|
|||
Vector3 camPos = v3(0, 5.0f, 6);
|
||||
float yaw = 0.0f, pitch = 0.0f;
|
||||
|
||||
Vector3 prevBodyPos = v3(0, 5.0f, 6);
|
||||
Vector3 currentTargetBody = v3(0, 5.0f, 6);
|
||||
float interpTimer = 0.0f;
|
||||
|
||||
float recoilYaw = 0.0f, recoilPitch = 0.0f, crossSpread = 0.0f;
|
||||
int scoped = 0;
|
||||
float fireCooldown = 0.0f;
|
||||
|
|
@ -802,7 +793,6 @@ int main(void) {
|
|||
continue;
|
||||
|
||||
RemotePlayer *p = &rp[ps->id];
|
||||
p->prevPos = p->pos;
|
||||
p->present = 1;
|
||||
p->alive = ps->alive;
|
||||
p->hp = ps->hp;
|
||||
|
|
@ -821,9 +811,14 @@ int main(void) {
|
|||
}
|
||||
|
||||
if (myId != 255 && rp[myId].present) {
|
||||
prevBodyPos = currentTargetBody;
|
||||
currentTargetBody = rp[myId].pos;
|
||||
interpTimer = 0.0f;
|
||||
Vector3 body = rp[myId].pos;
|
||||
camPos.x = body.x;
|
||||
camPos.y = body.y + 1.0f;
|
||||
camPos.z = body.z + 0.0001f;
|
||||
|
||||
// Prevent camera from clipping into terrain
|
||||
float terrain_h = get_terrain_height(camPos.x, camPos.z);
|
||||
camPos.y = fmaxf(camPos.y, terrain_h + 1.5f);
|
||||
}
|
||||
} else if (type == MSG_ITEMS && n >= (int)sizeof(MsgItems)) {
|
||||
MsgItems *m = (MsgItems *)buf;
|
||||
|
|
@ -848,23 +843,6 @@ int main(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// Interpolate camera position
|
||||
if (myId != 255 && rp[myId].present) {
|
||||
float interpFactor = interpTimer / (1.0f / 20.0f);
|
||||
if (interpFactor > 1.0f)
|
||||
interpFactor = 1.0f;
|
||||
Vector3 interpBody = v3_add(v3_mul(prevBodyPos, 1.0f - interpFactor),
|
||||
v3_mul(currentTargetBody, interpFactor));
|
||||
camPos.x = interpBody.x;
|
||||
camPos.y = interpBody.y + 1.0f;
|
||||
camPos.z = interpBody.z + 0.0001f;
|
||||
|
||||
// Prevent camera from clipping into terrain
|
||||
float terrain_h = get_terrain_height(camPos.x, camPos.z);
|
||||
camPos.y = fmaxf(camPos.y, terrain_h + 1.5f);
|
||||
}
|
||||
interpTimer += dt;
|
||||
|
||||
Vector2 md = GetMouseDelta();
|
||||
const float sens = 0.0025f;
|
||||
yaw -= md.x * sens;
|
||||
|
|
@ -953,14 +931,6 @@ int main(void) {
|
|||
Vector3 forward = v3(sinf(viewYaw) * cosf(viewPitch), sinf(viewPitch),
|
||||
cosf(viewYaw) * cosf(viewPitch));
|
||||
|
||||
// Offset camera position: 0.3m in front, 0.2m below
|
||||
camPos = v3_add(camPos, v3_mul(forward, 0.3f));
|
||||
camPos.y -= 0.2f;
|
||||
|
||||
// Ensure camera doesn't clip into terrain after offset
|
||||
float terrain_h = get_terrain_height(camPos.x, camPos.z);
|
||||
camPos.y = fmaxf(camPos.y, terrain_h + 1.5f);
|
||||
|
||||
Camera3D cam = {0};
|
||||
cam.position = camPos;
|
||||
cam.target = v3_add(camPos, forward);
|
||||
|
|
@ -1007,10 +977,6 @@ int main(void) {
|
|||
(Color){80, 140, 70, 255};
|
||||
DrawModel(terrainModel, (Vector3){0, 0, 0}, 1.0f, WHITE);
|
||||
|
||||
// Draw border
|
||||
float borderSize = TERRAIN_MAX - TERRAIN_MIN;
|
||||
DrawCube((Vector3){0, 0, 0}, borderSize, 1000, borderSize, (Color){255, 0, 0, 100});
|
||||
|
||||
// Items with basic lighting (no shader for now to keep it simple)
|
||||
for (int i = 0; i < MAX_ITEMS; i++) {
|
||||
if (!wi[i].present)
|
||||
|
|
@ -1034,11 +1000,7 @@ int main(void) {
|
|||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!rp[i].present)
|
||||
continue;
|
||||
float interpFactor = interpTimer / (1.0f / 20.0f);
|
||||
if (interpFactor > 1.0f)
|
||||
interpFactor = 1.0f;
|
||||
Vector3 p = v3_add(v3_mul(rp[i].prevPos, 1.0f - interpFactor),
|
||||
v3_mul(rp[i].pos, interpFactor));
|
||||
Vector3 p = rp[i].pos;
|
||||
Color c =
|
||||
(i == myId) ? (Color){80, 180, 255, 255} : (Color){255, 80, 80, 255};
|
||||
if (!rp[i].alive)
|
||||
|
|
@ -1058,12 +1020,7 @@ int main(void) {
|
|||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!rp[i].present || !rp[i].username[0])
|
||||
continue;
|
||||
float interpFactor = interpTimer / (1.0f / 20.0f);
|
||||
if (interpFactor > 1.0f)
|
||||
interpFactor = 1.0f;
|
||||
Vector3 p = v3_add(v3_mul(rp[i].prevPos, 1.0f - interpFactor),
|
||||
v3_mul(rp[i].pos, interpFactor));
|
||||
Vector3 head = v3(p.x, p.y + 1.2f, p.z);
|
||||
Vector3 head = v3(rp[i].pos.x, rp[i].pos.y + 1.2f, rp[i].pos.z);
|
||||
Vector3 camForward = v3_norm(v3_sub(cam.target, cam.position));
|
||||
Vector3 toHead = v3_sub(head, cam.position);
|
||||
if (v3_dot(camForward, toHead) <= 0.0f)
|
||||
|
|
@ -1124,18 +1081,18 @@ int main(void) {
|
|||
|
||||
// Room state overlay
|
||||
if (roomState == 0) { // Waiting
|
||||
DrawRectangle(sw / 2 - 150, sh / 2 - 50, 350, 100, (Color){0, 0, 0, 200});
|
||||
DrawRectangle(sw / 2 - 150, sh / 2 - 50, 300, 100, (Color){0, 0, 0, 200});
|
||||
DrawText("WAITING FOR PLAYERS", sw / 2 - 120, sh / 2 - 30, 24, RAYWHITE);
|
||||
DrawText("Need at least 2 players", sw / 2 - 100, sh / 2 - 5, 18,
|
||||
(Color){200, 200, 200, 255});
|
||||
} else if (roomState == 1) { // Counting down
|
||||
DrawRectangle(sw / 2 - 150, sh / 2 - 50, 350, 100, (Color){0, 0, 0, 200});
|
||||
DrawRectangle(sw / 2 - 150, sh / 2 - 50, 300, 100, (Color){0, 0, 0, 200});
|
||||
DrawText("GAME STARTING SOON", sw / 2 - 120, sh / 2 - 30, 24,
|
||||
(Color){255, 255, 80, 255});
|
||||
DrawText(TextFormat("%.1f seconds", countdownRemaining), sw / 2 - 60,
|
||||
sh / 2 - 5, 20, RAYWHITE);
|
||||
} else if (roomState == 3) { // Finished
|
||||
DrawRectangle(sw / 2 - 200, sh / 2 - 50, 450, 100, (Color){0, 0, 0, 200});
|
||||
DrawRectangle(sw / 2 - 200, sh / 2 - 50, 400, 100, (Color){0, 0, 0, 200});
|
||||
DrawText("GAME FINISHED", sw / 2 - 80, sh / 2 - 30, 28,
|
||||
(Color){255, 80, 80, 255});
|
||||
if (winnerName[0]) {
|
||||
|
|
|
|||
BIN
game/client.o
BIN
game/client.o
Binary file not shown.
1
game/libfishsoup
Symbolic link
1
game/libfishsoup
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../libfishsoup
|
||||
BIN
game/server
BIN
game/server
Binary file not shown.
|
|
@ -1,3 +1,4 @@
|
|||
// game/server.c - SMOOTH TERRAIN VERSION
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -153,8 +154,6 @@ float get_terrain_height(float x, float z) {
|
|||
|
||||
#define TERRAIN_SIZE 256
|
||||
#define TERRAIN_SCALE 1.0f
|
||||
#define TERRAIN_MIN (-TERRAIN_SIZE * TERRAIN_SCALE / 2.0f)
|
||||
#define TERRAIN_MAX (TERRAIN_SIZE * TERRAIN_SCALE / 2.0f)
|
||||
static dReal *gHeightData = NULL;
|
||||
static dGeomID gTerrainGeom = NULL;
|
||||
|
||||
|
|
@ -300,7 +299,6 @@ typedef struct Player {
|
|||
uint32_t rng;
|
||||
float reloadTimer;
|
||||
int reloadWeapon;
|
||||
float borderDamageTimer;
|
||||
dBodyID body;
|
||||
dGeomID geom;
|
||||
} Player;
|
||||
|
|
@ -469,8 +467,6 @@ static void player_ode_create(Player *p, int spawnIndex) {
|
|||
dGeomSetBody(p->geom, p->body);
|
||||
dGeomSetCategoryBits(p->geom, CAT_PLAYER);
|
||||
dGeomSetCollideBits(p->geom, CAT_WORLD | CAT_PLAYER);
|
||||
|
||||
p->borderDamageTimer = 0.0f;
|
||||
}
|
||||
|
||||
static void player_ode_destroy(Player *p) {
|
||||
|
|
@ -993,71 +989,27 @@ int main(void) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
Player *p = &players[i];
|
||||
if (!p->inUse || !p->alive)
|
||||
continue;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
Player *p = &players[i];
|
||||
if (!p->inUse || !p->alive)
|
||||
continue;
|
||||
|
||||
const dReal *lvel = dBodyGetLinearVel(p->body);
|
||||
const dReal *avel = dBodyGetAngularVel(p->body);
|
||||
const dReal *lvel = dBodyGetLinearVel(p->body);
|
||||
const dReal *avel = dBodyGetAngularVel(p->body);
|
||||
|
||||
float dx = p->moveX, dz = p->moveZ;
|
||||
float len = sqrtf(dx * dx + dz * dz);
|
||||
if (len > 1e-6f) {
|
||||
dx /= len;
|
||||
dz /= len;
|
||||
}
|
||||
float dx = p->moveX, dz = p->moveZ;
|
||||
float len = sqrtf(dx * dx + dz * dz);
|
||||
if (len > 1e-6f) {
|
||||
dx /= len;
|
||||
dz /= len;
|
||||
}
|
||||
|
||||
float speed = 10.0f;
|
||||
float fx = sinf(p->yaw) * dz - cosf(p->yaw) * dx;
|
||||
float fz = cosf(p->yaw) * dz + sinf(p->yaw) * dx;
|
||||
dBodySetLinearVel(p->body, fx * speed, lvel[1], fz * speed);
|
||||
dBodySetAngularVel(p->body, avel[0], 0, avel[2]);
|
||||
}
|
||||
|
||||
// Border damage
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
Player *p = &players[i];
|
||||
if (!p->inUse || !p->alive)
|
||||
continue;
|
||||
const dReal *pos = dBodyGetPosition(p->body);
|
||||
float px = (float)pos[0], pz = (float)pos[2];
|
||||
if (px < TERRAIN_MIN || px > TERRAIN_MAX || pz < TERRAIN_MIN || pz > TERRAIN_MAX) {
|
||||
p->borderDamageTimer += DT;
|
||||
if (p->borderDamageTimer >= 0.5f) {
|
||||
p->borderDamageTimer -= 0.5f;
|
||||
p->hp -= 1;
|
||||
if (p->hp <= 0) {
|
||||
p->hp = 0;
|
||||
p->alive = 0;
|
||||
// Drop loot as in shooting death
|
||||
const dReal *pos2 = dBodyGetPosition(p->body);
|
||||
float x = (float)pos2[0], z = (float)pos2[2];
|
||||
if (p->pistolAmmo > 0) {
|
||||
int qty = p->pistolAmmo;
|
||||
if (qty > 12) qty = 12;
|
||||
item_spawn(ITEM_AMMO_PISTOL, qty, x + frand_signed(&p->rng) * 2.0f, z + frand_signed(&p->rng) * 2.0f);
|
||||
p->pistolAmmo -= qty;
|
||||
}
|
||||
if (p->rifleAmmo > 0) {
|
||||
int qty = p->rifleAmmo;
|
||||
if (qty > 30) qty = 30;
|
||||
item_spawn(ITEM_AMMO_RIFLE, qty, x + frand_signed(&p->rng) * 2.0f, z + frand_signed(&p->rng) * 2.0f);
|
||||
p->rifleAmmo -= qty;
|
||||
}
|
||||
if (p->medkits > 0) {
|
||||
int qty = p->medkits;
|
||||
if (qty > 2) qty = 2;
|
||||
item_spawn(ITEM_MEDKIT, qty, x + frand_signed(&p->rng) * 2.0f, z + frand_signed(&p->rng) * 2.0f);
|
||||
p->medkits -= qty;
|
||||
}
|
||||
printf("Player %d died from border damage and dropped loot\n", i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p->borderDamageTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
float speed = 10.0f;
|
||||
float fx = sinf(p->yaw) * dz - cosf(p->yaw) * dx;
|
||||
float fz = cosf(p->yaw) * dz + sinf(p->yaw) * dx;
|
||||
dBodySetLinearVel(p->body, fx * speed, lvel[1], fz * speed);
|
||||
dBodySetAngularVel(p->body, avel[0], 0, avel[2]);
|
||||
}
|
||||
|
||||
MsgSnapshot snap = {0};
|
||||
snap.type = MSG_SNAPSHOT;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue