fix CCD (but introduce another issue >.<)

This commit is contained in:
Schluffe
2026-04-19 16:24:40 +02:00
parent 52e4aca941
commit 7a068060e1
2 changed files with 28 additions and 23 deletions
+25 -20
View File
@@ -2,13 +2,7 @@ import type { Circle } from "#/engine/Circle.ts";
import type { Polygon } from "#/engine/Polygon.ts";
import type { Rect } from "#/engine/Rect.ts";
import $ from "#/engine/Scene.ts";
import {
createVector,
getDotProduct,
invScale,
scale,
type Vector,
} from "#/engine/Vector.ts";
import { createVector, invScale, type Vector, ZERO } from "#/engine/Vector.ts";
export enum Shape {
Circle,
@@ -418,6 +412,7 @@ function createCollision(): Collision {
};
}
const relVelocity = createVector();
export function moveAndCollide(
id: string,
velocity: Vector,
@@ -425,6 +420,7 @@ export function moveAndCollide(
): Array<Collision> {
const colliders = $<Collider>("collider")!;
const positions = $<Vector>("position")!;
const velocities = $<Vector>("velocity");
const selfColl = colliders.get(id)!.value;
const selfPos = positions.get(id)!.value;
@@ -438,13 +434,22 @@ export function moveAndCollide(
const otherColl = collider.value;
const otherPos = positions.get(cid)!.value;
const otherVel = velocities?.get(cid)?.value ?? ZERO;
relVelocity.x = velocity.x - otherVel.x;
relVelocity.y = velocity.y - otherVel.y;
// no relative motion
if (relVelocity.x === 0 && relVelocity.y === 0) {
continue;
}
const collision = next(selfColl.buffer);
const tHit = sweptAABB(
collision,
selfColl,
selfPos,
velocity,
relVelocity,
otherColl,
otherPos,
delta,
@@ -462,7 +467,7 @@ export function moveAndCollide(
collision,
selfColl,
selfPos,
velocity,
relVelocity,
otherColl,
otherPos,
delta,
@@ -474,7 +479,7 @@ export function moveAndCollide(
collision,
selfColl,
selfPos,
velocity,
relVelocity,
otherColl,
otherPos,
delta,
@@ -486,7 +491,7 @@ export function moveAndCollide(
collision,
selfColl,
selfPos,
velocity,
relVelocity,
otherColl,
otherPos,
delta,
@@ -510,6 +515,7 @@ export function moveAndSlide(
): void {
let timeLeft = 1;
const position = $<Vector>("position").get(id)!.value;
const velocities = $<Vector>("velocity");
let i = 0;
while (i++ < 4 && timeLeft > 0) {
@@ -530,19 +536,18 @@ export function moveAndSlide(
}
const time = closest.time;
// if the collider overlap already
if (time === 0) {
break;
}
const dot = getDotProduct(velocity, closest.normal);
velocity.x -= closest.normal.x * dot;
velocity.y -= closest.normal.y * dot;
const scalar = Math.max(0, time - EPSILON) * deltaLeft;
position.x += velocity.x * scalar;
position.y += velocity.y * scalar;
// a stationary entity might not have a velocity compnent
const otherVel = velocities.get(closest.cid)?.value ?? ZERO;
const rvx = velocity.x - otherVel.x;
const rvy = velocity.y - otherVel.y;
const dot = rvx * closest.normal.x + rvy * closest.normal.y;
velocity.x -= closest.normal.x * dot;
velocity.y -= closest.normal.y * dot;
timeLeft *= 1 - time;
}
}