diff --git a/engine/system/physics.ts b/engine/system/physics.ts index f17d8bb..e0ee7e6 100644 --- a/engine/system/physics.ts +++ b/engine/system/physics.ts @@ -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 { const colliders = $("collider")!; const positions = $("position")!; + const velocities = $("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 = $("position").get(id)!.value; + const velocities = $("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; } } diff --git a/game/entities/testEntity/entity.ts b/game/entities/testEntity/entity.ts index 737cf47..a02da56 100644 --- a/game/entities/testEntity/entity.ts +++ b/game/entities/testEntity/entity.ts @@ -72,7 +72,7 @@ const process = defineEntity<{ stuff: 1, }); -process((id, _delta) => { +process((id, delta) => { const position = $("position").get(id)!.value; const velocity = $("velocity").get(id)!.value; const collider = $("collider").get(id)!.value; @@ -80,8 +80,8 @@ process((id, _delta) => { const sprite = $("sprite").get(id)!; const animation = $("animation").get(id)!; - velocity.x = stuff.value * 0.5; - position.x += velocity.x; + velocity.x = stuff.value * 0.05; + position.x += velocity.x * delta; if (position.x + collider.offset.x > viewport.canvas.width - 16) { stuff.value = -1;