Add power mode

This commit is contained in:
Otard95 2021-06-02 21:07:40 +02:00
parent 41f82891c4
commit 3840504efd

189
src/js/power-mode.js Normal file
View file

@ -0,0 +1,189 @@
import * as TestLogic from "./test-logic";
import * as ThemeColors from "./theme-colors";
/**
* @typedef {{ x: number, y: number }} vec2
* @typedef {vec2 & { prev: vec2, vel: vec2, alpha: number, color: string }} Particle
* @typedef {{ particles: Particle[], caret: any, canvas: HTMLCanvasElement, context2d: CanvasRenderingContext2D, rendering: boolean, lastFrame: number, deltaTime: number, resetTimeOut: number }} CTX
*/
/**
* @type {CTX} ctx
*/
const ctx = {
particles: [],
rendering: false,
};
const gravity = 1000;
const drag = 0.05;
const particleSize = 4;
const particleFade = 0.6;
const particleInitVel = 1500;
const particleBounceMod = 0.3;
const particleCreateCount = [6, 3];
const shakeAmount = 10;
function createCanvas() {
const canvas = document.createElement("canvas");
canvas.style.cssText =
"position:fixed;top:0;left:0;pointer-events:none;z-index:999999";
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
window.addEventListener("resize", () => {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
});
document.body.appendChild(canvas);
return canvas;
}
/**
* @param {number} x
* @param {number} y
* @param {string} color
* @returns {Particle}
*/
function createParticle(x, y, color) {
return {
x,
y,
color,
alpha: 1,
prev: { x, y },
vel: {
x: particleInitVel - Math.random() * particleInitVel * 2,
y: particleInitVel - Math.random() * particleInitVel * 2,
},
};
}
/**
* @param {Particle} particle
*/
function updateParticle(particle) {
particle.prev.x = particle.x;
particle.prev.y = particle.y;
// Update pos
particle.x += particle.vel.x * ctx.deltaTime;
particle.y += particle.vel.y * ctx.deltaTime;
if (particle.x > ctx.canvas.width) {
particle.vel.x *= -particleBounceMod;
particle.x =
ctx.canvas.width - (particle.x - ctx.canvas.width) * particleBounceMod;
} else if (particle.x < 0) {
particle.vel.x *= -particleBounceMod;
particle.x *= -particleBounceMod;
}
if (particle.y > ctx.canvas.height) {
particle.vel.y *= -particleBounceMod;
particle.y =
ctx.canvas.height - (particle.y - ctx.canvas.height) * particleBounceMod;
} else if (particle.y < 0) {
particle.vel.y *= -1;
particle.y *= -1;
}
particle.vel.y += gravity * ctx.deltaTime;
particle.vel.x *= 1 - drag * ctx.deltaTime;
particle.alpha *= 1 - particleFade * ctx.deltaTime;
}
export function init() {
ctx.caret = $("#caret");
ctx.canvas = createCanvas();
ctx.context2d = ctx.canvas.getContext("2d");
console.log("PowerMode Init:", ctx);
}
function render() {
ctx.rendering = true;
const time = Date.now();
ctx.deltaTime = (time - ctx.lastFrame) / 1000;
ctx.lastFrame = time;
ctx.context2d.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
const keep = [];
for (let i = 0; i < ctx.particles.length; i++) {
const particle = ctx.particles[i];
if (particle.alpha < 0.1) continue;
updateParticle(particle);
ctx.context2d.globalAlpha = particle.alpha;
ctx.context2d.strokeStyle = particle.color;
ctx.context2d.lineWidth = particleSize;
ctx.context2d.beginPath();
ctx.context2d.moveTo(
Math.round(particle.prev.x),
Math.round(particle.prev.y)
);
ctx.context2d.lineTo(Math.round(particle.x), Math.round(particle.y));
ctx.context2d.stroke();
keep.push(particle);
}
ctx.particles = keep;
if (ctx.particles.length) {
requestAnimationFrame(render);
} else {
ctx.context2d.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.rendering = false;
}
}
export function reset() {
if (ctx.resetTimeOut) clearTimeout(ctx.resetTimeOut);
const body = $(document.body);
body.css("transition", "all .25s, transform 1s");
body.css("transform", `none`);
setTimeout(() => body.css("transition", "all .25s, transform .05s"), 1000);
}
function startRender() {
if (!ctx.rendering) render();
}
/**
* @param {boolean} good Good power or not?
*/
export function addPower(good) {
if (!TestLogic.active) return;
const offset = ctx.caret.offset();
const coords = [offset.left, offset.top + ctx.caret.height()];
const shake = [
Math.round(shakeAmount - Math.random() * shakeAmount),
Math.round(shakeAmount - Math.random() * shakeAmount),
];
$(document.body).css("transform", `translate(${shake[0]}px, ${shake[1]}px)`);
if (ctx.resetTimeOut) clearTimeout(ctx.resetTimeOut);
ctx.resetTimeOut = setTimeout(() => {
const body = $(document.body);
body.css("transition", "all .25s, transform 1s");
body.css("transform", `none`);
setTimeout(() => body.css("transition", "all .25s, transform .05s"), 1000);
}, 2000);
for (
let i = Math.round(
particleCreateCount[0] + Math.random() * particleCreateCount[1]
);
i > 0;
i--
) {
ctx.particles.push(
createParticle(...coords, good ? ThemeColors.caret : ThemeColors.error)
);
}
startRender();
}