From ba78c98a747ab0029afbbc2e9e39f636a92de068 Mon Sep 17 00:00:00 2001 From: Schluffe Date: Wed, 25 Mar 2026 21:59:04 +0100 Subject: [PATCH] Add moveAndSlide --- engine/system/physics.ts | 40 +++++++++++++++++++++++++++--------- game/entities/hero/entity.ts | 17 ++++++--------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/engine/system/physics.ts b/engine/system/physics.ts index 624378e..69edbaa 100644 --- a/engine/system/physics.ts +++ b/engine/system/physics.ts @@ -2,7 +2,14 @@ import type { Circle } from "#/engine/Circle.ts"; import type { Polygon } from "#/engine/Polygon.ts"; import { createRect, fillRect, type Rect, strokeRect } from "#/engine/Rect.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"; export enum Shape { @@ -41,9 +48,6 @@ export type Collider = { export type Collision = { cid: string; normal: Vector; - position: Vector; - depth: number; - angle: number; time: number; }; @@ -149,9 +153,15 @@ function collideWithRect( other: Collider, ) { collision.cid = cid; - const inflX = other.aabb.position.x - self.aabb.width; - const inflY = other.aabb.position.y - self.aabb.height; - collision.depth = getDistance(createVector(inflX, inflY), self.aabb.position); + const x = self.aabb.position.x - other.aabb.position.x; + const y = self.aabb.position.y - other.aabb.position.y; + 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( @@ -209,9 +219,6 @@ function createCollision(): Collision { return { cid: "", normal: createVector(), - position: createVector(), - depth: 0, - angle: 0, time: 0, }; } @@ -268,3 +275,16 @@ export function moveAndCollide( 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; + } +} diff --git a/game/entities/hero/entity.ts b/game/entities/hero/entity.ts index dd402c1..d38b781 100644 --- a/game/entities/hero/entity.ts +++ b/game/entities/hero/entity.ts @@ -14,10 +14,12 @@ import { type Collision, createCollider, moveAndCollide, + moveAndSlide, Shape, } from "#/engine/system/physics.ts"; import { createVector, + getDotProduct, normalize, scale, type Vector, @@ -55,24 +57,17 @@ process((id, delta) => { velocity.x += keyboardInput.arrowRight ? 1 : 0; velocity.y -= keyboardInput.arrowUp ? 1 : 0; velocity.y += keyboardInput.arrowDown ? 1 : 0; + normalize(velocity); scale(velocity, speed); + moveAndSlide(id, velocity, delta); - let cScale = 1; - const collisions = moveAndCollide(id, velocity, 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; + position.x += velocity.x * delta; + position.y += velocity.y * delta; velocity.x = 0; velocity.y = 0; fillRect(viewport.ctx, collider.aabb, "orange"); strokeRect(viewport.ctx, collider.aabb, "red"); - if (collisions.some((c: Collision) => c.cid.length > 0)) { - fillRect(viewport.ctx, collider.aabb, "red"); - } });