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 */