Nimbin2git.christianimmanuel.de / Games / strichmaennchen / commits / 5a94d7c

strichmaennchen git · main

git clone https://git.christianimmanuel.de/games/strichmaennchen.gitwget https://git.christianimmanuel.de/games/strichmaennchen/archive/strichmaennchen.tar.gz

we now have push strength

Christian Immanuel · 2025-10-05 10:23 · 5a94d7c947fa54cceb051a3461a1d5c68f32a3ff

 game.c   |   8 +--
 object.c | 168 +++++++++++++++++++++++++++++++--------------------------------
 object.h |   4 +-
 3 files changed, 88 insertions(+), 92 deletions(-)

diff --git a/game.c b/game.c
index 4c6aca6..843275b 100644
--- a/game.c
+++ b/game.c
@@ -19,7 +19,7 @@ bool Game_init(Game* game) {
     Human  *player     = Human_create(vec3(1,4,0), CUBE_VERTICES_MODERN, vec3(0.5f,1.6f,0.25f), true, 60);
     player->isPlayer   = true;
     Human  *human      = Human_create(vec3(0,4,0), CUBE_VERTICES_MODERN, vec3(0.5f,1.6f,0.25f), false, 60);
-    Human  *human_1    = Human_create(vec3(-1,2,1), CUBE_VERTICES_MODERN, vec3(0.5f,1.6f,0.25f), false, 60);
+    Human  *human_1    = Human_create(vec3(0,2,0), CUBE_VERTICES_MODERN, vec3(0.5f,1.6f,0.25f), false, 60);
 
     Object* ground     = Object_create(OBJ_GROUND, CUBE_VERTICES_GROUND, vec3(0,-1,0), vec3(130, 1, 130), 0);
     Object* ground_1   = Object_create(OBJ_GROUND, CUBE_VERTICES_WARM, vec3(-8,0,1), vec3(1, 1, 1), 20);
@@ -36,7 +36,7 @@ bool Game_init(Game* game) {
     World_addObject(&game->world, tree);
 
 
-    Object* cylinder   = Object_create(OBJ_CYLINDER,   CUBE_VERTICES_WARM,   vec3(-3,0,1), vec3(1,3,1), 100);
+    Object* cylinder   = Object_create(OBJ_CYLINDER,   CUBE_VERTICES_WARM,   vec3(-3,0,1), vec3(1,3,1), 1000);
     Object_setRotation(cylinder, (Vec3){DEG2RAD(90), 0, 0});
 
     Object* cylinder_1 = Object_create(OBJ_CYLINDER,   CUBE_VERTICES_MODERN, vec3(-3,0,3), vec3(1,3,1), 100);
@@ -44,7 +44,7 @@ bool Game_init(Game* game) {
     World_addObject(&game->world, cylinder_1);
 
 
-    Object* cube        = Object_create(OBJ_CUBE,     CUBE_VERTICES_MODERN, vec3(2,2,8), vec3(1,3,1), 20);
+    Object* cube        = Object_create(OBJ_CUBE,     CUBE_VERTICES_MODERN, vec3(2,2,8), vec3(1,3,1), 100);
     Object_setRotation(cube, (Vec3){DEG2RAD(90), 0, 0});
     Object* cuber       = Object_create(OBJ_CUBE, CUBE_VERTICES_MODERN, vec3(1,0,2), vec3(2,1,2), 20);
     World_addObject(&game->world, cube);
@@ -92,7 +92,7 @@ bool Game_init(Game* game) {
     Object_setRotation(house_main, (Vec3){0, DEG2RAD(180), 0});
     World_addObject(&game->world, house_main);
 
-    Object* house_main_1 = Object_create(OBJ_HOUSE_MAIN,   CUBE_VERTICES_WARM,   vec3(-5,0,23), vec3(12.0f,11.0f,18.0f), 20);
+    Object* house_main_1 = Object_create(OBJ_HOUSE_MAIN,   CUBE_VERTICES_WARM,   vec3(-5,0,23), vec3(18.0f,11.0f,12.0f), 20);
     Object_setRotation(house_main_1, (Vec3){0, DEG2RAD(90), 0});
     World_addObject(&game->world, house_main_1);
 
diff --git a/object.c b/object.c
index 57c1f97..b69c833 100644
--- a/object.c
+++ b/object.c
@@ -16,6 +16,7 @@ Object *Object_create(ObjectType type, VertexPreset vertex, Vec3 position, Vec3
     obj->type     = type;
     obj->position = position;
     obj->weight   = weight;
+    obj->strength = 100;
 
     obj->vertex   = vertex;
     obj->rotation = (Vec3){0,0,0};
@@ -71,24 +72,18 @@ Object *Object_create(ObjectType type, VertexPreset vertex, Vec3 position, Vec3
         case OBJ_TREE:
             obj->mesh = Mesh_createTree(3.0f, 0.3f, 8, 1.5f);
 			obj->collider.isStatic = true;
-            obj->position_center = (Vec3){0, obj->collider.half_extents.y, 0};
             obj->position.y = -size.y/2.0f;
-            obj->collider.position = obj->position_center;
-            return obj;
+            break;
         case OBJ_HOUSE_MAIN:
             obj->mesh = Mesh_createHouse();
             obj->collider.isStatic = true;
-            obj->position_center = (Vec3){0, obj->collider.half_extents.y, 0};
             obj->position.y = -size.y/2.0f;
-            obj->collider.position = obj->position_center;
-            return obj;
+            break;
         case OBJ_BARN:
             obj->mesh = Mesh_createBarn();
             obj->collider.isStatic = true;
-            obj->position_center = (Vec3){0, obj->collider.half_extents.y, 0};
             obj->position.y = -size.y/2.0f;
-            obj->collider.position = obj->position_center;
-            return obj;
+            break;
 
         default:
             obj->mesh = mesh_default;
@@ -235,6 +230,7 @@ void Collider_positionGround(Object* obj, Object* ground) {
 
     // penetration = distance we need to move obj down to sit on top
     float penetration = (distAlongUp - (groundHalf + objHalf));
+    if (penetration > 1.0f) penetration = 1.0f;
 
     // Only snap if penetrating (obj is above ground)
     if (penetration < 0) {
@@ -254,6 +250,21 @@ void Collider_positionGround(Object* obj, Object* ground) {
     }
 }
 
+static float calc_PushFactor(int obj_weight, int obj_strength, int other_weight) {
+    if (obj_strength <= 0 || obj_weight <= 0)
+        return 0.0f;
+
+    float max_weight = obj_weight * (obj_strength / 50.0f);
+
+    if (other_weight <= 0)
+        return 1.0f;
+    if (other_weight >= max_weight)
+        return 0.0f;
+
+    return 1.0f - (other_weight / max_weight);
+}
+
+
 void Object_resolveDynamicCollision(Object *obj, Object *other) {
     if (obj->collider.isStatic && other->collider.isStatic) return;
 
@@ -265,87 +276,94 @@ void Object_resolveDynamicCollision(Object *obj, Object *other) {
     // Ensure MTV points from obj -> other
     Vec3 dir = vec3_sub(colliderCenterWorld(other), colliderCenterWorld(obj));
     if (vec3_dot(dir, mtv_axis) < 0) mtv_axis = vec3_scale(mtv_axis, -1.0f);
+    mtv_axis = vec3_normalize(mtv_axis);
 
-    // Determine whether the collision is mainly vertical (landing)
     const Vec3 world_up = {0,1,0};
-    float verticalAlignment = fabsf(vec3_dot(mtv_axis, world_up)); // 1.0 == straight up/down
+    float verticalAlignment = fabsf(vec3_dot(mtv_axis, world_up));
 
-    // compute base push factors
-    float totalWeight = obj->weight + other->weight;
-    float pushFactorObj   = other->collider.isStatic ? 1.0f : other->weight / totalWeight;
-    float pushFactorOther = obj->collider.isStatic ? 1.0f : obj->weight / totalWeight;
-
-    // --- Special handling for mostly-vertical collisions (landings) ---
+    // --- Handle vertical collisions ---
     if (verticalAlignment > 0.70f) {
-        // If other is static, snap obj to it and stop vertical movement
         if (other->collider.isStatic) {
-            // Use your ground snap routine which uses OBB math
-            Collider_positionGround(obj, other);
-            // ensure no vertical impulse
-            obj->velocity.y = 0.0f;
-            obj->is_grounded = true;
-            // do not apply horizontal impulse if tiny
-            return; // already resolved vertical landing; optional: still apply horizontal push below if wanted
+            float dotUp = vec3_dot(mtv_axis, world_up);
+            if (dotUp < 0.0f) {
+                Collider_positionGround(obj, other);
+                obj->velocity.y = 0.0f;
+                obj->is_grounded = true;
+                return;
+            } else {
+                if (obj->velocity.y > 0.0f) obj->velocity.y = 0.0f;
+                return;
+            }
         } else {
-            // Both dynamic:
-            // Prefer moving the incoming (obj) up rather than pushing other downward into the ground.
-            // Make obj take most of the separation.
-            pushFactorObj   = 1.0f;
-            pushFactorOther = 0.0f;
-
-            // Stop vertical velocity of obj so it doesn't bounce
             obj->velocity.y = 0.0f;
             obj->is_grounded = true;
-            // We will continue to apply horizontal impulse and torque below.
         }
     }
 
-    // --- 1. Separate objects along MTV (respect push factors) ---
-    if (!obj->collider.isStatic)
-        obj->position = vec3_sub(obj->position, vec3_scale(mtv_axis, penetration * pushFactorObj));
-    if (!other->collider.isStatic)
-        other->position = vec3_add(other->position, vec3_scale(mtv_axis, penetration * pushFactorOther));
+    // --- 1. Separate objects along MTV ---
+    const float MAX_CORRECTION = 0.5f;
+    if (penetration > MAX_CORRECTION) penetration = MAX_CORRECTION;
 
-    // After separation: avoid leaving 'other' intersecting the ground.
-    // If other moved and could be intersecting a static collider below it, optionally fix it:
-    // (simple protective clamp) — compute other's bottom world Y and ensure it isn't below any static ground
-    // (You may implement a broader world-ground-check later if needed.)
+    if (!other->collider.isStatic) {
+        float pushRatioObjToOther = calc_PushFactor(obj->weight, obj->strength, other->weight);
+        if (pushRatioObjToOther > 0.0f) {
+            Vec3 pushVec = vec3_scale(mtv_axis, penetration * pushRatioObjToOther);
+            other->position = vec3_add(other->position, pushVec);
+        } else {
+            obj->position = vec3_sub(obj->position, vec3_scale(mtv_axis, penetration));
+            obj->velocity = vec3_scale(obj->velocity, 0.2f);
+        }
+    } else if (!obj->collider.isStatic) {
+        obj->position = vec3_sub(obj->position, vec3_scale(mtv_axis, penetration));
+    }
 
-    // --- 2. Apply horizontal velocity impulses only ---
-    float pushStrength = 5.0f;
-    // horizontal component of MTV (world-space)
+    // --- 2. Apply horizontal linear velocity ---
     Vec3 horizontalAxis = (Vec3){ mtv_axis.x, 0.0f, mtv_axis.z };
     if (vec3_length(horizontalAxis) > 1e-6f)
         horizontalAxis = vec3_normalize(horizontalAxis);
     else
         horizontalAxis = (Vec3){0,0,0};
 
-    // Apply impulse only along horizontalAxis so we don't reintroduce vertical bounce
-    if (!obj->collider.isStatic)
-        obj->velocity = vec3_sub(obj->velocity, vec3_scale(horizontalAxis, pushStrength * pushFactorObj));
-    if (!other->collider.isStatic)
-        other->velocity = vec3_add(other->velocity, vec3_scale(horizontalAxis, pushStrength * pushFactorOther));
+    float pushStrength = 2.0f;
+    float pushRatioObjToOther = calc_PushFactor(obj->weight, obj->strength, other->weight);
 
-    // --- 3. Angular impulse using torque = r × F ---
-    Vec3 offset = vec3_sub(colliderCenterWorld(other), colliderCenterWorld(obj));
-    offset.y = 0.0f; // we only care about horizontal offset
+    if (!other->collider.isStatic && pushRatioObjToOther > 0.0f) {
+        Vec3 dv = vec3_scale(horizontalAxis, pushStrength * pushRatioObjToOther);
+        other->velocity = vec3_add(other->velocity, dv);
+    }
 
-    Vec3 impulse = vec3_scale(horizontalAxis, pushStrength); // collision push direction
+    if (!obj->collider.isStatic && pushRatioObjToOther > 0.0f) {
+        obj->velocity = vec3_sub(obj->velocity, vec3_scale(horizontalAxis, pushStrength * 0.2f * pushRatioObjToOther));
+    }
 
-    // Torque (around Y) = r.x * F.z - r.z * F.x
-    float torque = -(offset.x * impulse.z - offset.z * impulse.x);
+    // --- 3. Apply angular velocity with stronger torque ---
+    float angularPushFactor = 10.5f; // increase this for stronger spin
+    if (!other->collider.isStatic && vec3_length(horizontalAxis) > 1e-6f && pushRatioObjToOther > 0.0f) {
+        Vec3 offset = vec3_sub(colliderCenterWorld(obj), colliderCenterWorld(other));
+        offset.y = 0.0f;
+        Vec3 impulse = vec3_scale(horizontalAxis, pushStrength * pushRatioObjToOther);
+        float torque = (offset.x * impulse.z - offset.z * impulse.x) * angularPushFactor;
+        other->angular_velocity.y += torque / (other->weight > 0 ? other->weight : 1.0f);
+    }
+}
 
-    if (!obj->collider.isStatic)
-        obj->angular_velocity.y += torque / (obj->weight > 0 ? obj->weight : 1.0f);
 
-    // Now same for the other object (opposite offset, opposite force)
-    Vec3 offsetOther = vec3_scale(offset, -1.0f);
-    Vec3 impulseOther = vec3_scale(horizontalAxis, -pushStrength);
+void Object_applyFriction(Object *obj, float dt) {
+    if (obj->collider.isStatic) return;
+
+    // Base friction coefficient (tweak)
+    float frictionCoeff = 0.5f;
 
-    float otherTorque = -(offsetOther.x * impulseOther.z - offsetOther.z * impulseOther.x);
+    // Friction proportional to weight (mass)
+    float friction = frictionCoeff * fminf(obj->weight, 10.0f);
 
-    if (!other->collider.isStatic)
-        other->angular_velocity.y += otherTorque / (other->weight > 0 ? other->weight : 1.0f);
+    // Apply only to horizontal velocity (XZ)
+    obj->velocity.x -= obj->velocity.x * friction * dt;
+    obj->velocity.z -= obj->velocity.z * friction * dt;
+
+    // Stop very small velocities to prevent jitter
+    if (fabs(obj->velocity.x) < 0.01f) obj->velocity.x = 0;
+    if (fabs(obj->velocity.z) < 0.01f) obj->velocity.z = 0;
 }
 
 void Object_resolveCollisions(Object *obj, Object **worldObjects, int count) {
@@ -373,24 +391,6 @@ void Object_resolveCollisions(Object *obj, Object **worldObjects, int count) {
     }
 }
 
-void Object_applyFriction(Object *obj, float dt) {
-    if (obj->collider.isStatic) return;
-
-    // Base friction coefficient (tweak)
-    float frictionCoeff = 0.5f;
-
-    // Friction proportional to weight (mass)
-    float friction = frictionCoeff * obj->weight;
-
-    // Apply only to horizontal velocity (XZ)
-    obj->velocity.x -= obj->velocity.x * friction * dt;
-    obj->velocity.z -= obj->velocity.z * friction * dt;
-
-    // Stop very small velocities to prevent jitter
-    if (fabs(obj->velocity.x) < 0.01f) obj->velocity.x = 0;
-    if (fabs(obj->velocity.z) < 0.01f) obj->velocity.z = 0;
-}
-
 void Collider_update(Collider *c) {
     // Build rotation matrix from Euler angles
     Mat4 rot = mat4_identity();
@@ -450,7 +450,3 @@ void Object_update(Object *obj, Object **worldObjects, int count, float dt) {
     Object_applyFriction(obj, dt);
     obj->movement = (Vec3){0,0,0};
 }
-
-void Object_addMovement(Object *obj, Vec3 move) {
-    obj->velocity = vec3_add(obj->velocity, move);
-}
diff --git a/object.h b/object.h
index 1c032e8..f4467e5 100644
--- a/object.h
+++ b/object.h
@@ -46,7 +46,8 @@ typedef struct {
     Vec3 angular_velocity;
     Vec3 movement;
     bool is_grounded;
-    float weight;
+    int weight;
+    int strength;
 } Object;
 
 
@@ -61,7 +62,6 @@ void Object_rotate(Object *obj, Vec3 delta);
 void Object_applyGravity(Object *obj, float dt);
 void Object_resolveCollisions(Object *obj, Object **worldObjects, int count);
 void Object_update(Object *obj, Object **worldObjects, int count, float dt);
-void Object_addMovement(Object *obj, Vec3 move);
 void Object_setRotation(Object *obj, Vec3 rotation);
 void Object_rotate(Object *obj, Vec3 delta);
 #endif /* GAMEOBJECT_H */