Skip to content

Commit 73db48d

Browse files
author
Basu Jindal
committed
add wind
1 parent a11e7c4 commit 73db48d

1 file changed

Lines changed: 31 additions & 8 deletions

File tree

js/japanese-petals.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
const ctx = canvas.getContext('2d');
1212
const COLORS = ['#ffb7c5', '#ff8aa3', '#ffc8d5', '#ffd1dc', '#ffa8b8', '#ff95b0'];
1313
const TARGET_FLYING = 18;
14-
const SETTLED_CAP = 60;
15-
const SPAWN_INTERVAL_MS = 900;
16-
// Only the big surfaces — petals on tiny cells (chart, options) obscure content.
17-
const SURFACE_SEL = '.jp-fact, .jp-card, .jp-quiz-prompt, .jp-word-card, .jp-modal-card';
14+
const SETTLED_CAP = 220; // memory cap — oldest settled gets dropped past this
15+
const SPAWN_INTERVAL_MS = 280;
16+
// Petals can settle on any visible surface, big or small.
17+
const SURFACE_SEL = '.jp-fact, .jp-card, .jp-card-face, .jp-quiz-prompt, .jp-word-card, .jp-modal-card, .jp-mode, .jp-stat, .jp-opt, .jp-match-tile, .jp-tool-btn, .jp-chart-cell, .jp-pill, .jp-mini-pill, .jp-word-cat, .jp-restart-btn, .jp-btn, .jp-fact-next, .jp-speak-btn';
1818

1919
let dpr = Math.min(window.devicePixelRatio || 1, 2);
2020
let W = window.innerWidth, H = window.innerHeight;
@@ -47,6 +47,16 @@
4747
}
4848
}
4949

50+
// ===== Wind from the side =====
51+
// Layered sines: a slow base direction + slower gust + faster ripple.
52+
// Returns a value roughly in [-1, +1.6]; positive = blowing rightward.
53+
function wind(t) {
54+
return 0.25
55+
+ Math.sin(t * 0.00035) * 0.55
56+
+ Math.sin(t * 0.0013) * 0.25
57+
+ Math.sin(t * 0.0041) * 0.1;
58+
}
59+
5060
// ===== Petal =====
5161
class Petal {
5262
constructor(initial) { this.reset(initial); }
@@ -94,6 +104,7 @@
94104
// Physics
95105
this.vy += 0.012; // gravity
96106
this.vx += Math.sin(t * 0.001 + this.swayPhase) * 0.018 * this.swayAmp; // gentle wind
107+
this.vx += wind(t) * 0.012; // global side wind
97108
this.vx *= 0.985; // drag
98109
if (this.vy > 2.6) this.vy = 2.6;
99110
if (this.vx > 1.6) this.vx = 1.6;
@@ -155,8 +166,13 @@
155166
}
156167

157168
const petals = [];
158-
// Seed with a handful of flying petals already on screen.
159-
for (let i = 0; i < TARGET_FLYING; i++) petals.push(new Petal(true));
169+
// Seed petals only ABOVE the viewport so they fall in naturally — no random
170+
// in-screen positions at start.
171+
for (let i = 0; i < TARGET_FLYING; i++) {
172+
const p = new Petal(false);
173+
p.y = -20 - Math.random() * H * 2;
174+
petals.push(p);
175+
}
160176

161177
// Anchor flying petals to the page (not the viewport): when the user
162178
// scrolls, shift each flying petal by the same amount so it stays put
@@ -178,13 +194,20 @@
178194
if (surfaceListAge > 1500) { rebuildSurfaceEls(); surfaceListAge = 0; }
179195
refreshSurfaceRects();
180196

181-
// Maintain a steady stream of new flying petals — settled ones never get replaced.
197+
// Maintain a steady stream of new flying petals — they keep falling forever.
182198
let flyingCount = 0, settledCount = 0;
183199
for (let i = 0; i < petals.length; i++) {
184200
if (petals[i].settled) settledCount++;
185201
else flyingCount++;
186202
}
187-
if (flyingCount < TARGET_FLYING && settledCount < SETTLED_CAP && t - lastSpawn > SPAWN_INTERVAL_MS) {
203+
// Memory cap: drop oldest settled petal once we exceed the cap (FIFO).
204+
if (settledCount > SETTLED_CAP) {
205+
for (let i = 0; i < petals.length; i++) {
206+
if (petals[i].settled) { petals.splice(i, 1); break; }
207+
}
208+
}
209+
// Always keep the air populated with falling petals.
210+
if (flyingCount < TARGET_FLYING && t - lastSpawn > SPAWN_INTERVAL_MS) {
188211
petals.push(new Petal(false));
189212
lastSpawn = t;
190213
}

0 commit comments

Comments
 (0)