fix(nds): use deltaTime in frame based-motion

This commit is contained in:
2026-02-13 17:10:32 +01:00
parent 555ecf8d80
commit f674404ff2
4 changed files with 59 additions and 48 deletions

View File

@@ -1,21 +1,22 @@
const PARTICLE_COUNT = 400;
const SPAWN_DURATION = 700;
const VX_RANGE = 0.5;
const VY_MIN = 0.3;
const VY_RANGE = 0.2;
const SPAWN_DURATION = 350;
const VX_RANGE = 1.0;
const VY_MIN = 0.6;
const VY_RANGE = 0.4;
const WIDTH_MIN = 3;
const WIDTH_RANGE = 4;
const HEIGHT_MIN = 2;
const HEIGHT_RANGE = 3;
const ROTATION_SPEED_RANGE = 0.15;
const DRIFT_STRENGTH = 0.03;
const GRAVITY = 0.007;
const VX_DAMPING = 0.995;
const SWAY_AMPLITUDE = 0.3;
const SWAY_SPEED_MIN = 0.02;
const SWAY_SPEED_RANGE = 0.03;
const ROTATION_SPEED_RANGE = 0.3;
const DRIFT_STRENGTH = 0.06;
const GRAVITY = 0.014;
const VX_DAMPING = 0.988;
const SWAY_AMPLITUDE = 0.6;
const SWAY_SPEED_MIN = 0.04;
const SWAY_SPEED_RANGE = 0.06;
const OFFSCREEN_MARGIN = 10;
const TOTAL_HEIGHT = 192 * 2;
const FRAME_TIME = 1000 / 60;
const COLORS = [
"#fb0018",
@@ -41,7 +42,7 @@ export type ConfettiParticle = {
};
type Spawner = {
frame: number;
elapsed: number;
accumulator: number;
particleCount: number;
duration: number;
@@ -67,18 +68,25 @@ const spawnParticle = () => {
};
const spawn = (particleCount = PARTICLE_COUNT, duration = SPAWN_DURATION) => {
spawners.push({ frame: 0, accumulator: 0, particleCount, duration });
spawners.push({
elapsed: 0,
accumulator: 0,
particleCount,
duration: duration * FRAME_TIME,
});
};
const update = () => {
const update = (deltaTime: number) => {
const dt = deltaTime / FRAME_TIME;
for (let s = spawners.length - 1; s >= 0; s -= 1) {
const spawner = spawners[s]!;
if (spawner.frame < spawner.duration) {
const progress = spawner.frame / spawner.duration;
if (spawner.elapsed < spawner.duration) {
const progress = spawner.elapsed / spawner.duration;
const inv = 1 - progress;
const rate = inv * inv;
spawner.accumulator +=
rate * (spawner.particleCount / spawner.duration) * 3;
rate * (spawner.particleCount / spawner.duration) * 3 * deltaTime;
const count = Math.floor(spawner.accumulator);
spawner.accumulator -= count;
@@ -87,7 +95,7 @@ const update = () => {
spawnParticle();
}
spawner.frame += 1;
spawner.elapsed += deltaTime;
} else {
spawners.splice(s, 1);
}
@@ -95,13 +103,13 @@ const update = () => {
for (let i = particles.length - 1; i >= 0; i -= 1) {
const p = particles[i]!;
p.vy += GRAVITY;
p.vx += (Math.random() - 0.5) * DRIFT_STRENGTH;
p.vx *= VX_DAMPING;
p.swayPhase += p.swaySpeed;
p.x += p.vx + Math.sin(p.swayPhase) * SWAY_AMPLITUDE;
p.y += p.vy;
p.rotation += p.rotationSpeed;
p.vy += GRAVITY * dt;
p.vx += (Math.random() - 0.5) * DRIFT_STRENGTH * dt;
p.vx *= Math.pow(VX_DAMPING, dt);
p.swayPhase += p.swaySpeed * dt;
p.x += (p.vx + Math.sin(p.swayPhase) * SWAY_AMPLITUDE) * dt;
p.y += p.vy * dt;
p.rotation += p.rotationSpeed * dt;
if (p.y > TOTAL_HEIGHT + OFFSCREEN_MARGIN) {
particles.splice(i, 1);