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.99.0: catching breath, calm breathing
- Fixed: after running the shoulders twitched very fast (the breathing sped through whole breaths whenever it slowed down again); breathing is now calm, quicker only the more out of breath - Out of breath and standing still, people catch it their own way: the unfit bent over with the hands on the knees, the sporty hands on top of the head or a light stretch, anyone hands on the hips
entropie/Makefile | 2 +- entropie/README.md | 4 ++++ entropie/STATE.md | 6 +++++- entropie/commit_message.txt | 13 +++++++------ entropie/src/people/body.c | 16 +++++++++++----- entropie/src/people/body.h | 1 + entropie/src/people/body_internal.h | 11 +++++++++++ entropie/src/people/body_pose.c | 21 +++++++++++++-------- 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/entropie/Makefile b/entropie/Makefile index c9c7b4b..52ec634 100644 --- a/entropie/Makefile +++ b/entropie/Makefile @@ -1,5 +1,5 @@ APP := entropie -VERSION := 1.98.0 +VERSION := 1.99.0 PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin diff --git a/entropie/README.md b/entropie/README.md index e68e1ac..2c19385 100644 --- a/entropie/README.md +++ b/entropie/README.md @@ -295,6 +295,10 @@ and satellite pictures (about 340 x 340 m). Now and then someone shakes a leg loose, rocks on the toes, stretches, rolls the shoulders, stretches the neck, folds the arms, taps a foot, rubs the hands, clasps them behind the head or puts both on the hips +- Out of breath (after running, hard work), standing still: they catch it - + the unfit bent over with the hands on the knees, the sporty with the hands + on top of the head or a light stretch, anyone hands on the hips. Breathing + is calm and slow, and quicker the more out of breath - One hand now and then: on the hip, scratching the head, at the chin, in the pocket, rubbing the neck or the nose, at the ear, back through the hair, thumb in the belt, on the chest, shading the eyes. How someone feels diff --git a/entropie/STATE.md b/entropie/STATE.md index 47de684..77ae157 100644 --- a/entropie/STATE.md +++ b/entropie/STATE.md @@ -142,6 +142,10 @@ Round 1.98: - NPCs step up onto higher things (`object.c` Object_stepUpMost: (0.38 + 0.37 fitness) x (0.75 + 0.25 vigor) - 0.25 drunk, 0.25-0.75 m scaled; the player 0.75). `ai.c` longToStepOnto: static things too (not a building's parts), 1.5 m long or more; up to ONTO_HIGH 0.55 anything, higher up to their own most if at least ONTO_DEEP 0.5 m deep. `physics.c` startStepOver: the "higher" step up for NPCs as high as Object_stepUpMost (it was the player only). - Step over / onto: where the way meets the thing's near and far face from a ray (`Collider_ray`) instead of its projected radius - at a slant a long thing's corner made the step start 1 m early and land in the air before it. +Round 1.99: +- Breathing (`body_pose.c` solveStanding): `breath_phase` runs at the breathing rate (1.5 + 0.6 nerves + 3 exertion rad/s); it was sin(clock x rate), which raced through whole breaths whenever the rate changed (recovering after running: the shoulders twitched fast). +- Catching breath (`body.c` fidgets): `puffed` = smoothstep(0.35, 0.75, exertion); fidgets come up to 4x sooner. New FIDGET_KNEES (bent over, `bentDown` = max(being sick, 0.85 x catchingBreath, eased 0.9 s), hands on the thighs above the knees; weight 4 puffed x (1.15 - fitness) - proud) and FIDGET_ON_HEAD (fingers laced on top of the head, elbows up, chest open; 3.5 puffed x (0.2 + fitness)); hands on the hips +2 puffed, a stretch +1.2 puffed x fitness. + Unfinished building (Shell_build, at SHELL_AT in the frame's frame): brick shell 6.4 x 4.7, walls 2.9, open front (2 m) to the frame (now only the front half: pillars at z -13.8 / -9.2), window holes, bare floor, tiled roof with slabs. Barn: brick courses on BUILDING_BRICK walls (`addBrickCourses`: mortar a shade lighter, so the ink doesn't trace it), ivy (`Shapes_ivy`, OBJ_STRUCTUREs) on both long sides; the woodpile (OBJ_WOODPILE "Woodpile", WOODPILE_A/B) left of the toilet, everybody's woodpile from the start (`scene.c` Scene_finish). Fireplace tripod: wooden poles, feet TRIPOD_OUT 0.9 m outside the stones, TRIPOD_PAST 0.4 m past the top, a lashing; each pole an OBJ_WALL along it ("Tripod pole"). Gates (FURN_GATE, green boards): in your garages' doorways (GATES: hinge, end), `gate_open` / `gate_t`, `hinge`, `gate_shut` / `gate_out`; Object_swingGate (1.2 s), driven by showProps; a click within 1.2 m opens / shuts both leaves. Props that show (1.89, `world.c` showProps every frame): the tin's mesh is built again when its butts change (`Shapes_ashtray`: up to 12 show, the ash rises, a heap from 14; `shown` = what's built); the coat rack (FURN_COATRACK, in your kitchen by the doors, garage coords 20.6 / 2.4) shows the jackets hanging on it (`Shapes_coatRack`, up to 6, a bitmask of whose in `shown`). `jacket_hung` (characters, true at the start): cold (chill 0.6+) and the jacket with them: on it goes (as before); hanging: NPCs `ai.want_jacket` -> `ai.c` fetchJacket (idle / wander: goTo the rack, on with it, "Ah, better."; gives up after 90 s or warm again); you are told once ("your jacket hangs on the rack in your garage") and click the rack (`game_actions.c` coatRack: on, or back onto it). Warm again: it comes off and stays with them. @@ -294,4 +298,4 @@ Most important first. - Drawing many figures on a real graphics card: not measured (software GL: 300 people cost 3x the rest of the scene) --- -State of `entropie 1.98.0 (build f761dd4)` +State of `entropie 1.99.0 (build 39a2b19)` diff --git a/entropie/commit_message.txt b/entropie/commit_message.txt index 35ae27f..6c0ad47 100644 --- a/entropie/commit_message.txt +++ b/entropie/commit_message.txt @@ -1,7 +1,8 @@ -entropie 1.98.0: people step up onto blocks and crates +entropie 1.99.0: catching breath, calm breathing -- People step up onto a long block, crate or log in their way instead of - always walking round: the sporty and fresh up to about hip height, the - unfit, worn out or drunk only about knee high -- Stepping over or onto something long at a slant starts at its face, not - a metre early in mid-air (for you too) +- Fixed: after running the shoulders twitched very fast (the breathing + sped through whole breaths whenever it slowed down again); breathing is + now calm, quicker only the more out of breath +- Out of breath and standing still, people catch it their own way: the + unfit bent over with the hands on the knees, the sporty hands on top of + the head or a light stretch, anyone hands on the hips diff --git a/entropie/src/people/body.c b/entropie/src/people/body.c index 524811e..9792fca 100644 --- a/entropie/src/people/body.c +++ b/entropie/src/people/body.c @@ -5,7 +5,7 @@ #include "people/body_internal.h" -static const float FIDGET_LENGTH[FIDGET_COUNT] = { 0.0f, 1.6f, 2.4f, 2.6f, 2.0f, 3.0f, 6.0f, 2.8f, 2.4f, 5.0f, 5.0f }; +static const float FIDGET_LENGTH[FIDGET_COUNT] = { 0.0f, 1.6f, 2.4f, 2.6f, 2.0f, 3.0f, 6.0f, 2.8f, 2.4f, 5.0f, 5.0f, 5.5f, 5.0f }; static Vec3 clearSpot(const BodyFrame *f, Foot *foot, Vec3 spot, Vec3 other, float reach, bool sloppy, float s); static Vec3 leapPast(const BodyFrame *f, Foot *foot, Vec3 aim, Vec3 other, float reach, float s); @@ -748,20 +748,26 @@ static void updateExpression(Body *b, const BodyFrame *f, float speed) { b->fidget_time = fmaxf(0.0f, b->fidget_time - dt); if (!at_ease && (b->fidget_fade -= dt / FIDGET_FADE) <= 0.0f) b->fidget_time = 0.0f; /* (fades out from where it is) */ if ((b->fidget_timer -= dt) <= 0.0f && b->fidget_time <= 0.0f) { - b->fidget_timer = (3.0f + 8.0f * random01(b)) * (1.0f - 0.45f * b->shown.nerves); + /* (out of breath: soon after stopping, one after the other - catching it) */ + const float puffed = smoothstepf(0.35f, 0.75f, b->exertion); + b->fidget_timer = (3.0f + 8.0f * random01(b)) * (1.0f - 0.45f * b->shown.nerves) * (1.0f - 0.75f * puffed); if (at_ease && b->gesture_time <= 0.0f) { const float nerves = b->shown.nerves, tired = fmaxf(-b->shown.energy, 0.0f), proud = proudness(b); + const float fit = b->fitness; const float weight[FIDGET_COUNT] = { [FIDGET_SHAKE_LEG] = 0.8f + 1.5f * nerves, [FIDGET_ROCK] = 0.7f + 0.8f * nerves - 0.4f * tired, - [FIDGET_STRETCH] = 0.4f + 1.6f * tired + 0.8f * b->exertion, - [FIDGET_SHOULDERS] = 0.6f + 0.6f * b->exertion, + [FIDGET_STRETCH] = 0.4f + 1.6f * tired + 1.2f * puffed * fit, + [FIDGET_SHOULDERS] = 0.6f + 0.3f * puffed, [FIDGET_NECK] = 0.6f + 0.8f * tired, [FIDGET_CROSS_ARMS] = 0.5f + 1.5f * proud - 0.3f * shyness(b), [FIDGET_TAP_FOOT] = 0.3f + 2.0f * nerves, [FIDGET_RUB_HANDS] = 0.2f + 1.2f * nerves, [FIDGET_HEAD_BEHIND] = 0.2f + 0.6f * proud + 0.5f * fmaxf(b->shown.energy, 0.0f) - 0.3f * shyness(b), - [FIDGET_AKIMBO] = 0.3f + 1.4f * proud - 0.3f * shyness(b), + [FIDGET_AKIMBO] = 0.3f + 1.4f * proud - 0.3f * shyness(b) + 2.0f * puffed, + /* catching breath, by who they are: the unfit bent over, the sporty hands on the head */ + [FIDGET_KNEES] = 4.0f * puffed * (1.15f - fit) - 1.0f * proud, + [FIDGET_ON_HEAD] = 3.5f * puffed * (0.2f + fit), }; float total = 0.0f; for (int k = 1; k < FIDGET_COUNT; k++) total += fmaxf(weight[k], 0.0f); diff --git a/entropie/src/people/body.h b/entropie/src/people/body.h index 0744e53..70d3311 100644 --- a/entropie/src/people/body.h +++ b/entropie/src/people/body.h @@ -96,6 +96,7 @@ typedef struct { float teeter, teeter_v; /* -1 .. 1 tipping to the left / right (past 1: a step off) */ bool stepped_off; /* lost the balance just now (the world says so; taken) */ float exertion; /* 0 = fresh .. 1 = exhausted: heavy breathing */ + float breath_phase; /* where in a breath (radians, runs at the breathing rate) */ float chin_goal; /* head tipped back (radians), e.g. drinking */ float urge; /* 0..1: wants to move on (gets up faster after a fall) */ float disgust; /* 0..1: something stinks (face scrunches up); eases off by itself */ diff --git a/entropie/src/people/body_internal.h b/entropie/src/people/body_internal.h index 8876e06..fc3668f 100644 --- a/entropie/src/people/body_internal.h +++ b/entropie/src/people/body_internal.h @@ -133,6 +133,8 @@ enum { FIDGET_RUB_HANDS, /* rubbing the hands together (nervous) */ FIDGET_HEAD_BEHIND, /* hands clasped behind the head, elbows out (at ease, proud) */ FIDGET_AKIMBO, /* both hands on the hips (proud) */ + FIDGET_KNEES, /* out of breath: bent over, hands on the knees (the unfit) */ + FIDGET_ON_HEAD, /* out of breath: hands on top of the head, chest open (the sporty) */ FIDGET_COUNT }; #define FIDGET_FADE 0.35f @@ -263,6 +265,15 @@ static inline float fidgetWeight(const Body *b, int kind) { * smoothstepf(0.0f, 1.0f, b->fidget_fade); } +/* Out of breath, bent over with the hands on the knees (eased in and out slower than a fidget). */ +static inline float catchingBreath(const Body *b) { + if (b->fidget != FIDGET_KNEES || b->fidget_time <= 0.0f) return 0.0f; + return smoothstepf(0.0f, 0.9f, b->fidget_time) * smoothstepf(0.0f, 0.9f, b->fidget_len - b->fidget_time) * smoothstepf(0.0f, 1.0f, b->fidget_fade); +} + +/* Bent over: being sick, or catching breath. */ +static inline float bentDown(const Body *b) { return fmaxf(bentOver(b), 0.85f * catchingBreath(b)); } + static inline float fidgetPhase(const Body *b) { return b->fidget_len > 0.0f ? 1.0f - b->fidget_time / b->fidget_len : 0.0f; } diff --git a/entropie/src/people/body_pose.c b/entropie/src/people/body_pose.c index 5dd5725..4b411ca 100644 --- a/entropie/src/people/body_pose.c +++ b/entropie/src/people/body_pose.c @@ -404,8 +404,10 @@ static void solveStanding(Body *b, Vec3 position, Vec3 facing, float s, float dt Vec3 *j = out->joints; const float shy = shyness(b), proud = proudness(b), tired = fmaxf(-b->shown.energy, 0.0f); const float u = b->unsteadiness; - const float breath = sinf(b->clock * (1.5f + 0.6f * b->shown.nerves + 3.0f * b->exertion)) - * (b->asleep ? 1.6f : 1.0f) * (1.0f + 1.5f * b->exertion); + /* (the rate changes with how puffed they are: the phase runs at it - sin(clock x rate) + raced through whole breaths whenever the rate changed: the shoulders twitched) */ + b->breath_phase = fmodf(b->breath_phase + dt * (1.5f + 0.6f * b->shown.nerves + 3.0f * b->exertion), 2.0f * PI_F); + const float breath = sinf(b->breath_phase) * (b->asleep ? 1.6f : 1.0f) * (1.0f + 1.5f * b->exertion); /* Feet in figure space (unscaled) */ Vec3 ankle[2], toe[2]; @@ -458,7 +460,7 @@ static void solveStanding(Body *b, Vec3 position, Vec3 facing, float s, float dt } const float reach_y = goal_y; /* (as high as the standing legs reach) */ goal_y -= b->crouch * 0.42f; - goal_y -= 0.010f + 0.022f * fminf(speed / 3.0f, 1.0f) + 0.03f * u + 0.012f * tired + 0.12f * bentOver(b); + goal_y -= 0.010f + 0.022f * fminf(speed / 3.0f, 1.0f) + 0.03f * u + 0.012f * tired + 0.12f * bentDown(b); { /* Walking: up over the standing leg in the middle of each step, down as the other foot lands */ float walk = smoothstepf(0.25f, 0.9f, speed) * (1.0f - smoothstepf(BOB_FROM, BOB_FULL, speed)) * (b->airborne ? 0.0f : 1.0f); float swing = 0.0f; @@ -506,9 +508,9 @@ static void solveStanding(Body *b, Vec3 position, Vec3 facing, float s, float dt float pitch = b->lean * 0.3f + b->crouch * 0.55f + fminf(speed * 0.035f, 0.22f) + 0.1f * runAmount(speed) - 0.06f * proud + 0.12f * shy + 0.09f * tired + 0.08f * u - 0.08f * burpIn(b) - + 1.0f * bentOver(b) + 0.1f * heaving(b) * sinf(b->clock * 20.0f) + + 1.0f * bentDown(b) + 0.1f * heaving(b) * sinf(b->clock * 20.0f) + clampf(b->grade * 0.35f, -0.1f, 0.2f) /* leaning into a climb */ - + drift_z * 1.5f - 0.14f * stretch + 0.05f * rock; + + drift_z * 1.5f - 0.14f * stretch + 0.05f * rock - 0.08f * fidgetWeight(b, FIDGET_ON_HEAD); /* Stepping over something: leaning forward into it, the lifted foot reaches further */ for (int i = 0; i < 2; i++) if (b->feet[i].stepping && b->feet[i].over > 0.0f) @@ -609,9 +611,9 @@ static void solveStanding(Body *b, Vec3 position, Vec3 facing, float s, float dt yaw_goal += clampf(b->turn_rate * 0.3f, -0.5f, 0.5f); yaw_goal += SWING_HEAD * swing_yaw; /* (with the swing, a little: the eyes stay on the work) */ /* The head stays fairly level while the back leans, except when bent over being sick */ - float level = 0.4f * (pitch - 1.0f * bentOver(b)); + float level = 0.4f * (pitch - 1.0f * bentDown(b)); pitch_goal += 0.12f * proud - 0.28f * shy - 0.1f * tired - 0.15f * u - level + b->chin - + 0.25f * burpIn(b) - 0.12f * burpOut(b) - 0.5f * bentOver(b) - 0.35f * peeing(b); + + 0.25f * burpIn(b) - 0.12f * burpOut(b) - 0.5f * bentDown(b) - 0.35f * peeing(b); for (int i = 0; i < 2; i++) if (b->feet[i].stepping) pitch_goal -= 0.025f * sinf(2.0f * PI_F * b->feet[i].step); /* nod with the steps */ float neck = fidgetWeight(b, FIDGET_NECK); /* stretching the neck: over to one side, then the other */ @@ -719,7 +721,7 @@ static void solveStanding(Body *b, Vec3 position, Vec3 facing, float s, float dt arm.pole = vec3_normalize(arm.pole); /* Idle habits, hands on the knees while being sick, at the belt while peeing */ - float bent = bentOver(b), pee = peeing(b); + float bent = bentDown(b), pee = peeing(b); float gesturing = fmaxf(gestureWeight(b, 0), gestureWeight(b, 1)); float habit = fmaxf(fmaxf(clasp, behind) * (1.0f - gesturing), fmaxf(bent, pee)) * (1.0f - b->hand_weight[side]); if (habit > 0.001f) { @@ -777,6 +779,9 @@ static void solveStanding(Body *b, Vec3 position, Vec3 facing, float s, float dt float behind_head = fidgetWeight(b, FIDGET_HEAD_BEHIND); if (behind_head > 0.001f) blendArm(&arm, vec3_add(j[JOINT_HEAD], vec3(sign * 0.05f, 0.02f, -0.11f)), vec3(sign, 0.5f, -0.1f), behind_head); + float on_head = fidgetWeight(b, FIDGET_ON_HEAD); + if (on_head > 0.001f) /* (fingers laced on top of the head, elbows out and up) */ + blendArm(&arm, vec3_add(j[JOINT_HEAD], vec3(sign * 0.035f, 0.13f, 0.0f)), vec3(sign, 0.7f, 0.1f), on_head); float akimbo = fidgetWeight(b, FIDGET_AKIMBO); if (akimbo > 0.001f) blendArm(&arm, vec3_add(j[JOINT_PELVIS], vec3(sign * 0.19f, 0.03f, -0.01f)), vec3(sign, 0.0f, -0.6f), akimbo);