mirror of
https://github.com/nvms/prsm.git
synced 2025-12-17 08:30:53 +00:00
147 lines
4.0 KiB
TypeScript
147 lines
4.0 KiB
TypeScript
import { pulse } from "./misc";
|
|
import { createWorld, type WorldState } from "./ngn";
|
|
import { create2D } from "./packages/2d";
|
|
import { ColorEasing, createParticleSystem, Particle } from "./packages/emitter";
|
|
|
|
const { canvas, draw } = create2D({ canvas: { fullscreen: true } });
|
|
|
|
const particleSystem = createParticleSystem({
|
|
x: canvas.width / 2,
|
|
y: canvas.height / 2,
|
|
canvas,
|
|
});
|
|
|
|
const emitter = particleSystem.createEmitter({
|
|
x: canvas.width / 2,
|
|
y: canvas.height / 2,
|
|
maxParticles: 100,
|
|
rate: 0.1,
|
|
lifetime: 1000,
|
|
lifetimeVariation: 0.2,
|
|
size: 20,
|
|
sizeVariation: 10,
|
|
colorStart: ["#FF0000", "#ff5100"],
|
|
colorEnd: "#222222",
|
|
colorEasing: ColorEasing.EASE_IN,
|
|
fadeOutEasing: ColorEasing.EASE_OUT,
|
|
speed: 0.1,
|
|
speedVariation: 1,
|
|
angle: 0,
|
|
spread: 0.75,
|
|
gravity: { x: 0, y: 0 },
|
|
canvas,
|
|
burst: false,
|
|
|
|
onInit: (particle: Particle, state: WorldState) => {
|
|
particle.x += Math.random() < 0.5 ? -6 : 6;
|
|
particle.y += Math.random() < 0.5 ? -6 : 6;
|
|
|
|
if (!(Math.random() < 0.02)) {
|
|
return;
|
|
}
|
|
|
|
particle.size = 15;
|
|
particle.speedY = -0.3;
|
|
particle.lifetime = 1000;
|
|
particle.colorEnd = "#ff0000";
|
|
|
|
particle.onRemove = () => {
|
|
particleSystem.createEmitter({
|
|
x: particle.x,
|
|
y: particle.y,
|
|
maxParticles: 3,
|
|
lifetimeVariation: 0.2,
|
|
size: 3,
|
|
sizeVariation: 2,
|
|
colorStart: ["#FF0000", "#ff5100"],
|
|
colorEnd: "#222222",
|
|
colorEasing: ColorEasing.EASE_IN,
|
|
fadeOutEasing: ColorEasing.EASE_OUT,
|
|
speed: 0.02,
|
|
speedVariation: 1,
|
|
spread: 6,
|
|
angle: 180,
|
|
canvas,
|
|
burst: true,
|
|
});
|
|
};
|
|
|
|
particle.onUpdate = () => {
|
|
particle.size = Math.max(0, particle.size + 0.25);
|
|
};
|
|
},
|
|
onUpdate: (particle: Particle, state: WorldState) => {
|
|
particle.size = Math.max(0, particle.size - 0.35);
|
|
const v = pulse(state.time.elapsed, 0.25, -1, 1);
|
|
particle.x += v * 1;
|
|
},
|
|
onRemove: (particle: Particle, state: WorldState) => {},
|
|
});
|
|
|
|
const { addSystem, start, step, defineMain } = createWorld();
|
|
|
|
const clearCanvasSystem = () => {
|
|
const context = canvas.getContext("2d");
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
context.fillStyle = "#111";
|
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
};
|
|
|
|
const fpsDrawSystem = (state: WorldState) => {
|
|
draw.text({ x: 10, y: 20 }, `FPS: ${state.time.fps.toFixed(2)}`, "white");
|
|
};
|
|
|
|
const particleCountSystem = (state: WorldState) => {
|
|
draw.text({ x: 10, y: 40 }, `Particle count: ${particleSystem.numParticles}`, "white");
|
|
};
|
|
|
|
const particlePositionSystem = (state: WorldState) => {
|
|
const { time } = state;
|
|
const xPos = pulse(time.elapsed, 0.25, canvas.width / 2 - 100, canvas.width / 2 + 100);
|
|
// const yPos = pulse(time.elapsed, 0.25, canvas.height / 2 - 100, canvas.height / 2 + 100);
|
|
emitter.x = xPos;
|
|
// emitter.y = yPos;
|
|
};
|
|
|
|
addSystem(clearCanvasSystem, fpsDrawSystem, particleCountSystem, particlePositionSystem, particleSystem);
|
|
|
|
defineMain(() => {
|
|
step();
|
|
});
|
|
|
|
start();
|
|
|
|
const container = document.createElement("div");
|
|
container.style.position = "fixed";
|
|
container.style.bottom = "0";
|
|
container.style.left = "0";
|
|
container.style.padding = "10px";
|
|
container.style.display = "flex";
|
|
container.style.justifyContent = "space-between";
|
|
container.style.alignItems = "center";
|
|
document.body.appendChild(container);
|
|
|
|
const pauseButton = document.createElement("button");
|
|
pauseButton.innerText = "Pause";
|
|
pauseButton.onclick = () => {
|
|
particleSystem.pause();
|
|
};
|
|
container.appendChild(pauseButton);
|
|
|
|
const startButton = document.createElement("button");
|
|
startButton.innerText = "Start";
|
|
startButton.style.marginLeft = "5px";
|
|
startButton.onclick = () => {
|
|
particleSystem.start();
|
|
};
|
|
container.appendChild(startButton);
|
|
|
|
const destroyButton = document.createElement("button");
|
|
destroyButton.innerText = "Destroy";
|
|
destroyButton.style.marginLeft = "5px";
|
|
destroyButton.onclick = () => {
|
|
particleSystem.destroy();
|
|
};
|
|
container.appendChild(destroyButton);
|