Refactors options and adds a fillScreen mode

This commit is contained in:
Emmaline Autumn 2023-11-04 23:41:39 -06:00
parent 31596774df
commit e70787260a
5 changed files with 146 additions and 73 deletions

159
bundle.js
View File

@ -684,54 +684,6 @@ class OriginVector extends Vector {
return new OriginVector(origin, v);
}
}
function satCollisionSpline(p, spline) {
for(let i = 0; i < 100; i++){
const t1 = i / 100;
const t2 = (i + 1) / 100;
const segmentStart = spline.getPointAtT(t1);
const segmentEnd = spline.getPointAtT(t2);
if (segmentIntersectsPolygon(p, segmentStart, segmentEnd)) {
return true;
}
}
return false;
}
function segmentIntersectsPolygon(p, start, end) {
const edges = p.getEdges();
for (const edge of edges){
const axis = edge.copy().normal().normalize();
const proj1 = projectPolygonOntoAxis(p, axis);
const proj2 = projectSegmentOntoAxis(start, end, axis);
if (!overlap(proj1, proj2)) {
return false;
}
}
return true;
}
function projectPolygonOntoAxis(p, axis) {
let min = Infinity;
let max = -Infinity;
for (const point of p.points){
const dotProduct = point.copy().add(p.center).dot(axis);
min = Math.min(min, dotProduct);
max = Math.max(max, dotProduct);
}
return {
min,
max
};
}
function projectSegmentOntoAxis(start, end, axis) {
const dotProductStart = start.dot(axis);
const dotProductEnd = end.dot(axis);
return {
min: Math.min(dotProductStart, dotProductEnd),
max: Math.max(dotProductStart, dotProductEnd)
};
}
function overlap(proj1, proj2) {
return proj1.min <= proj2.max && proj1.max >= proj2.min;
}
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;
class Doodler {
@ -749,15 +701,24 @@ class Doodler {
draggables = [];
clickables = [];
dragTarget;
constructor({ width, height, canvas, bg, framerate }, postInit){
constructor({ width, height, fillScreen, canvas, bg, framerate }, postInit){
if (!canvas) {
canvas = document.createElement("canvas");
document.body.append(canvas);
}
this.bg = bg || "white";
this.framerate = framerate || 60;
canvas.width = width;
canvas.height = height;
canvas.width = fillScreen ? document.body.clientWidth : width;
canvas.height = fillScreen ? document.body.clientHeight : height;
if (fillScreen) {
const resizeObserver = new ResizeObserver((entries)=>{
for (const entry of entries){
this._canvas.width = entry.target.clientWidth;
this._canvas.height = entry.target.clientHeight;
}
});
resizeObserver.observe(document.body);
}
this._canvas = canvas;
const ctx = canvas.getContext("2d");
if (!ctx) throw "Unable to initialize Doodler: Canvas context not found";
@ -1308,6 +1269,54 @@ const init = (opt, zoomable, postInit)=>{
window.doodler = zoomable ? new ZoomableDoodler(opt, postInit) : new Doodler(opt, postInit);
window.doodler.init();
};
function satCollisionSpline(p, spline) {
for(let i = 0; i < 100; i++){
const t1 = i / 100;
const t2 = (i + 1) / 100;
const segmentStart = spline.getPointAtT(t1);
const segmentEnd = spline.getPointAtT(t2);
if (segmentIntersectsPolygon(p, segmentStart, segmentEnd)) {
return true;
}
}
return false;
}
function segmentIntersectsPolygon(p, start, end) {
const edges = p.getEdges();
for (const edge of edges){
const axis = edge.copy().normal().normalize();
const proj1 = projectPolygonOntoAxis(p, axis);
const proj2 = projectSegmentOntoAxis(start, end, axis);
if (!overlap(proj1, proj2)) {
return false;
}
}
return true;
}
function projectPolygonOntoAxis(p, axis) {
let min = Infinity;
let max = -Infinity;
for (const point of p.points){
const dotProduct = point.copy().add(p.center).dot(axis);
min = Math.min(min, dotProduct);
max = Math.max(max, dotProduct);
}
return {
min,
max
};
}
function projectSegmentOntoAxis(start, end, axis) {
const dotProductStart = start.dot(axis);
const dotProductEnd = end.dot(axis);
return {
min: Math.min(dotProductStart, dotProductEnd),
max: Math.max(dotProductStart, dotProductEnd)
};
}
function overlap(proj1, proj2) {
return proj1.min <= proj2.max && proj1.max >= proj2.min;
}
class Polygon {
points;
center;
@ -1580,9 +1589,8 @@ class SplineSegment {
}
}
init({
width: 400,
height: 400,
framerate: 90
fillScreen: true,
bg: "#333"
}, true, (ctx)=>{
ctx.imageSmoothingEnabled = false;
});
@ -1590,7 +1598,48 @@ const img = new Image();
img.src = "./pixel fire.gif";
const p = new Vector();
const gif = new GIFAnimation("./fire-joypixels.gif", p, .5);
const spline = new SplineSegment([
new Vector({
x: -25,
y: -25
}).mult(10).add(p),
new Vector({
x: 25,
y: -25
}).mult(10).add(p),
new Vector({
x: -25,
y: -25
}).mult(10).add(p),
new Vector({
x: -25,
y: 25
}).mult(10).add(p)
]);
const poly2 = Polygon.createPolygon(4);
poly2.center = p.copy().add(100, 100);
doodler.createLayer((c, i, t)=>{
gif.draw(t);
for(let i = 0; i < c.canvas.width; i += 50){
for(let j = 0; j < c.canvas.height; j += 50){
doodler.drawSquare(new Vector(i, j), 50, {
color: "#00000010"
});
}
}
poly2.circularHitbox;
const intersects = satCollisionSpline(poly2, spline);
const color = intersects ? "red" : "aqua";
spline.draw(color);
poly2.draw(color);
const [gamepad] = navigator.getGamepads();
if (gamepad) {
gamepad.axes[0];
gamepad.axes[1];
const rightX = gamepad.axes[2];
const rightY = gamepad.axes[3];
let mMulti = 10;
const mod = new Vector(Math.min(Math.max(rightX - 0.05, 0), rightX + 0.05), Math.min(Math.max(rightY - 0.05, 0), rightY + 0.05));
poly2.center.add(mod.mult(mMulti));
}
});
requestAnimationFrame;

View File

@ -6,7 +6,7 @@ import { postInit } from "./postInit.ts";
import { ZoomableDoodler } from "./zoomableCanvas.ts";
export const init = (
opt: IDoodlerOptions,
opt: DoodlerOptions,
zoomable: boolean,
postInit?: postInit,
) => {
@ -19,13 +19,22 @@ export const init = (
window.doodler.init();
};
export interface IDoodlerOptions {
width: number;
height: number;
type DoodlerOptionalOptions = {
canvas?: HTMLCanvasElement;
bg?: string;
framerate?: number;
}
};
type DoodlerRequiredOptions = {
width: number;
height: number;
fillScreen?: false;
} | {
width?: 0;
height?: 0;
fillScreen: true;
};
export type DoodlerOptions = DoodlerOptionalOptions & DoodlerRequiredOptions;
type layer = (
ctx: CanvasRenderingContext2D,
@ -57,10 +66,11 @@ export class Doodler {
constructor({
width,
height,
fillScreen,
canvas,
bg,
framerate,
}: IDoodlerOptions, postInit?: postInit) {
}: DoodlerOptions, postInit?: postInit) {
if (!canvas) {
canvas = document.createElement("canvas");
document.body.append(canvas);
@ -69,8 +79,19 @@ export class Doodler {
this.bg = bg || "white";
this.framerate = framerate || 60;
canvas.width = width;
canvas.height = height;
canvas.width = fillScreen ? document.body.clientWidth : width;
canvas.height = fillScreen ? document.body.clientHeight : height;
if (fillScreen) {
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
this._canvas.width = entry.target.clientWidth;
this._canvas.height = entry.target.clientHeight;
// this.ctx = this.c
}
});
resizeObserver.observe(document.body);
}
this._canvas = canvas;

View File

@ -9,6 +9,12 @@
<style>
* {
image-rendering: pixelated;
margin: 0;
}
body {
height: 100vh;
overflow: hidden;
}
img {

13
main.ts
View File

@ -14,8 +14,9 @@ import { SplineSegment } from "./geometry/spline.ts";
initializeDoodler(
{
width: 2400,
height: 1200,
// width: 2400,
fillScreen: true,
// height: 1200,
bg: "#333",
},
true,
@ -35,11 +36,6 @@ img.src = "./pixel fire.gif";
const p = new Vector();
const gif = new GIFAnimation("./fire-joypixels.gif", p, .5);
doodler.createLayer((c, i, t) => {
gif.draw(t);
// c.drawImage(img, 0, 0);
});
const spline = new SplineSegment([
new Vector({ x: -25, y: -25 }).mult(10).add(p),
new Vector({ x: 25, y: -25 }).mult(10).add(p),
@ -53,7 +49,8 @@ const poly2 = Polygon.createPolygon(4);
poly2.center = p.copy().add(100, 100);
// poly.center.add(p);
doodler.createLayer((c) => {
doodler.createLayer((c, i, t) => {
gif.draw(t);
// c.translate(1200, 600);
for (let i = 0; i < c.canvas.width; i += 50) {
for (let j = 0; j < c.canvas.height; j += 50) {

View File

@ -1,4 +1,4 @@
import { Doodler, IDoodlerOptions } from "./canvas.ts";
import { Doodler, DoodlerOptions } from "./canvas.ts";
import { OriginVector, Point } from "./geometry/vector.ts";
import { postInit } from "./postInit.ts";
import { easeInOut } from "./timing/EaseInOut.ts";
@ -29,7 +29,7 @@ export class ZoomableDoodler extends Doodler {
maxScale = 4;
constructor(options: IDoodlerOptions, postInit?: postInit) {
constructor(options: DoodlerOptions, postInit?: postInit) {
super(options, postInit);
this._canvas.addEventListener("wheel", (e) => {