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 { Polygon } from "#/engine/Polygon.ts";
import type { Rect } from "#/engine/Rect.ts"; import type { Rect } from "#/engine/Rect.ts";
import $ from "#/engine/Scene.ts"; import $ from "#/engine/Scene.ts";
import { import { createVector, invScale, type Vector, ZERO } from "#/engine/Vector.ts";
createVector,
getDotProduct,
invScale,
scale,
type Vector,
} from "#/engine/Vector.ts";
export enum Shape { export enum Shape {
Circle, Circle,
@@ -418,6 +412,7 @@ function createCollision(): Collision {
}; };
} }
const relVelocity = createVector();
export function moveAndCollide( export function moveAndCollide(
id: string, id: string,
velocity: Vector, velocity: Vector,
@@ -425,6 +420,7 @@ export function moveAndCollide(
): Array<Collision> { ): Array<Collision> {
const colliders = $<Collider>("collider")!; const colliders = $<Collider>("collider")!;
const positions = $<Vector>("position")!; const positions = $<Vector>("position")!;
const velocities = $<Vector>("velocity");
const selfColl = colliders.get(id)!.value; const selfColl = colliders.get(id)!.value;
const selfPos = positions.get(id)!.value; const selfPos = positions.get(id)!.value;
@@ -438,13 +434,22 @@ export function moveAndCollide(
const otherColl = collider.value; const otherColl = collider.value;
const otherPos = positions.get(cid)!.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 collision = next(selfColl.buffer);
const tHit = sweptAABB( const tHit = sweptAABB(
collision, collision,
selfColl, selfColl,
selfPos, selfPos,
velocity, relVelocity,
otherColl, otherColl,
otherPos, otherPos,
delta, delta,
@@ -462,7 +467,7 @@ export function moveAndCollide(
collision, collision,
selfColl, selfColl,
selfPos, selfPos,
velocity, relVelocity,
otherColl, otherColl,
otherPos, otherPos,
delta, delta,
@@ -474,7 +479,7 @@ export function moveAndCollide(
collision, collision,
selfColl, selfColl,
selfPos, selfPos,
velocity, relVelocity,
otherColl, otherColl,
otherPos, otherPos,
delta, delta,
@@ -486,7 +491,7 @@ export function moveAndCollide(
collision, collision,
selfColl, selfColl,
selfPos, selfPos,
velocity, relVelocity,
otherColl, otherColl,
otherPos, otherPos,
delta, delta,
@@ -510,6 +515,7 @@ export function moveAndSlide(
): void { ): void {
let timeLeft = 1; let timeLeft = 1;
const position = $<Vector>("position").get(id)!.value; const position = $<Vector>("position").get(id)!.value;
const velocities = $<Vector>("velocity");
let i = 0; let i = 0;
while (i++ < 4 && timeLeft > 0) { while (i++ < 4 && timeLeft > 0) {
@@ -530,19 +536,18 @@ export function moveAndSlide(
} }
const time = closest.time; 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; const scalar = Math.max(0, time - EPSILON) * deltaLeft;
position.x += velocity.x * scalar; position.x += velocity.x * scalar;
position.y += velocity.y * 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; timeLeft *= 1 - time;
} }
} }
+3 -3
View File
@@ -72,7 +72,7 @@ const process = defineEntity<{
stuff: 1, stuff: 1,
}); });
process((id, _delta) => { process((id, delta) => {
const position = $<Vector>("position").get(id)!.value; const position = $<Vector>("position").get(id)!.value;
const velocity = $<Vector>("velocity").get(id)!.value; const velocity = $<Vector>("velocity").get(id)!.value;
const collider = $<Collider>("collider").get(id)!.value; const collider = $<Collider>("collider").get(id)!.value;
@@ -80,8 +80,8 @@ process((id, _delta) => {
const sprite = $<Sprite>("sprite").get(id)!; const sprite = $<Sprite>("sprite").get(id)!;
const animation = $<SpriteAnimation>("animation").get(id)!; const animation = $<SpriteAnimation>("animation").get(id)!;
velocity.x = stuff.value * 0.5; velocity.x = stuff.value * 0.05;
position.x += velocity.x; position.x += velocity.x * delta;
if (position.x + collider.offset.x > viewport.canvas.width - 16) { if (position.x + collider.offset.x > viewport.canvas.width - 16) {
stuff.value = -1; stuff.value = -1;