WIP
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { copyVector, type Vector } from "#/engine/Vector.ts";
|
||||
|
||||
export type AABB = {
|
||||
position: Vector;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
export function createAABB(
|
||||
position: Vector,
|
||||
width: number,
|
||||
height: number,
|
||||
): AABB {
|
||||
return {
|
||||
position,
|
||||
width,
|
||||
height,
|
||||
};
|
||||
}
|
||||
|
||||
export function fromMinMax(min: Vector, max: Vector): AABB {
|
||||
return {
|
||||
position: copyVector(min),
|
||||
width: max.x - min.x,
|
||||
height: max.y - min.y,
|
||||
};
|
||||
}
|
||||
|
||||
export function drawAABB(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
aabb: AABB,
|
||||
color: string = "#fff",
|
||||
): void {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = color;
|
||||
ctx.strokeRect(
|
||||
Math.round(aabb.position.x) - 0.5,
|
||||
Math.round(aabb.position.y) - 0.5,
|
||||
aabb.width,
|
||||
aabb.height,
|
||||
);
|
||||
ctx.restore();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { Vector } from "#/engine/Vector.ts";
|
||||
|
||||
export type Circle = {
|
||||
position: Vector;
|
||||
radius: number;
|
||||
};
|
||||
|
||||
export function createCircle(position: Vector, radius: number): Circle {
|
||||
return {
|
||||
position,
|
||||
radius,
|
||||
};
|
||||
}
|
||||
|
||||
export function drawCircle(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
circle: Circle,
|
||||
color: string = "#fff",
|
||||
): void {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = color;
|
||||
ctx.beginPath();
|
||||
ctx.arc(circle.position.x, circle.position.y, circle.radius, 0, 2 * Math.PI);
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { Vector } from "#/engine/Vector.ts";
|
||||
|
||||
export type Polygon = {
|
||||
position: Vector;
|
||||
points: Array<Vector>;
|
||||
axes: Array<Vector>;
|
||||
};
|
||||
@@ -7,6 +7,13 @@ export function createVector(x: number = 0, y: number = 0): Vector {
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
export function copyVector(vector: Vector): Vector {
|
||||
return {
|
||||
x: vector.x,
|
||||
y: vector.y,
|
||||
};
|
||||
}
|
||||
|
||||
export function fromPolar(direction: number, magnitude: number): Vector {
|
||||
return {
|
||||
x: Math.cos(direction) * magnitude,
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import type { AABB } from "#/engine/AABB.ts";
|
||||
import type { Circle } from "#/engine/Circle.ts";
|
||||
import type { Vector } from "#/engine/Vector.ts";
|
||||
|
||||
export function isPointInCircle(point: Vector, circle: Circle): boolean {
|
||||
const dx = point.x - circle.position.x;
|
||||
const dy = point.y - circle.position.y;
|
||||
|
||||
return dx * dx + dy * dy <= circle.radius ** 2;
|
||||
}
|
||||
|
||||
export function isPointInAABB(point: Vector, aabb: AABB): boolean {
|
||||
const rx = aabb.position.x;
|
||||
const ry = aabb.position.y;
|
||||
|
||||
return (
|
||||
point.x >= rx &&
|
||||
point.x <= rx + aabb.width &&
|
||||
point.y >= ry &&
|
||||
point.y <= ry + aabb.height
|
||||
);
|
||||
}
|
||||
|
||||
export function circleIntersectCircle(a: Circle, b: Circle): boolean {
|
||||
const dx = a.position.x - b.position.x;
|
||||
const dy = a.position.y - b.position.y;
|
||||
|
||||
return dx * dx + dy * dy <= (a.radius + b.radius) ** 2;
|
||||
}
|
||||
|
||||
export function AABBIntersectAABB(a: AABB, b: AABB): boolean {
|
||||
const ax = a.position.x;
|
||||
const ay = a.position.y;
|
||||
const bx = b.position.x;
|
||||
const by = b.position.y;
|
||||
|
||||
return (
|
||||
ax <= bx + b.width &&
|
||||
ax + a.width >= bx &&
|
||||
ay <= by + b.height &&
|
||||
ay + a.height >= by
|
||||
);
|
||||
}
|
||||
|
||||
export function circleIntersectAABB(circle: Circle, aabb: AABB): boolean {
|
||||
const cx = circle.position.x;
|
||||
const cy = circle.position.y;
|
||||
const rx = aabb.position.x;
|
||||
const ry = aabb.position.y;
|
||||
|
||||
const dx = cx - Math.max(rx, Math.min(cx, rx + aabb.width));
|
||||
const dy = cy - Math.max(ry, Math.min(cy, ry + aabb.height));
|
||||
|
||||
return dx * dx + dy * dy <= circle.radius ** 2;
|
||||
}
|
||||
|
||||
export function circleContainsCircle(a: Circle, b: Circle): boolean {
|
||||
const dx = a.position.x - b.position.x;
|
||||
const dy = a.position.y - b.position.y;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
return a.radius >= b.radius + distance;
|
||||
}
|
||||
|
||||
export function AABBContainsAABB(a: AABB, b: AABB): boolean {
|
||||
const ax = a.position.x;
|
||||
const ay = a.position.y;
|
||||
const bx = b.position.x;
|
||||
const by = b.position.y;
|
||||
|
||||
return (
|
||||
ax <= bx &&
|
||||
ax + a.width >= bx + b.width &&
|
||||
ay <= by &&
|
||||
ay + a.height >= by + b.height
|
||||
);
|
||||
}
|
||||
|
||||
export function AABBContainsCircle(aabb: AABB, circle: Circle): boolean {
|
||||
const rx = aabb.position.x;
|
||||
const ry = aabb.position.y;
|
||||
const cx = circle.position.x;
|
||||
const cy = circle.position.y;
|
||||
|
||||
return (
|
||||
rx <= cx - circle.radius &&
|
||||
rx + aabb.width >= cx + circle.radius &&
|
||||
ry <= cy - circle.radius &&
|
||||
ry + aabb.height >= cy + circle.radius
|
||||
);
|
||||
}
|
||||
|
||||
export function circleContainsAABB(circle: Circle, aabb: AABB): boolean {
|
||||
const radiusSquare = circle.radius ** 2;
|
||||
|
||||
const dax = aabb.position.x - circle.position.x;
|
||||
const day = aabb.position.y - circle.position.y;
|
||||
if (dax * dax + day * day > radiusSquare) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dbx = aabb.position.x + aabb.width - circle.position.x;
|
||||
const dby = aabb.position.y - circle.position.y;
|
||||
if (dbx * dbx + dby * dby > radiusSquare) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dcx = aabb.position.x - circle.position.x;
|
||||
const dcy = aabb.position.y + aabb.height - circle.position.y;
|
||||
if (dcx * dcx + dcy * dcy > radiusSquare) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ddx = aabb.position.x + aabb.width - circle.position.x;
|
||||
const ddy = aabb.position.y + aabb.height - circle.position.y;
|
||||
if (ddx * ddx + ddy * ddy > radiusSquare) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { pointer } from "#/engine/Pointer.ts";
|
||||
import { fromSrc, type Sprite } from "#/engine/Sprite.ts";
|
||||
import charIdle from "#/game/assets/char-idle.png";
|
||||
|
||||
// import { moveAndCollide } from "#/some/where.ts";
|
||||
|
||||
const idle: Sprite = await fromSrc(charIdle, 2, 4);
|
||||
|
||||
const { animate, process } = defineEntity("hero", {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { drawCircle } from "#/engine/Circle";
|
||||
import { pointer } from "#/engine/Pointer.ts";
|
||||
import { defineScene } from "#/engine/Scene.ts";
|
||||
import type { Vector } from "#/engine/Vector.ts";
|
||||
import data from "./data.json";
|
||||
|
||||
const { process, preProcess, linkScenes } = defineScene(data);
|
||||
@@ -15,19 +15,11 @@ preProcess((entityInstanceMap) => {
|
||||
instance.position.y = data.height - 16;
|
||||
});
|
||||
|
||||
function drawPoint(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
position: Vector,
|
||||
radius: number = 4,
|
||||
): void {
|
||||
ctx.beginPath();
|
||||
ctx.arc(position.x, position.y, radius, 0, 2 * Math.PI);
|
||||
ctx.strokeStyle = "#ff9000";
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
process((ctx, delta) => {
|
||||
if (!pointer.isDown) {
|
||||
drawPoint(ctx, pointer.position);
|
||||
drawCircle(ctx, {
|
||||
position: pointer.position,
|
||||
radius: 4,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user