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/people/hands.h raw
#ifndef PEOPLE_HANDS_H
#define PEOPLE_HANDS_H
/*
* What a character does with its hands: pick up and carry items (one per
* hand, or one big item with both), and grab objects to push or pull them.
* Works for any character; the player drives it from input.
*
* Rules
* one hand : up to ONE_HAND_MAX_WEIGHT kg and ONE_HAND_MAX_SIZE m
* two hands: up to TWO_HAND_MAX_WEIGHT kg and TWO_HAND_MAX_SIZE m, both hands free
* grab : any loose object; uses every free hand. Several characters can
* grab the same object and their strength adds up.
*
* Grabbed objects can be lifted by everyone holding them together and carried
* (Hands_toggleLift).
*
* While grabbing, the character faces the object along a fixed heading:
* forward pushes, backward pulls, sideways drags it along. Looking around
* does not move the object.
*/
#include <stdbool.h>
#include "math/linalg.h"
struct Object;
typedef enum {
HAND_FREE,
HAND_REACHING, /* bending down / reaching for an item */
HAND_HOLDING, /* carrying an item */
HAND_GRABBING, /* holding on to an object to push or pull it */
HAND_READY, /* reaching out in front (E / Q): takes hold of whatever comes in reach */
HAND_HOLD, /* holding on to something fixed (a post, a wall, a tree) or somebody (a body part): hold, hold_local */
} HandState;
typedef struct {
HandState state[2];
struct Object *item[2]; /* same item in both hands = carried with two hands */
float timer[2];
float item_yaw[2]; /* item rotation relative to the carrier */
struct Object *grabbed;
Vec3 grab_vector; /* object position minus own position (world, fixed) */
Vec3 grab_heading; /* direction we face while grabbing (horizontal) */
Vec3 grab_point[2]; /* hand contacts in object space (turn with the object) */
float grab_share; /* how much the object follows (0..1, whole team) */
float throw_time[2]; /* > 0: arm follows through after a throw */
bool overhand[2]; /* ... that was thrown overhand */
float wind; /* > 0: winding up for a throw (seconds held) */
bool winding; /* ... still held this frame */
bool touching; /* this frame: a hand reaches for touch_point */
Vec3 touch_point;
float rope; /* this frame: both hands on a rope at rope_at (0 none), leaning back into it this hard (0..1) */
Vec3 rope_at, rope_dir; /* ... the near hand's grip, the way the rope runs (to where it's tied) */
bool on_edge; /* this frame: both free hands hold on to an edge (climbing up) */
Vec3 edge_point, edge_across;
float edge_crouch;
int edge_lead; /* ... this hand gets there first ... */
float edge_trail; /* ... the other still this far behind (1: down by the shoulder, 0: on it too) ... */
float edge_turn; /* ... the shoulders turned this far, the first hand's side ahead (radians) */
float settle[2]; /* 0 -> 1 just after taking an item: it turns into the carry pose */
bool by_neck[2]; /* bottles: held at the neck (rare) instead of low around the body */
float miss_time; /* grabbing: seconds the hands couldn't reach their grip */
Vec3 settle_y[2]; /* item axes when it was taken (figure space) */
Vec3 settle_z[2];
int drink_hand; /* hand bringing a bottle to the mouth, -1 = none */
float drink_time;
bool drink_sipped;
struct Object *hold[2]; /* HAND_HOLD: what (or who) this hand holds on to ... */
Vec3 hold_local[2]; /* ... where on it (its own space; a person: unused) ... */
int hold_joint[2]; /* ... a person: the joint (Joint) held at, its part (people/touch.h) */
int hold_part[2];
} Hands;
/* E / Q: this hand reaches out in front and takes hold of whatever comes in reach - a thing to
carry, something heavy to push, something fixed to hold on to, somebody. Again: lets go. */
void Hands_reachOut(struct Object *who, int hand);
/* Lets go with this hand (whatever it holds on to, reaching out). */
void Hands_letGo(struct Object *who, int hand);
/* A hand reaching out: what's in reach of it now taken hold of. Returns what (or NULL); *person: it's somebody. */
struct Object *Hands_catch(struct Object *who, int hand, struct Object *const *objects, int count, bool *person);
/* Holding on to this one (a hand on them), or -1. */
int Hands_holding(const struct Object *who, const struct Object *whom);
/* Where a hand is held (world): the fixed point, or the person's joint now. */
Vec3 Hands_holdPoint(const struct Object *who, int hand);
/* Picks up the item in front with this hand (or both), or drops what it holds. */
bool Hands_pickUpOrDrop(struct Object *who, int hand, struct Object *const *objects, int count);
void Hands_drop(struct Object *who, int hand);
/* Puts whatever is in the hands down on the ground beside them (lets go of
what they hold on to): the hands are free, for a pee. out: what was put down. */
void Hands_setAside(struct Object *who, struct Object *out[2]);
/*
* Takes whatever is in front: small things with a free hand, bigger ones with
* both, and anything too heavy to carry is taken hold of (push, pull, or lift
* it together). Returns 1 picked up, 2 holding on to it, 0 nothing there,
* -1 hands full.
*/
int Hands_takeInFront(struct Object *who, struct Object *const *objects, int count);
/* The loose object in front within reach, or NULL. */
struct Object *Hands_inFront(const struct Object *who, struct Object *const *objects, int count);
/* The hand to use first: the main hand if it is free, else the other, -1 if both are busy. */
int Hands_freeHand(const struct Object *who);
/* Picks up a specific item if this hand is free and it is within reach (used by the AI). */
bool Hands_pickUpObject(struct Object *who, int hand, struct Object *item);
/* Takes an item handed over by someone (one hand, no reaching for it). */
bool Hands_receive(struct Object *who, int hand, struct Object *item);
/* Winding up to throw (call every frame while the key is held): a quick one
goes underhand, held longer the arm comes back over the shoulder for a
harder, further throw overhand. */
void Hands_windUp(struct Object *who);
bool Hands_isWindingUp(const struct Object *who);
/* Throws what the main (else the other) hand holds along dir, as wound up (not at all: a lob). */
bool Hands_throw(struct Object *who, Vec3 dir);
/*
* Team lifting: everybody holding the grabbed object lifts it off the ground
* if their strength together carries its weight (about 40 kg per person),
* and carries it where they walk. Again to put it down.
* A long log too heavy for them but not for half its weight: one end comes
* up, the other drags on the ground (slower).
* Returns 1 lifted, 2 one end lifted, 0 put down, -1 too heavy for the people
* holding it, -3 could lift one end but isn't held near one.
*/
int Hands_toggleLift(struct Object *who, struct Object *const *objects, int count);
/* This frame, reach out and touch a point (e.g. to wake someone). */
void Hands_touch(struct Object *who, Vec3 point);
/* This frame, the free hands hold on to an edge at point, a shoulder width apart along across. */
void Hands_holdEdge(struct Object *who, Vec3 point, Vec3 across, float crouch);
/* Grabs the object in front with all free hands. */
bool Hands_grab(struct Object *who, struct Object *const *objects, int count);
/* Grabs a specific object if it is within reach (used by the AI). */
bool Hands_grabObject(struct Object *who, struct Object *target);
void Hands_release(struct Object *who);
bool Hands_isGrabbing(const struct Object *who);
/* Turns what who holds on to (with everybody holding it) about its middle, towards
want radians (+: the way the heading angle grows), as fast as strength allows and
only as far as nothing solid is in the way. Returns the angle turned. */
float Hands_turnGrabbed(struct Object *who, struct Object *const *objects, int count, float want, float dt);
/* Takes a sip from a carried bottle, or a bite of carried food (right hand first). */
bool Hands_drink(struct Object *who);
bool Hands_isDrinking(const struct Object *who);
/* Hand holding a bottle or food with something left, or -1. */
int Hands_bottleHand(const struct Object *who);
/* Gap between a body standing at position and an object's surface (meters). */
float Hands_gapFrom(Vec3 position, float height, const struct Object *o);
/* Is an item of this type in the hands? */
bool Hands_carries(const struct Object *who, int type);
/* Walking speed multiplier while carrying or pushing. */
float Hands_moveFactor(const struct Object *who);
/* After physics: moves grabbed objects with everybody holding them (strength adds up). */
void Hands_solveGrabs(struct Object *const *objects, int count, float dt);
/* After physics: advances reaching and sets the body goals and hand targets. */
void Hands_update(struct Object *who, float dt);
/* After the skeleton is solved: moves carried items into the hands. */
void Hands_placeHeld(struct Object *who);
#endif /* PEOPLE_HANDS_H */