Add moveAndSlide

This commit is contained in:
Schluffe
2026-03-25 21:59:04 +01:00
parent d08afa5d4a
commit ba78c98a74
2 changed files with 36 additions and 21 deletions
+30 -10
View File
@@ -2,7 +2,14 @@ import type { Circle } from "#/engine/Circle.ts";
import type { Polygon } from "#/engine/Polygon.ts"; import type { Polygon } from "#/engine/Polygon.ts";
import { createRect, fillRect, type Rect, strokeRect } from "#/engine/Rect.ts"; import { createRect, fillRect, type Rect, strokeRect } from "#/engine/Rect.ts";
import $ from "#/engine/Scene.ts"; import $ from "#/engine/Scene.ts";
import { createVector, getDistance, type Vector } from "#/engine/Vector.ts"; import {
createVector,
getDistance,
getDotProduct,
invScale,
setUnitNormal,
type Vector,
} from "#/engine/Vector.ts";
import { viewport } from "#/engine/Viewport.ts"; import { viewport } from "#/engine/Viewport.ts";
export enum Shape { export enum Shape {
@@ -41,9 +48,6 @@ export type Collider = {
export type Collision = { export type Collision = {
cid: string; cid: string;
normal: Vector; normal: Vector;
position: Vector;
depth: number;
angle: number;
time: number; time: number;
}; };
@@ -149,9 +153,15 @@ function collideWithRect(
other: Collider, other: Collider,
) { ) {
collision.cid = cid; collision.cid = cid;
const inflX = other.aabb.position.x - self.aabb.width; const x = self.aabb.position.x - other.aabb.position.x;
const inflY = other.aabb.position.y - self.aabb.height; const y = self.aabb.position.y - other.aabb.position.y;
collision.depth = getDistance(createVector(inflX, inflY), self.aabb.position); if (Math.abs(x) > Math.abs(y)) {
collision.normal.y = 0;
collision.normal.x = x > 0 ? 1 : -1;
} else {
collision.normal.x = 0;
collision.normal.y = y > 0 ? 1 : -1;
}
} }
function collideWithPolygon( function collideWithPolygon(
@@ -209,9 +219,6 @@ function createCollision(): Collision {
return { return {
cid: "", cid: "",
normal: createVector(), normal: createVector(),
position: createVector(),
depth: 0,
angle: 0,
time: 0, time: 0,
}; };
} }
@@ -268,3 +275,16 @@ export function moveAndCollide(
return slice; return slice;
} }
export function moveAndSlide(
id: string,
velocity: Vector,
delta: number,
): void {
const collisions = moveAndCollide(id, velocity, delta);
for (const collision of collisions) {
const dot = getDotProduct(velocity, collision.normal);
velocity.x -= collision.normal.x * dot;
velocity.y -= collision.normal.y * dot;
}
}
+6 -11
View File
@@ -14,10 +14,12 @@ import {
type Collision, type Collision,
createCollider, createCollider,
moveAndCollide, moveAndCollide,
moveAndSlide,
Shape, Shape,
} from "#/engine/system/physics.ts"; } from "#/engine/system/physics.ts";
import { import {
createVector, createVector,
getDotProduct,
normalize, normalize,
scale, scale,
type Vector, type Vector,
@@ -55,24 +57,17 @@ process((id, delta) => {
velocity.x += keyboardInput.arrowRight ? 1 : 0; velocity.x += keyboardInput.arrowRight ? 1 : 0;
velocity.y -= keyboardInput.arrowUp ? 1 : 0; velocity.y -= keyboardInput.arrowUp ? 1 : 0;
velocity.y += keyboardInput.arrowDown ? 1 : 0; velocity.y += keyboardInput.arrowDown ? 1 : 0;
normalize(velocity); normalize(velocity);
scale(velocity, speed); scale(velocity, speed);
moveAndSlide(id, velocity, delta);
let cScale = 1; position.x += velocity.x * delta;
const collisions = moveAndCollide(id, velocity, delta); position.y += velocity.y * delta;
for (const collision of collisions) {
cScale = Math.min(0, collision.time - 0.001);
}
position.x += velocity.x * delta * cScale;
position.y += velocity.y * delta * cScale;
velocity.x = 0; velocity.x = 0;
velocity.y = 0; velocity.y = 0;
fillRect(viewport.ctx, collider.aabb, "orange"); fillRect(viewport.ctx, collider.aabb, "orange");
strokeRect(viewport.ctx, collider.aabb, "red"); strokeRect(viewport.ctx, collider.aabb, "red");
if (collisions.some((c: Collision) => c.cid.length > 0)) {
fillRect(viewport.ctx, collider.aabb, "red");
}
}); });