reformat move.ts
This commit is contained in:
@@ -4,14 +4,12 @@ import { drawCircle, resizeCanvas } from "./common.js";
|
|||||||
const SEGMENT_SPACING = 100;
|
const SEGMENT_SPACING = 100;
|
||||||
|
|
||||||
function initTrail(pos: Vec2d, len: number) {
|
function initTrail(pos: Vec2d, len: number) {
|
||||||
return Array.from({ length: len }, (_, i) =>
|
return Array.from({ length: len }, (_, i) => pos.add(new Vec2d(-1, 0).scale(i * SEGMENT_SPACING)));
|
||||||
pos.add(new Vec2d(0, -1).scale(i * SEGMENT_SPACING)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// state
|
// state
|
||||||
let target: Vec2d | undefined = undefined;
|
let target: Vec2d | undefined = undefined;
|
||||||
let trail = initTrail(new Vec2d(200, 200), 5);
|
let trail = initTrail(new Vec2d(500, 500), 5);
|
||||||
let velocity = new Vec2d(500, 500);
|
let velocity = new Vec2d(500, 500);
|
||||||
let pause = false;
|
let pause = false;
|
||||||
let mode: "follow" | "bounce" | "circle" = "follow";
|
let mode: "follow" | "bounce" | "circle" = "follow";
|
||||||
@@ -23,26 +21,19 @@ function update(ctx: CanvasRenderingContext2D, timestamp: number) {
|
|||||||
lastFrameTime = timestamp;
|
lastFrameTime = timestamp;
|
||||||
if (!pause) {
|
if (!pause) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "bounce":
|
case "bounce": updateBounce(ctx, dt); break;
|
||||||
updateBounce(ctx, dt);
|
case "follow": updateFollow(ctx, dt); break;
|
||||||
break;
|
case "circle": updateCircle(ctx, dt); break;
|
||||||
case "follow":
|
default: throw new Error(`Unknown mode: ${mode}`);
|
||||||
updateFollow(ctx, dt);
|
|
||||||
break;
|
|
||||||
case "circle":
|
|
||||||
updateCircle(ctx, dt);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`Unknown mode: ${mode}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
for (const pos of trail) {
|
for (const pos of trail) {
|
||||||
drawCircle(ctx, pos, 20, 0xff00ff);
|
drawCircle(ctx, pos, 20, 0xFF00FF);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.requestAnimationFrame((t) => update(ctx, t));
|
window.requestAnimationFrame(t => update(ctx, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFollow(ctx: CanvasRenderingContext2D, dt: number) {
|
function updateFollow(ctx: CanvasRenderingContext2D, dt: number) {
|
||||||
@@ -52,7 +43,9 @@ function updateFollow(ctx: CanvasRenderingContext2D, dt: number) {
|
|||||||
// frame, so this is framerate dependent:
|
// frame, so this is framerate dependent:
|
||||||
// trail[0] = trail[0].lerp(target, 0.1);
|
// trail[0] = trail[0].lerp(target, 0.1);
|
||||||
// use exponential decay instead, this is framerate independent:
|
// use exponential decay instead, this is framerate independent:
|
||||||
const alpha = Math.exp(-10 * dt);
|
// a = a + (b - a) * t lerp formula
|
||||||
|
// a = a + (b - a) * e^(-k * dt) substitute t with e^(-k * dt)
|
||||||
|
const alpha = Math.exp(-10 * dt)
|
||||||
trail[0] = trail[0].lerp(target, alpha);
|
trail[0] = trail[0].lerp(target, alpha);
|
||||||
updateTrail();
|
updateTrail();
|
||||||
}
|
}
|
||||||
@@ -62,32 +55,19 @@ function updateBounce(ctx: CanvasRenderingContext2D, dt: number) {
|
|||||||
// update head pos
|
// update head pos
|
||||||
// P_t+1 = P_t + V * t
|
// P_t+1 = P_t + V * t
|
||||||
const newPos = trail[0].add(velocity.scale(dt));
|
const newPos = trail[0].add(velocity.scale(dt));
|
||||||
if (newPos.x > ctx.canvas.width - 100) {
|
if (newPos.x > ctx.canvas.width - 100) { velocity.x *= -1; newPos.x = ctx.canvas.width - 100; }
|
||||||
velocity.x *= -1;
|
if (newPos.y > ctx.canvas.height - 100) { velocity.y *= -1; newPos.y = ctx.canvas.height - 100; }
|
||||||
newPos.x = ctx.canvas.width - 100;
|
if (newPos.x < 100) { velocity.x *= -1; newPos.x = 100; }
|
||||||
}
|
if (newPos.y < 100) { velocity.y *= -1; newPos.y = 100; }
|
||||||
if (newPos.y > ctx.canvas.height - 100) {
|
|
||||||
velocity.y *= -1;
|
|
||||||
newPos.y = ctx.canvas.height - 100;
|
|
||||||
}
|
|
||||||
if (newPos.x < 100) {
|
|
||||||
velocity.x *= -1;
|
|
||||||
newPos.x = 100;
|
|
||||||
}
|
|
||||||
if (newPos.y < 100) {
|
|
||||||
velocity.y *= -1;
|
|
||||||
newPos.y = 100;
|
|
||||||
}
|
|
||||||
trail[0] = newPos;
|
trail[0] = newPos;
|
||||||
updateTrail();
|
updateTrail();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCircle(ctx: CanvasRenderingContext2D, dt: number) {
|
function updateCircle(ctx: CanvasRenderingContext2D, dt: number) {
|
||||||
const center = new Vec2d(ctx.canvas.width / 2, ctx.canvas.height / 2);
|
const center = new Vec2d(ctx.canvas.width / 2, ctx.canvas.height / 2);
|
||||||
const rel = trail[0].sub(center);
|
const rel = trail[0].sub(center); // distance from center
|
||||||
const radius = rel.length();
|
const { r, theta } = rel.toPolar();
|
||||||
const theta = Math.atan2(rel.y, rel.x) + dt;
|
trail[0] = center.add(Vec2d.fromPolar(r, theta + dt));
|
||||||
trail[0] = center.add(Vec2d.fromPolar(radius, theta));
|
|
||||||
updateTrail();
|
updateTrail();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,22 +97,22 @@ function init() {
|
|||||||
canvas.onmousemove = (evt) => {
|
canvas.onmousemove = (evt) => {
|
||||||
const {clientX, clientY} = evt;
|
const {clientX, clientY} = evt;
|
||||||
target = new Vec2d(clientX, clientY);
|
target = new Vec2d(clientX, clientY);
|
||||||
};
|
}
|
||||||
|
|
||||||
canvas.onclick = () => {
|
canvas.onclick = () => {
|
||||||
pause = !pause;
|
pause = !pause;
|
||||||
};
|
}
|
||||||
|
|
||||||
window.onkeydown = (evt) => {
|
window.onkeydown = (evt) => {
|
||||||
if (mode === "bounce") mode = "follow";
|
if (mode === "bounce") mode = "follow";
|
||||||
else if (mode === "follow") mode = "circle";
|
else if (mode === "follow") mode = "circle";
|
||||||
else if (mode === "circle") mode = "bounce";
|
else if (mode === "circle") mode = "bounce";
|
||||||
console.log(mode);
|
console.log(mode);
|
||||||
};
|
}
|
||||||
|
|
||||||
window.addEventListener("resize", () => resizeCanvas(ctx));
|
window.addEventListener('resize', () => resizeCanvas(ctx));
|
||||||
|
|
||||||
window.requestAnimationFrame((t) => update(ctx, t));
|
window.requestAnimationFrame(t => update(ctx, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ export default class Vec2d implements Point {
|
|||||||
return `[${this.x}, ${this.y}]`;
|
return `[${this.x}, ${this.y}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toPolar() {
|
||||||
|
return {
|
||||||
|
r: this.length(),
|
||||||
|
theta: Math.atan2(this.y, this.x),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
normalize(): Vec2d {
|
normalize(): Vec2d {
|
||||||
const len = this.length();
|
const len = this.length();
|
||||||
return new Vec2d(this.x / len, this.y / len);
|
return new Vec2d(this.x / len, this.y / len);
|
||||||
|
|||||||
Reference in New Issue
Block a user