changes hitbox getters to get properties, adds aaContains
This commit is contained in:
parent
601bc51233
commit
62b13e49e7
109
bundle.js
109
bundle.js
@ -2,8 +2,8 @@
|
|||||||
// deno-lint-ignore-file
|
// deno-lint-ignore-file
|
||||||
// This code was bundled using `deno bundle` and it's not recommended to edit it manually
|
// This code was bundled using `deno bundle` and it's not recommended to edit it manually
|
||||||
|
|
||||||
const axisAlignedCollision = (aa1, aa2)=>{
|
const axisAlignedContains = (aa1, aa2)=>{
|
||||||
return aa1.x < aa2.x + aa2.w && aa1.x + aa1.w > aa2.x && aa1.y < aa2.y + aa2.h && aa1.y + aa1.h > aa2.y;
|
return aa1.x < aa2.x && aa1.y < aa2.y && aa1.x + aa1.w > aa2.x + aa2.w && aa1.y + aa1.h > aa2.y + aa2.h;
|
||||||
};
|
};
|
||||||
const Constants = {
|
const Constants = {
|
||||||
TWO_PI: Math.PI * 2
|
TWO_PI: Math.PI * 2
|
||||||
@ -293,6 +293,89 @@ class OriginVector extends Vector {
|
|||||||
return new OriginVector(origin, v);
|
return new OriginVector(origin, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const satCollision = (s1, s2)=>{
|
||||||
|
const shape1 = s1.points.map((p)=>new Vector(p).add(s1.center));
|
||||||
|
const shape2 = s2.points.map((p)=>new Vector(p).add(s2.center));
|
||||||
|
if (shape1.length < 2 || shape2.length < 2) {
|
||||||
|
throw "Insufficient shape data in satCollision";
|
||||||
|
}
|
||||||
|
new Vector(s1.center).sub(s2.center);
|
||||||
|
for(let i = 0; i < shape1.length; i++){
|
||||||
|
const axis = shape1[i].normal(shape1.at(i - 1));
|
||||||
|
let [p1min, p1minDot] = Vector.vectorProjectionAndDot(shape1[0], axis);
|
||||||
|
let [p1max, p1maxDot] = [
|
||||||
|
p1min,
|
||||||
|
p1minDot
|
||||||
|
];
|
||||||
|
for (const point of shape1){
|
||||||
|
const [projected, dot] = Vector.vectorProjectionAndDot(point, axis);
|
||||||
|
p1min = dot < p1minDot ? projected : p1min;
|
||||||
|
p1minDot = Math.min(dot, p1minDot);
|
||||||
|
p1max = dot > p1maxDot ? projected : p1max;
|
||||||
|
p1maxDot = Math.max(dot, p1maxDot);
|
||||||
|
}
|
||||||
|
let [p2min, p2minDot] = Vector.vectorProjectionAndDot(shape2[0], axis);
|
||||||
|
let [p2max, p2maxDot] = [
|
||||||
|
p2min,
|
||||||
|
p2minDot
|
||||||
|
];
|
||||||
|
for (const point of shape2){
|
||||||
|
const [projected, dot] = Vector.vectorProjectionAndDot(point, axis);
|
||||||
|
p2min = dot < p2minDot ? projected : p2min;
|
||||||
|
p2minDot = Math.min(dot, p2minDot);
|
||||||
|
p2max = dot > p2maxDot ? projected : p2max;
|
||||||
|
p2maxDot = Math.max(dot, p2maxDot);
|
||||||
|
}
|
||||||
|
if (p1minDot - p2maxDot > 0 || p2minDot - p1maxDot > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
[
|
||||||
|
axis,
|
||||||
|
p1max,
|
||||||
|
p1min,
|
||||||
|
p2max,
|
||||||
|
p2min
|
||||||
|
];
|
||||||
|
}
|
||||||
|
for(let i = 0; i < shape2.length; i++){
|
||||||
|
const axis = shape2[i].normal(shape2.at(i - 1));
|
||||||
|
let [p1min, p1minDot] = Vector.vectorProjectionAndDot(shape2[0], axis);
|
||||||
|
let [p1max, p1maxDot] = [
|
||||||
|
p1min,
|
||||||
|
p1minDot
|
||||||
|
];
|
||||||
|
for (const point of shape2){
|
||||||
|
const [projected, dot] = Vector.vectorProjectionAndDot(point, axis);
|
||||||
|
p1min = dot < p1minDot ? projected : p1min;
|
||||||
|
p1minDot = Math.min(dot, p1minDot);
|
||||||
|
p1max = dot > p1maxDot ? projected : p1max;
|
||||||
|
p1maxDot = Math.max(dot, p1maxDot);
|
||||||
|
}
|
||||||
|
let [p2min, p2minDot] = Vector.vectorProjectionAndDot(shape1[0], axis);
|
||||||
|
let [p2max, p2maxDot] = [
|
||||||
|
p2min,
|
||||||
|
p2minDot
|
||||||
|
];
|
||||||
|
for (const point of shape1){
|
||||||
|
const [projected, dot] = Vector.vectorProjectionAndDot(point, axis);
|
||||||
|
p2min = dot < p2minDot ? projected : p2min;
|
||||||
|
p2minDot = Math.min(dot, p2minDot);
|
||||||
|
p2max = dot > p2maxDot ? projected : p2max;
|
||||||
|
p2maxDot = Math.max(dot, p2maxDot);
|
||||||
|
}
|
||||||
|
if (p1minDot - p2maxDot > 0 || p2minDot - p1maxDot > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
[
|
||||||
|
axis,
|
||||||
|
p1max,
|
||||||
|
p1min,
|
||||||
|
p2max,
|
||||||
|
p2min
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
const easeInOut = (x)=>x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
const easeInOut = (x)=>x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
||||||
const map = (value, x1, y1, x2, y2)=>(value - x1) * (y2 - x2) / (y1 - x1) + x2;
|
const map = (value, x1, y1, x2, y2)=>(value - x1) * (y2 - x2) / (y1 - x1) + x2;
|
||||||
class Doodler {
|
class Doodler {
|
||||||
@ -879,10 +962,6 @@ class Polygon {
|
|||||||
doodler.line(p1.copy().add(this.center), p2.copy().add(this.center), {
|
doodler.line(p1.copy().add(this.center), p2.copy().add(this.center), {
|
||||||
color
|
color
|
||||||
});
|
});
|
||||||
const { x, y, w, h } = this.aaHitbox();
|
|
||||||
doodler.drawRect(new Vector(x, y), w, h, {
|
|
||||||
color: "lime"
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calcCenter() {
|
calcCenter() {
|
||||||
@ -894,7 +973,7 @@ class Polygon {
|
|||||||
center.div(this.points.length);
|
center.div(this.points.length);
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
circularHitbox() {
|
get circularHitbox() {
|
||||||
let greatestDistance = 0;
|
let greatestDistance = 0;
|
||||||
for (const p of this.points){
|
for (const p of this.points){
|
||||||
greatestDistance = Math.max(p.copy().add(this.center).dist(this.center), greatestDistance);
|
greatestDistance = Math.max(p.copy().add(this.center).dist(this.center), greatestDistance);
|
||||||
@ -904,7 +983,7 @@ class Polygon {
|
|||||||
radius: greatestDistance
|
radius: greatestDistance
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
aaHitbox() {
|
get aaHitbox() {
|
||||||
let smallestX, biggestX, smallestY, biggestY;
|
let smallestX, biggestX, smallestY, biggestY;
|
||||||
smallestX = smallestY = Infinity;
|
smallestX = smallestY = Infinity;
|
||||||
biggestX = biggestY = -Infinity;
|
biggestX = biggestY = -Infinity;
|
||||||
@ -953,12 +1032,12 @@ document.body.append(img);
|
|||||||
const p = new Vector(500, 500);
|
const p = new Vector(500, 500);
|
||||||
const poly = new Polygon([
|
const poly = new Polygon([
|
||||||
{
|
{
|
||||||
x: -50,
|
x: -25,
|
||||||
y: -25
|
y: -25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: 25,
|
x: 25,
|
||||||
y: -50
|
y: -25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: 25,
|
x: 25,
|
||||||
@ -970,7 +1049,7 @@ const poly = new Polygon([
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
const poly2 = Polygon.createPolygon(5, 75);
|
const poly2 = Polygon.createPolygon(5, 75);
|
||||||
poly2.center = p.copy();
|
poly2.center = p.copy().add(100, 100);
|
||||||
poly.center.add(p);
|
poly.center.add(p);
|
||||||
doodler.createLayer((c)=>{
|
doodler.createLayer((c)=>{
|
||||||
for(let i = 0; i < c.canvas.width; i += 50){
|
for(let i = 0; i < c.canvas.width; i += 50){
|
||||||
@ -980,16 +1059,20 @@ doodler.createLayer((c)=>{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const color = axisAlignedCollision(poly.aaHitbox(), poly2.aaHitbox()) ? "red" : "black";
|
const color = satCollision(poly, poly2) ? "red" : "aqua";
|
||||||
poly.draw(color);
|
poly.draw(color);
|
||||||
poly2.draw(color);
|
poly2.draw(color);
|
||||||
const [gamepad] = navigator.getGamepads();
|
const [gamepad] = navigator.getGamepads();
|
||||||
if (gamepad) {
|
if (gamepad) {
|
||||||
const leftX = gamepad.axes[0];
|
const leftX = gamepad.axes[0];
|
||||||
const leftY = gamepad.axes[1];
|
const leftY = gamepad.axes[1];
|
||||||
poly.center.add(new Vector(Math.min(Math.max(leftX - 0.05, 0), leftX + 0.05), Math.min(Math.max(leftY - 0.05, 0), leftY + 0.05)).mult(10));
|
|
||||||
const rightX = gamepad.axes[2];
|
const rightX = gamepad.axes[2];
|
||||||
const rightY = gamepad.axes[3];
|
const rightY = gamepad.axes[3];
|
||||||
|
if (axisAlignedContains(poly2.aaHitbox, poly.aaHitbox)) {
|
||||||
|
poly.center.add(new Vector(Math.min(Math.max(rightX - 0.05, 0), rightX + 0.05), Math.min(Math.max(rightY - 0.05, 0), rightY + 0.05)).mult(10));
|
||||||
|
poly2.center.add(new Vector(Math.min(Math.max(leftX - 0.05, 0), leftX + 0.05), Math.min(Math.max(leftY - 0.05, 0), leftY + 0.05)).mult(10));
|
||||||
|
}
|
||||||
|
poly.center.add(new Vector(Math.min(Math.max(leftX - 0.05, 0), leftX + 0.05), Math.min(Math.max(leftY - 0.05, 0), leftY + 0.05)).mult(10));
|
||||||
poly2.center.add(new Vector(Math.min(Math.max(rightX - 0.05, 0), rightX + 0.05), Math.min(Math.max(rightY - 0.05, 0), rightY + 0.05)).mult(10));
|
poly2.center.add(new Vector(Math.min(Math.max(rightX - 0.05, 0), rightX + 0.05), Math.min(Math.max(rightY - 0.05, 0), rightY + 0.05)).mult(10));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -14,3 +14,13 @@ export const axisAlignedCollision = (
|
|||||||
aa1.y < aa2.y + aa2.h &&
|
aa1.y < aa2.y + aa2.h &&
|
||||||
aa1.y + aa1.h > aa2.y;
|
aa1.y + aa1.h > aa2.y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const axisAlignedContains = (
|
||||||
|
aa1: axisAlignedBoundingBox,
|
||||||
|
aa2: axisAlignedBoundingBox,
|
||||||
|
) => {
|
||||||
|
return aa1.x < aa2.x &&
|
||||||
|
aa1.y < aa2.y &&
|
||||||
|
aa1.x + aa1.w > aa2.x + aa2.w &&
|
||||||
|
aa1.y + aa1.h > aa2.y + aa2.h;
|
||||||
|
};
|
||||||
|
@ -19,8 +19,6 @@ export class Polygon {
|
|||||||
doodler.line(p1.copy().add(this.center), p2.copy().add(this.center), {
|
doodler.line(p1.copy().add(this.center), p2.copy().add(this.center), {
|
||||||
color,
|
color,
|
||||||
});
|
});
|
||||||
const { x, y, w, h } = this.aaHitbox();
|
|
||||||
doodler.drawRect(new Vector(x, y), w, h, { color: "lime" });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +33,7 @@ export class Polygon {
|
|||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
circularHitbox(): CircleLike {
|
get circularHitbox(): CircleLike {
|
||||||
let greatestDistance = 0;
|
let greatestDistance = 0;
|
||||||
for (const p of this.points) {
|
for (const p of this.points) {
|
||||||
greatestDistance = Math.max(
|
greatestDistance = Math.max(
|
||||||
@ -50,7 +48,7 @@ export class Polygon {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
aaHitbox(): axisAlignedBoundingBox {
|
get aaHitbox(): axisAlignedBoundingBox {
|
||||||
let smallestX, biggestX, smallestY, biggestY;
|
let smallestX, biggestX, smallestY, biggestY;
|
||||||
smallestX =
|
smallestX =
|
||||||
smallestY =
|
smallestY =
|
||||||
|
38
main.ts
38
main.ts
@ -1,6 +1,6 @@
|
|||||||
/// <reference types="./global.d.ts" />
|
/// <reference types="./global.d.ts" />
|
||||||
|
|
||||||
import { axisAlignedCollision } from "./collision/aa.ts";
|
import { axisAlignedCollision, axisAlignedContains } from "./collision/aa.ts";
|
||||||
import { circularCollision } from "./collision/circular.ts";
|
import { circularCollision } from "./collision/circular.ts";
|
||||||
import { satCollision } from "./collision/sat.ts";
|
import { satCollision } from "./collision/sat.ts";
|
||||||
import { Polygon } from "./geometry/polygon.ts";
|
import { Polygon } from "./geometry/polygon.ts";
|
||||||
@ -32,15 +32,15 @@ document.body.append(img);
|
|||||||
const p = new Vector(500, 500);
|
const p = new Vector(500, 500);
|
||||||
|
|
||||||
const poly = new Polygon([
|
const poly = new Polygon([
|
||||||
{ x: -50, y: -25 },
|
{ x: -25, y: -25 },
|
||||||
{ x: 25, y: -50 },
|
{ x: 25, y: -25 },
|
||||||
{ x: 25, y: 25 },
|
{ x: 25, y: 25 },
|
||||||
{ x: -25, y: 25 },
|
{ x: -25, y: 25 },
|
||||||
]);
|
]);
|
||||||
// poly.center = p.copy();
|
// poly.center = p.copy();
|
||||||
|
|
||||||
const poly2 = Polygon.createPolygon(5, 75);
|
const poly2 = Polygon.createPolygon(5, 75);
|
||||||
poly2.center = p.copy();
|
poly2.center = p.copy().add(100, 100);
|
||||||
|
|
||||||
poly.center.add(p);
|
poly.center.add(p);
|
||||||
|
|
||||||
@ -50,12 +50,12 @@ doodler.createLayer((c) => {
|
|||||||
doodler.drawSquare(new Vector(i, j), 50, { color: "#00000010" });
|
doodler.drawSquare(new Vector(i, j), 50, { color: "#00000010" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const color = axisAlignedCollision(
|
const color = satCollision(
|
||||||
poly.aaHitbox(),
|
poly,
|
||||||
poly2.aaHitbox(),
|
poly2,
|
||||||
)
|
)
|
||||||
? "red"
|
? "red"
|
||||||
: "black";
|
: "aqua";
|
||||||
|
|
||||||
// console.log(satCollision(
|
// console.log(satCollision(
|
||||||
// ));
|
// ));
|
||||||
@ -70,21 +70,37 @@ doodler.createLayer((c) => {
|
|||||||
if (gamepad) {
|
if (gamepad) {
|
||||||
const leftX = gamepad.axes[0];
|
const leftX = gamepad.axes[0];
|
||||||
const leftY = gamepad.axes[1];
|
const leftY = gamepad.axes[1];
|
||||||
|
const rightX = gamepad.axes[2];
|
||||||
|
const rightY = gamepad.axes[3];
|
||||||
|
|
||||||
|
if (axisAlignedContains(poly2.aaHitbox, poly.aaHitbox)) {
|
||||||
|
poly.center.add(
|
||||||
|
new Vector(
|
||||||
|
Math.min(Math.max(rightX - deadzone, 0), rightX + deadzone),
|
||||||
|
Math.min(Math.max(rightY - deadzone, 0), rightY + deadzone),
|
||||||
|
).mult(10),
|
||||||
|
);
|
||||||
|
poly2.center.add(
|
||||||
|
new Vector(
|
||||||
|
Math.min(Math.max(leftX - deadzone, 0), leftX + deadzone),
|
||||||
|
Math.min(Math.max(leftY - deadzone, 0), leftY + deadzone),
|
||||||
|
).mult(10),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
poly.center.add(
|
poly.center.add(
|
||||||
new Vector(
|
new Vector(
|
||||||
Math.min(Math.max(leftX - deadzone, 0), leftX + deadzone),
|
Math.min(Math.max(leftX - deadzone, 0), leftX + deadzone),
|
||||||
Math.min(Math.max(leftY - deadzone, 0), leftY + deadzone),
|
Math.min(Math.max(leftY - deadzone, 0), leftY + deadzone),
|
||||||
).mult(10),
|
).mult(10),
|
||||||
);
|
);
|
||||||
|
|
||||||
const rightX = gamepad.axes[2];
|
|
||||||
const rightY = gamepad.axes[3];
|
|
||||||
poly2.center.add(
|
poly2.center.add(
|
||||||
new Vector(
|
new Vector(
|
||||||
Math.min(Math.max(rightX - deadzone, 0), rightX + deadzone),
|
Math.min(Math.max(rightX - deadzone, 0), rightX + deadzone),
|
||||||
Math.min(Math.max(rightY - deadzone, 0), rightY + deadzone),
|
Math.min(Math.max(rightY - deadzone, 0), rightY + deadzone),
|
||||||
).mult(10),
|
).mult(10),
|
||||||
);
|
);
|
||||||
|
|
||||||
// (doodler as ZoomableDoodler).moveOrigin({ x: -rigthX * 5, y: -rigthY * 5 });
|
// (doodler as ZoomableDoodler).moveOrigin({ x: -rigthX * 5, y: -rigthY * 5 });
|
||||||
|
|
||||||
// if (gamepad.buttons[7].value) {
|
// if (gamepad.buttons[7].value) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user