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 1.60.0: folding ladder
- A folding ladder (two 2.5 m halves on a hinge, 5 m open) lies beside the telescopic one in the tool room - One click at a wall unfolds it in the put-up animation and leans it there; elsewhere a click unfolds or folds it Includes 1.59.0 (if not committed separately): - Stepping up onto blocks above knee high; set moves and jumps only for things standing on the ground in front of you Includes 1.58.0 (if not committed separately): - Walking over knee-high things is one smooth set move that always finishes; at a run: jump up onto blocks, catch climbable edges
entropie/Makefile | 2 +- entropie/README.md | 3 +++ entropie/STATE.md | 8 ++++--- entropie/commit_message.txt | 15 ++++++++----- entropie/src/game/game_actions.c | 9 +++++--- entropie/src/render/shapes.h | 5 +++++ entropie/src/render/shapes_props.c | 46 ++++++++++++++++++++++++++++++++++++++ entropie/src/world/ladder.c | 20 ++++++++++------- entropie/src/world/ladder.h | 2 ++ entropie/src/world/object.c | 11 ++++++--- entropie/src/world/site.c | 13 ++++++----- 11 files changed, 105 insertions(+), 29 deletions(-) diff --git a/entropie/Makefile b/entropie/Makefile index 371d4a5..2ed03c0 100644 --- a/entropie/Makefile +++ b/entropie/Makefile @@ -1,5 +1,5 @@ APP := entropie -VERSION := 1.59.0 +VERSION := 1.60.0 PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin diff --git a/entropie/README.md b/entropie/README.md index a606264..23241d4 100644 --- a/entropie/README.md +++ b/entropie/README.md @@ -317,6 +317,9 @@ A hand that can't reach its grip lets go and takes hold again. - A telescopic ladder (6 m out, 1.5 m together) lies in the tool room of your garages, on the floor along the end wall +- Beside it lies a folding ladder (two 2.5 m halves on a hinge, 5 m open). + A click at a wall unfolds it and leans it there; elsewhere a click unfolds + or folds it - Ladder in hand: click at a wall and it slides out just as far as it takes (about 0.9 m over the edge) and leans there in one go: you stand it up, slide it out and tip it onto the wall (about a second); slid out by hand diff --git a/entropie/STATE.md b/entropie/STATE.md index 2ecdcf4..8945bf8 100644 --- a/entropie/STATE.md +++ b/entropie/STATE.md @@ -93,6 +93,8 @@ Talk topics: offer, ask, suggest, where (new woodpile spot), ask for a hand, ask Ladder: one click at a wall slides it out to fit (top on the edge, 0.9 m over it; up to its 6 m) and leans it; slid out by hand, it keeps that length. Putting it up is a 1.1 s animation (`ladder.c`, putUp): stood upright, slid out, tipped onto the wall; you stand still with both hands on it (`game.c`, puttingUp); it can only be climbed or taken once it leans. +Folding ladder (`variant` LADDER_FOLDING, 9.8 kg so it carries one-handed): two 2.5 m sections on a hinge (`shapes_props.c`, Shapes_foldLadder: the upper section swings round the hinge by `extend`). It is either folded (2.5 m) or open (5 m, 18 rungs); leaning at a wall it always opens fully, the putUp animation swings the upper half up. `ladder.c` lengthFor / rung / rungCount pick per type. + Raised ladder: slid out (extend goal > 0.5) and in hand, it's held 0.45 m up from its foot, the hand in front, the other hand higher up the rail, tipped up 60 deg in front (43-83 deg with the view pitch, eased 1.6 rad/s; `ladder.c` Ladder_placeHeld). A click leans it where you look (view ray, ladder length + 1.5 m; else a ray along the ladder, length + 0.8 m; a top face: the side towards you under that edge). Aimed within 0.45 m of the top it rests on the edge; lower, against the face at that height, flatter (no flatter than 55 deg: "aim at least X m up"); its foot at most 1.8 m from you. Looking down (view y < -0.6) a click slides it together; nothing aimed at: says so. Carrying long things (ladder, logs: 0.62 m and longer): they stop at people and the dog like at walls (unless you carry it together), push them out of the way (up to 25 cm a frame), knock light loose things aside; NPCs treat a long thing someone carries as in the way and walk round it (`world.c` pushOffCarried, `ai.c` ai_blockedBy). @@ -107,7 +109,7 @@ Piling styles: how neatly someone stacks (`ai_stackCare`: firewood skill and lik Woodpile: firewood is stacked into the lowest free place (gaps left by pieces taken off are filled first); it counts what really lies on it; a piece that fell off is loose again (gets restacked). -Bottles (beer, vodka, water), apples, bread, sausages (grill: done, dark, burnt), crates and boxes, logs, branches, firewood, stumps, woodpiles, fireplace, trash and garbage bags, the waste container, tables and garage furniture, stones, garden hose (a rope: falls, lies, drapes round things), watering can, telescopic ladder, axe, shears, chainsaw, trees (fruit trees too), bushes, cars, buildings. +Bottles (beer, vodka, water), apples, bread, sausages (grill: done, dark, burnt), crates and boxes, logs, branches, firewood, stumps, woodpiles, fireplace, trash and garbage bags, the waste container, tables and garage furniture, stones, garden hose (a rope: falls, lies, drapes round things), watering can, telescopic and folding ladder, axe, shears, chainsaw, trees (fruit trees too), bushes, cars, buildings. ## World @@ -146,7 +148,7 @@ Most important first. - Clothing (trousers, skirt, dress, fly) – needed for the above **Things** -- More ladder types: a folding ladder (unfolds when put up) and a step ladder +- More ladder types: a step ladder (stands on its own) - Hose near fire: melts, may burn; duct tape for small damage; burned through: shorter, or cut the bad part (knife, scissors) and join the ends; put the fire out with your drink (C) **Tools for us** @@ -157,4 +159,4 @@ Most important first. - The walking map rebuild takes ~9 ms when fixed things change (a felled tree) --- -State of `entropie 1.59.0 (build 1eab5b0)` +State of `entropie 1.60.0 (build 6e3e5e9)` diff --git a/entropie/commit_message.txt b/entropie/commit_message.txt index 5bf0914..bdbb1ab 100644 --- a/entropie/commit_message.txt +++ b/entropie/commit_message.txt @@ -1,10 +1,13 @@ -entropie 1.59.0: stepping up onto blocks; set moves only for things on the ground +entropie 1.60.0: folding ladder -- Walking at a block above knee high up to about hip high with room on - top: you step up onto it, one leg after the other (no more knees - through its face) -- Set moves and jumps only for things standing on the ground in front of - you (something lying up on a roof made people step over thin air) +- A folding ladder (two 2.5 m halves on a hinge, 5 m open) lies beside + the telescopic one in the tool room +- One click at a wall unfolds it in the put-up animation and leans it + there; elsewhere a click unfolds or folds it + +Includes 1.59.0 (if not committed separately): +- Stepping up onto blocks above knee high; set moves and jumps only for + things standing on the ground in front of you Includes 1.58.0 (if not committed separately): - Walking over knee-high things is one smooth set move that always diff --git a/entropie/src/game/game_actions.c b/entropie/src/game/game_actions.c index d29585d..e650ffa 100644 --- a/entropie/src/game/game_actions.c +++ b/entropie/src/game/game_actions.c @@ -357,15 +357,18 @@ static bool useLadder(Game *game) { int lean = Ladder_lean(&game->world, p, ladder, was_in, &why); if (was_in && lean != LEAN_DONE) { Ladder_setExtend(ladder, extend_was); ladder->extend_goal = 0.0f; } if (lean == LEAN_DONE) game->putting_up = ladder; + const bool fold = ladder->variant == LADDER_FOLDING; if (lean == LEAN_DONE) - say(game, ladder->lean_top > 0.0f ? (was_in ? "You slide the ladder out and lean it there - click it to climb" + say(game, ladder->lean_top > 0.0f ? (was_in ? (fold ? "You unfold the ladder and lean it there - click it to climb" + : "You slide the ladder out and lean it there - click it to climb") : "The ladder leans there - click it to climb") : "It leans there, but doesn't reach the top"); else if (lean == LEAN_NO) say(game, why); else { Ladder_slide(ladder); - say(game, ladder->extend_goal > 0.5f ? "You slide the ladder out - click at a wall to lean it there" - : "You slide the ladder together"); + if (fold) say(game, ladder->extend_goal > 0.5f ? "You unfold the ladder - click where it should lean" : "You fold the ladder up"); + else say(game, ladder->extend_goal > 0.5f ? "You slide the ladder out - click at a wall to lean it there" + : "You slide the ladder together"); } return true; } diff --git a/entropie/src/render/shapes.h b/entropie/src/render/shapes.h index 4cf1566..d086276 100644 --- a/entropie/src/render/shapes.h +++ b/entropie/src/render/shapes.h @@ -136,6 +136,11 @@ float Shapes_ladderLength(float extend); /* Height of rung k (0 = the lowest) along the ladder. */ float Shapes_ladderRung(float extend, int k); Mesh Shapes_ladder(float extend); +/* The folding ladder (two hinged sections): unfold 0 = folded .. 1 = straight. */ +#define FOLD_RUNGS 9 /* per section */ +float Shapes_foldLadderLength(float unfold); +float Shapes_foldLadderRung(int k); +Mesh Shapes_foldLadder(float unfold); /* A round bush, base at y = 0. */ Mesh Shapes_bush(float diameter, float height, unsigned seed); diff --git a/entropie/src/render/shapes_props.c b/entropie/src/render/shapes_props.c index 9844511..68edd06 100644 --- a/entropie/src/render/shapes_props.c +++ b/entropie/src/render/shapes_props.c @@ -872,6 +872,52 @@ float Shapes_ladderLength(float extend) { return Shapes_ladderRung(extend, LADDER_RUNGS - 1) + LADDER_CAP; } +/* The folding ladder: two sections on a hinge. Folded, the upper one lies + along the lower (inside its rails, a little in front); unfolding, it + swings up and over to stand straight on top of it. */ +#define FOLD_PITCH 0.28f +#define FOLD_SECTION (LADDER_FOOT + FOLD_PITCH * (float)(FOLD_RUNGS - 1) + 0.14f) +#define FOLD_INSET 0.045f +#define FOLD_FRONT 0.05f + +static float foldAngle(float unfold) { return PI_F * (1.0f - clampf(unfold, 0.0f, 1.0f)); } + +float Shapes_foldLadderLength(float unfold) { + return fmaxf(FOLD_SECTION, FOLD_SECTION * (1.0f + cosf(foldAngle(unfold)))); +} + +float Shapes_foldLadderRung(int k) { + return k < FOLD_RUNGS ? LADDER_FOOT + FOLD_PITCH * (float)k + : FOLD_SECTION + LADDER_FOOT + FOLD_PITCH * (float)(k - FOLD_RUNGS); +} + +/* One section along +Y from 0, rails half apart. */ +static void foldSection(MeshBuilder *b, float half, bool lower) { + const Vec3 alu = { 0.80f, 0.70f, 0.42f }, joint = { 0.22f, 0.20f, 0.18f }; /* (yellowish: tell it from the other one) */ + for (int s = -1; s <= 1; s += 2) { + float x = (float)s * half; + addBlock(b, vec3(x, FOLD_SECTION * 0.5f, 0.0f), vec3(0.04f, FOLD_SECTION, 0.06f), alu); + if (lower) addBlock(b, vec3(x, 0.02f, 0.0f), vec3(0.06f, 0.04f, 0.07f), joint); /* rubber feet */ + else addBlock(b, vec3(x, FOLD_SECTION - 0.015f, 0.0f), vec3(0.05f, 0.03f, 0.06f), joint); /* end caps */ + } + for (int k = 0; k < FOLD_RUNGS; k++) + addBlock(b, vec3(0.0f, LADDER_FOOT + FOLD_PITCH * (float)k, 0.0f), vec3(2.0f * half, 0.03f, 0.045f), alu); +} + +Mesh Shapes_foldLadder(float unfold) { + const Vec3 joint = { 0.22f, 0.20f, 0.18f }; + const float half = LADDER_WIDTH * 0.5f; + MeshBuilder b; + MeshBuilder_init(&b); + foldSection(&b, half, true); + for (int s = -1; s <= 1; s += 2) /* the hinges */ + addBlock(&b, vec3((float)s * (half - FOLD_INSET * 0.5f), FOLD_SECTION, FOLD_FRONT * 0.5f), vec3(0.07f, 0.08f, 0.1f), joint); + size_t first = b.vertex_count; + foldSection(&b, half - FOLD_INSET, false); + transformSince(&b, first, mat4_mul(mat4_translate(vec3(0.0f, FOLD_SECTION, FOLD_FRONT)), mat4_rotate_x(foldAngle(unfold)))); + return Mesh_fromBuilder(&b); +} + Mesh Shapes_ladder(float extend) { const Vec3 alu = { 0.76f, 0.78f, 0.80f }, joint = { 0.20f, 0.20f, 0.22f }; const float half = LADDER_WIDTH * 0.5f, top = Shapes_ladderLength(extend); diff --git a/entropie/src/world/ladder.c b/entropie/src/world/ladder.c index 55e1a85..68148c6 100644 --- a/entropie/src/world/ladder.c +++ b/entropie/src/world/ladder.c @@ -32,13 +32,16 @@ static const Vec3 UP = { 0.0f, 1.0f, 0.0f }; static Vec3 flatv(Vec3 v) { return vec3(v.x, 0.0f, v.z); } static float flatDist(Vec3 a, Vec3 b) { return vec3_length(flatv(vec3_sub(a, b))); } -static float lengthOf(const Object *l) { return Shapes_ladderLength(l->extend); } +/* Two kinds: telescopic (variant 0: slides out) and folding (variant 1: two sections on a hinge, unfolds). */ +static bool folding(const Object *l) { return l->variant == LADDER_FOLDING; } +static float lengthFor(const Object *l, float extend) { return folding(l) ? Shapes_foldLadderLength(extend) : Shapes_ladderLength(extend); } +static float lengthOf(const Object *l) { return lengthFor(l, l->extend); } static Vec3 upAlong(const Object *l) { return l->colliders[0].axes[1]; } static Vec3 pointAt(const Object *l, float along) { return vec3_add(l->position, vec3_scale(upAlong(l), along)); } /* New mesh and collider for the current length. */ static void reshape(Object *l) { - Mesh mesh = Shapes_ladder(l->extend); + Mesh mesh = folding(l) ? Shapes_foldLadder(l->extend) : Shapes_ladder(l->extend); if (mesh.vao) { Mesh_destroy(&l->mesh); l->mesh = mesh; @@ -242,9 +245,9 @@ int Ladder_lean(World *world, Object *who, Object *l, bool fit, const char **why float mid = 0.5f * (lo + hi); if (Shapes_ladderLength(mid) < want) lo = mid; else hi = mid; } - extend_to = hi; + extend_to = folding(l) ? 1.0f : hi; /* (folding: all the way, it has no in between) */ } - const float len = Shapes_ladderLength(extend_to); + const float len = lengthFor(l, extend_to); bool reaches = h <= len * sinf(angle) - 0.15f; /* aimed lower down the face (not at its top): against the face there, as high as it reaches */ float against = len * sinf(angle) - 0.1f; @@ -411,13 +414,14 @@ int Ladder_climb(Object *who, float input, float dt) { } /* Rung k's height along the ladder. */ -static float rung(const Object *l, int k) { return Shapes_ladderRung(l->extend, k); } +static float rung(const Object *l, int k) { return folding(l) ? Shapes_foldLadderRung(k) : Shapes_ladderRung(l->extend, k); } +static int rungCount(const Object *l) { return folding(l) ? (l->extend > 0.99f ? 2 * FOLD_RUNGS : FOLD_RUNGS) : LADDER_RUNGS; } /* The rung at or just above `along`. */ static int rungAbove(const Object *l, float along) { - for (int k = 0; k < LADDER_RUNGS; k++) + for (int k = 0; k < rungCount(l); k++) if (rung(l, k) >= along) return k; - return LADDER_RUNGS - 1; + return rungCount(l) - 1; } /* A hand or foot going from rung to rung: it speeds up and slows down, and @@ -473,7 +477,7 @@ void Ladder_poseFeet(Object *who, float dt) { for (int i = 0; i < 2; i++) { /* one foot a rung higher than the other, swapping as you climb */ int kf = k + ((k + i) % 2 == 0 ? 0 : 1); - if (kf >= LADDER_RUNGS) kf = LADDER_RUNGS - 1; + if (kf >= rungCount(l)) kf = rungCount(l) - 1; float side = i == 0 ? 1.0f : -1.0f; Foot *foot = &who->body.feet[i]; Vec3 goal = vec3_add(pointAt(l, rung(l, kf)), vec3_add(vec3_scale(across, side * 0.11f), diff --git a/entropie/src/world/ladder.h b/entropie/src/world/ladder.h index b4957c2..3670244 100644 --- a/entropie/src/world/ladder.h +++ b/entropie/src/world/ladder.h @@ -21,6 +21,8 @@ void Ladder_setExtend(Object *ladder, float extend); /* Eases the sliding along, rebuilding mesh and collider as it goes. */ void Ladder_update(Object *ladder, float dt); +#define LADDER_FOLDING 1 /* variant: two sections on a hinge (unfolds); 0: telescopic (slides out) */ + enum { LEAN_NOTHING, LEAN_DONE, LEAN_NO }; /* Leans the ladder who carries against what's right in front. LEAN_NO sets why. fit: slides it out as far as it takes (over the edge a bit) first. */ diff --git a/entropie/src/world/object.c b/entropie/src/world/object.c index 317ab6a..eb85ccd 100644 --- a/entropie/src/world/object.c +++ b/entropie/src/world/object.c @@ -954,9 +954,14 @@ void Object_describe(const Object *obj, char *out, size_t size) { } case OBJ_HOSE: snprintf(out, size, "Garden hose - left click (hold) to spray: washes away puddles and dirt"); break; case OBJ_LADDER: - snprintf(out, size, obj->leaning ? "Ladder - left click: climb (W / S), E / Q: take it down" - : obj->extend_goal > 0.5f ? "Ladder (slid out) - left click at a wall: lean it there, else slide it together" - : "Ladder (slid together) - left click: slide it out, then lean it against something"); + if (obj->variant == 1) /* (folding) */ + snprintf(out, size, obj->leaning ? "Folding ladder - left click: climb (W / S), E / Q: take it down" + : obj->extend_goal > 0.5f ? "Folding ladder (unfolded) - left click where it should lean, look down: fold it" + : "Folding ladder (folded) - left click at a wall: unfold it and lean it there"); + else + snprintf(out, size, obj->leaning ? "Ladder - left click: climb (W / S), E / Q: take it down" + : obj->extend_goal > 0.5f ? "Ladder (slid out) - left click at a wall: lean it there, else slide it together" + : "Ladder (slid together) - left click: slide it out, then lean it against something"); break; case OBJ_STONE: snprintf(out, size, kg >= 1 ? "A stone - %d kg" : "A pebble", kg); break; case OBJ_CAN: diff --git a/entropie/src/world/site.c b/entropie/src/world/site.c index cce9a02..8ee92df 100644 --- a/entropie/src/world/site.c +++ b/entropie/src/world/site.c @@ -1,4 +1,5 @@ #include "world/site.h" +#include "world/ladder.h" #include <stdio.h> #include <SDL3/SDL.h> @@ -723,17 +724,19 @@ static bool furnishGarages(World *world, Vec3 origin, float yaw, float zsign) { if (!o || !World_add(world, o)) return false; } /* The tools: on and by the workbench in the tool room */ - struct { ObjectType type; Vec3 at, size, rot; float kg; } TOOLS[] = { - { OBJ_AXE, { 26.5f, 1.0f, 12.0f }, { 0.0f, 0.8f, 0.0f }, { 90, 0, 0 }, 2.2f }, - { OBJ_SHEARS, { 26.5f, 1.0f, 13.2f }, { 0.0f, 0.3f, 0.0f }, { 90, 20, 0 }, 0.4f }, - { OBJ_CHAINSAW, { 25.6f, 0.3f, 12.0f }, { 0.0f, 0.0f, 0.0f }, { 0, 60, 0 }, 6.0f }, - { OBJ_LADDER, { 20.9f, 0.1f, 13.55f }, { 0.0f, 0.0f, 0.0f }, { 90, 90, 0 }, 9.5f }, /* slid together, along the end wall */ + struct { ObjectType type; Vec3 at, size, rot; float kg; int variant; } TOOLS[] = { + { OBJ_AXE, { 26.5f, 1.0f, 12.0f }, { 0.0f, 0.8f, 0.0f }, { 90, 0, 0 }, 2.2f, 0 }, + { OBJ_SHEARS, { 26.5f, 1.0f, 13.2f }, { 0.0f, 0.3f, 0.0f }, { 90, 20, 0 }, 0.4f, 0 }, + { OBJ_CHAINSAW, { 25.6f, 0.3f, 12.0f }, { 0.0f, 0.0f, 0.0f }, { 0, 60, 0 }, 6.0f, 0 }, + { OBJ_LADDER, { 20.9f, 0.1f, 13.55f }, { 0.0f, 0.0f, 0.0f }, { 90, 90, 0 }, 9.5f, 0 }, /* slid together, along the end wall */ + { OBJ_LADDER, { 23.2f, 0.1f, 13.55f }, { 0.0f, 0.0f, 0.0f }, { 90, 90, 0 }, 9.8f, LADDER_FOLDING }, /* folded, beside it */ }; for (unsigned i = 0; i < sizeof(TOOLS) / sizeof(TOOLS[0]); i++) { Vec3 pos = placed(TOOLS[i].at, WALLED_CENTER, origin, yaw, zsign); Object *o = Object_create(TOOLS[i].type, PALETTE_WARM, pos, TOOLS[i].size, TOOLS[i].kg); if (!o) return false; Object_setRotation(o, vec3(deg2rad(TOOLS[i].rot.x), deg2rad(TOOLS[i].rot.y) + yaw, deg2rad(TOOLS[i].rot.z))); + if (TOOLS[i].variant) { o->variant = TOOLS[i].variant; Ladder_setExtend(o, 0.0f); } if (!World_add(world, o)) return false; } return true;