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 – architecture
How the code is put together. Read before adding a feature; update it in the same version when the structure changes (rules for working on it: RULES.md).
Modules
| Folder | What it is | May include |
|---|---|---|
src/core/ | window, GL loader (gl.h: every GL call is listed there), input, sound out (audio.c: a synthesizer and mixer, no sound files) | core |
src/math/ | vectors, matrices, frustum, yaw conventions (linalg.h) | math |
src/render/ | renderer and its passes, shaders' uniforms, meshes, procedural shapes (shapes*.c), figures, camera, sky, UI | core, math, render |
src/world/ | Object, World, physics, terrain, the map (site.c, scene.c, manor.c - also the Berlin rooms off the map, course.c), everybody in the story (cast.c), the floors' stages (stage.c), the side jobs' ground (field.c: the Kartoffelacker's grass, the snails, Kerry's art), the why questions' content (why.c), the festival's guests (guests.c), the big old tree's places (bigtree.c), broken bones and casts (injury.c), tools, forestry, ladder, hose, camp, clothes, car, water, weather, grass, grid, day | everything but game |
src/people/ | bodies (animation), hands, AI (the projects: ai_project.c, the side jobs and the big tree: ai_jobs.c, the festival weekend: ai_fest.c, held, hand in hand, stepping in: ai_touch.c), touching somebody and what it means (touch.c), talk, condition, dog, climbing | everything but game |
src/game/ | the frame: input to actions, player, camera follow, talk and dev UI, the arrival by car at the start, the story (game_story.c: the crew turning up, the crew overview), the shopping run (game_shop.c), the meetings in Berlin and the weekends (game_meeting.c), the why questions coming up and your notebook (game_why.c), the festival weekend and the storm (game_festival.c), the supporters' shifts, the clean-up and the drive home (game_cleanup.c), the big tree's rope and fall (game_bigtree.c), the ambulance and the hospital (game_injury.c), reaching out, holding people and who saw it (game_touch.c), saves (save.c), what you hear (sound.c) | all |
renderknows nothing of the world: it gets meshes, matrices and plain numbers.worldandpeopleare one layer: anObjectowns itsBody,AiandHands.*_internal.h: shared inside one module only.
One frame
Game_update → input, actions, talk, player → World_update:
physics for every object (near ones from the Grid) → grid rebuilt → felling and
cutting → hands (pushing, carrying) → hose → AI → bodies animated → props
(gates, chairs, ashtray, pullovers put down). Then the camera follows (game.c), and
Game_render: shadow pass, scene pass (terrain, objects, figures, grass), the sky,
Game_renderAir (rain, smoke, chips: after the sky, so they show against it),
ink pass, UI. Sound_update (main.c) after the update: the world's noises of the
frame and the steady sounds.
Budget: the update takes about 1 ms for ~950 objects. Drawing skips what's out of view (objects, 8×8 terrain tiles).
Objects
- One struct for every thing (
world/object.h):type,variant, size, - Fields only some kinds use are commented with the kind ("characters:",
is_static: never moved by physics. Only their own code moves them- Meshes come from
Shapes_*and are rebuilt only when what they show changes
position, rotation (yaw rotation.y), up to 3 oriented box colliders.
"gates:", "chairs:"). Objects start zeroed: zero must be a safe default.
(Object_swingGate, Object_slideChair), then Object_syncColliders.
(shown pattern in world.c showProps).
Space and turning
- y up, meters, seconds. Yaw: local +X turns to (cos, 0, sin), +Z to (-sin, 0, cos).
yaw_along(dir): lengths along +X (logs, gates, wall pieces).- The courtyard:
court(a, b)insite.c. The main building: local x along
yaw_facing(dir): fronts along +Z (furniture, doors, windows, chairs).
yaw_front(yaw): where a front points.
it, +z towards the yard (manor.c).
Building the map
Scene_load (start things) → Site_build (static things, buildings, roads)
→ World_buildTerrain (levels the ground under static things) →
Site_finish / Scene_finish (things that sit on the ground).
- Buildings you walk into (
manor.c): aPlanof boxes (box,wallX, - Below the ground:
Terrain_addPit(a turned rectangle). The ground's height
wallZ with gaps, opening). The look is one OBJ_STRUCTURE mesh, the
solid parts invisible OBJ_WALLs.
there is the pit floor, the ground isn't drawn there (holes in scene.frag).
Physics
- Per object, against near objects and the terrain. Characters: walk up stairs
- Rays:
Collider_ray/Object_rayToCollider(one box),World_rayCast
(up to SNAP_UP_MOST), higher edges and things to step over or onto are a set
move (over_t, beginStepOver); sitting down is a set move too (sit_moving).
(the first thing along a ray, with a skip filter). Down to the ground:
World_groundHeight.
Rendering
- One scene shader for everything not a figure: uniforms switch it to terrain
- New GL calls: add them to the list in
core/gl.h.
(terrainSize), decals, grass, glow. Figures have their own shader. The ink
pass draws the outlines over it all.
Sound
core/audio.c: SDL3 audio stream, mixed on the audio thread. Short voices- The world queues what makes a sound this frame:
World_noise(steps with - M mutes; menus pause the beds.
(noise, sine, saw or crackle; filters; attack and decay; pan; delay) and steady beds (wind, rain, fire, chainsaw, engine, crickets, hose) turned up and down. No device: silent, nothing else changes.
what's underfoot, chops, clinks, glass, thuds, a tree coming down, twigs).
game/sound.c empties the list each frame and plays them by distance and side
from the camera; the beds follow the weather, the fires, a chainsaw, the car.
Crates
- Each slot is known (
Object.crate_slot: kind and sips,CRATE_SLOT):
stored, crate_empties and the weight follow from it (Crate_recount).
Bottles of another kind put into a crate stay there as such until somebody
sorts them (Crate_takeWrong, the tidy: ai_help.c sortCrates).
Saves
src/game/save.c:<name>.sav(text:key valuelines,[game], then[o id]per object) and<name>.ground(binary: the wear map, the wet chunks). In the user's data folder (Platform_saveDir).- Loading builds the world as at the start (
Game_initWorld(game, false): no drive in), finds the scene's things byscene_id/spawn/spawn_type(set when the scene is built), makes the rest anew (Object_createwith the saved type, palette, size andmake_arg), then sets the fields and rebuilds what looks different (trees, tents, gear, crates, bags, bottles, ladders, pullovers, the car). - What's saved: the tables
THINGandPERSONin save.c (plus skills, likes, keys, hands, the car's boot, asleep). Buildings, walls, roads, bushes: only found again. - Keeping old saves working:
- A new field: add it to a table. Old saves don't have it: it keeps what the fresh world gives it.
- A key renamed or its meaning changed: raise
SAVE_FORMAT(save.h) and add a step tomigrate()that rewrites the old lines. - A save from a newer format is refused, never guessed at.
- A thing the scene no longer makes is dropped; one it newly makes keeps its fresh state.
- Not kept (comes back fresh): what anybody was in the middle of (AI plans, paths, poses), sparks and smoke. Kept specially: the hose's rope (
ropeline: every point, melted, taped), who sits where (sitline: sat down again, staying a while), who's up a ladder (ladderline: you back on it as high,Ladder_mountAt; the others at its foot), what's in each crate slot (slotsline; older saves: their own bottles, so many full and empty), holding on to something together (grab,helplines).
Versions
Makefile VERSION; the build id is an md5 of sources and assets
(make version). STATE.md ends with the version it describes.