Entropie git · main
Entropie festival game; first steps
C 88.5% Markdown 9.1% GLSL 2.3%git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gzentropie/src/world/course.c raw
#include "world/course.h"
#include "world/site.h"
#define LANE 3.5f /* meters between the lanes */
typedef enum { LOG, BRANCH, FIREWOOD, CRATE, BENCH, COOLBOX, WALL, STUMP, BLOCK } Piece;
typedef struct {
Piece piece;
float side, along; /* lane (-1 left, 0 middle, 1 right) and meters down the course */
Vec3 size; /* LOG: diameter; boxes: across, high, deep */
float kg;
} Obstacle;
static const Obstacle COURSE[] = {
/* left: spaced out, getting higher */
{ BRANCH, -1, 4.0f, { 0.0f, 0.9f, 0.0f }, 1.5f },
{ FIREWOOD, -1, 8.0f, { 0.3f, 0.45f, 2.0f }, 0.0f },
{ LOG, -1, 12.0f, { 0.20f, 0, 0 }, 0.0f },
{ LOG, -1, 16.0f, { 0.30f, 0, 0 }, 0.0f },
{ LOG, -1, 20.0f, { 0.42f, 0, 0 }, 0.0f },
{ CRATE, -1, 24.0f, { 0.8f, 0.3f, 0.4f }, 12.0f },
{ CRATE, -1, 28.0f, { 0.4f, 0.4f, 0.4f }, 6.0f }, /* the orange cube */
{ CRATE, -1, 32.0f, { 0.6f, 0.45f, 0.45f }, 18.0f },
{ CRATE, -1, 36.0f, { 0.8f, 0.6f, 0.6f }, 20.0f }, /* too high to step over */
/* middle: close together */
{ LOG, 0, 4.0f, { 0.30f, 0, 0 }, 0.0f },
{ LOG, 0, 5.0f, { 0.30f, 0, 0 }, 0.0f },
{ LOG, 0, 6.2f, { 0.30f, 0, 0 }, 0.0f },
{ LOG, 0, 7.6f, { 0.30f, 0, 0 }, 0.0f },
{ LOG, 0, 9.2f, { 0.30f, 0, 0 }, 0.0f },
{ LOG, 0, 12.0f, { 0.18f, 0, 0 }, 0.0f },
{ LOG, 0, 12.7f, { 0.18f, 0, 0 }, 0.0f },
{ LOG, 0, 13.4f, { 0.18f, 0, 0 }, 0.0f },
{ CRATE, 0, 16.0f, { 0.8f, 0.3f, 0.4f }, 12.0f },
{ CRATE, 0, 17.2f, { 0.8f, 0.3f, 0.4f }, 12.0f },
{ LOG, 0, 18.4f, { 0.36f, 0, 0 }, 0.0f },
/* right: things that stay put */
{ BENCH, 1, 4.0f, { 1.8f, 0.45f, 0.36f }, 0.0f },
{ COOLBOX, 1, 8.0f, { 0.6f, 0.45f, 0.4f }, 0.0f },
{ WALL, 1, 12.0f, { 2.0f, 0.35f, 0.25f }, 0.0f },
{ STUMP, 1, 16.0f, { 0.45f, 0.35f, 0.0f }, 0.0f },
{ BENCH, 1, 20.0f, { 1.8f, 0.45f, 0.36f }, 0.0f },
{ WALL, 1, 21.2f, { 2.0f, 0.25f, 0.25f }, 0.0f },
{ BLOCK, 1, 26.0f, { 1.2f, 0.6f, 0.8f }, 0.0f }, /* too high: step up / climb */
{ BLOCK, 1, 32.0f, { 1.6f, 1.1f, 1.0f }, 0.0f }, /* climb */
};
#define COURSE_COUNT ((int)(sizeof(COURSE) / sizeof(COURSE[0])))
static float ground(const World *world, Vec3 p) {
return Terrain_height(&world->terrain, p.x, p.z);
}
static Object *place(World *world, const Obstacle *o, Vec3 start, Vec3 along, Vec3 across) {
Vec3 p = vec3_add(start, vec3_add(vec3_scale(along, o->along), vec3_scale(across, o->side * LANE)));
p.y = ground(world, p);
float yaw = atan2f(across.z, across.x); /* (its width runs across the lane) */
Object *obj = NULL;
switch (o->piece) {
case LOG: {
obj = Object_create(OBJ_LOG, PALETTE_WARM, vec3_zero(), vec3(o->size.x, 1.6f, 0.0f), 0.0f);
if (obj) Object_makeLog(obj, vec3_add(p, vec3(0.0f, o->size.x * 0.5f + 0.01f, 0.0f)), across, 1.6f, o->size.x);
break;
}
case BRANCH:
obj = Object_create(OBJ_BRANCH, PALETTE_WARM, vec3_add(p, vec3(0.0f, 0.15f, 0.0f)), o->size, o->kg);
if (obj) Object_setRotation(obj, euler_yxz_from_axes(across, vec3(0.0f, 1.0f, 0.0f)));
break;
case FIREWOOD:
obj = Object_create(OBJ_FIREWOOD, PALETTE_WARM, vec3_add(p, vec3(0.0f, 0.15f, 0.0f)), o->size, 0.0f);
if (obj) Object_setRotation(obj, euler_yxz_from_axes(across, vec3(0.0f, 1.0f, 0.0f)));
break;
case CRATE:
obj = Object_create(OBJ_BOX, o->kg <= 6.0f ? PALETTE_WARM : PALETTE_STANDARD, p, o->size, o->kg);
break;
case BENCH:
obj = Object_createFurniture(FURN_BENCH, p, o->size, 0.0f);
break;
case COOLBOX:
obj = Object_create(OBJ_SUPPLY, PALETTE_STANDARD, p, o->size, 0.0f);
break;
case WALL:
case BLOCK:
obj = Object_create(OBJ_BOX_STATIC, PALETTE_GROUND, p, o->size, 100.0f);
break;
case STUMP:
obj = Object_create(OBJ_STUMP, PALETTE_WARM, vec3_add(p, vec3(0.0f, o->size.y * 0.5f, 0.0f)), o->size, 0.0f);
break;
}
if (obj && o->piece != LOG && o->piece != BRANCH && o->piece != FIREWOOD && o->piece != STUMP)
Object_setRotation(obj, vec3(0.0f, yaw, 0.0f)); /* (local x across: see mat4_rotate_y) */
return obj;
}
bool Course_build(World *world, Object *who, float *yaw) {
Vec3 start, along;
Site_courseFrame(&start, &along);
Vec3 across = vec3(-along.z, 0.0f, along.x);
for (int i = 0; i < COURSE_COUNT; i++) {
Object *o = place(world, &COURSE[i], start, along, across);
if (!o || !World_add(world, o)) return false;
}
if (!who) return true;
/* At the start of the middle lane, looking down the course */
who->position = vec3(start.x, ground(world, start) + 0.05f, start.z);
who->rotation.y = atan2f(along.z, along.x) + PI_F / 2.0f;
Object_syncColliders(who);
*yaw = atan2f(along.z, along.x);
return true;
}