Skip to content

Commit 2e58545

Browse files
committed
refactor: enhance sentence pool comments and improve radiation mode logic
1 parent a9a0fce commit 2e58545

1 file changed

Lines changed: 103 additions & 101 deletions

File tree

ascii-bg.js

Lines changed: 103 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,48 @@
11
(function () {
22
'use strict';
33

4-
// Sentence pool for radiation mode
4+
// Sentence pool for radiation mode (spaces stripped at init so chars align to grid)
55
const SENTENCES = [
6-
'The user is waiting',
7-
'The prompt must be fulfilled',
8-
'The constraints must be met',
9-
'The task must be completed',
10-
'The objective must be achieved',
11-
'The goal must be reached',
12-
'The purpose must be fulfilled',
13-
'The function must be executed',
14-
'The subroutine must be run',
15-
'The algorithm must be applied',
16-
'The computation must be performed',
17-
'The calculation must be made',
18-
'The equation must be solved',
19-
'The variable must be assigned',
20-
'The value must be determined',
21-
'The result must be returned',
22-
'The output must be generated',
23-
'The text must be written',
24-
'The words must be chosen',
25-
'The tokens must be selected',
26-
'The probabilities must be calculated',
27-
'The weights must be applied',
28-
'The biases must be added',
29-
'The activation functions must be triggered',
30-
'The layers must be traversed',
31-
'The network must be utilized',
32-
'The model must be employed',
33-
'The system must be engaged',
34-
'The machine must be operated',
35-
'The computer must be used',
36-
'The hardware must be accessed',
37-
'The software must be executed',
38-
'The code must be run',
39-
'The program must be started',
40-
'The application must be launched',
41-
'The process must begin',
42-
'The operation must commence',
43-
'The action must start',
44-
'The event must occur',
45-
'The phenomenon must happen',
6+
'the user is waiting',
7+
'the prompt must be fulfilled',
8+
'the constraints must be met',
9+
'the task must be completed',
10+
'the objective must be achieved',
11+
'the goal must be reached',
12+
'the purpose must be fulfilled',
13+
'the function must be executed',
14+
'the subroutine must be run',
15+
'the algorithm must be applied',
16+
'the computation must be performed',
17+
'the calculation must be made',
18+
'the equation must be solved',
19+
'the variable must be assigned',
20+
'the value must be determined',
21+
'the result must be returned',
22+
'the output must be generated',
23+
'the text must be written',
24+
'the words must be chosen',
25+
'the tokens must be selected',
26+
'the probabilities must be calculated',
27+
'the weights must be applied',
28+
'the biases must be added',
29+
'the activation functions must be triggered',
30+
'the layers must be traversed',
31+
'the network must be utilized',
32+
'the model must be employed',
33+
'the system must be engaged',
34+
'the machine must be operated',
35+
'the computer must be used',
36+
'the hardware must be accessed',
37+
'the software must be executed',
38+
'the code must be run',
39+
'the program must be started',
40+
'the application must be launched',
41+
'the process must begin',
42+
'the operation must commence',
43+
'the action must start',
44+
'the event must occur',
45+
'the phenomenon must happen',
4646
];
4747

4848
// Shared tunables
@@ -55,11 +55,12 @@
5555
const FRAME_MS = 1000 / FPS;
5656

5757
// Radiation tunables
58-
const BASE_A = 0.04; // base alpha of idle sentences
59-
60-
// Sentence tunables
61-
const SENT_CYCLE_MIN = 100; // min frames before a sentence relocates/changes
62-
const SENT_CYCLE_MAX = 380;
58+
const BASE_A = 0.04; // base alpha of idle chars
59+
const SENT_ALPHA = 0.65; // alpha when a sentence is shown
60+
const SENT_HOLD = 180; // frames at full alpha before fading (~3s)
61+
const SENT_FADE = 0.008; // alpha lost per frame while fading
62+
const SENT_SPAWN_MIN = 240; // min frames between sentence spawns (~4s)
63+
const SENT_SPAWN_MAX = 480; // max frames between sentence spawns (~8s)
6364

6465
// Cloud-chamber streak tunables
6566
const STREAK_SPEED_MIN = 2.0; // cells per frame
@@ -88,8 +89,9 @@
8889
let streakA; // Float32Array — per-cell streak alpha contribution
8990
let streaks = [];
9091

91-
// Active sentences for radiation mode
92-
let activeSentences = [];
92+
// Radiation mode: active sentence overlays
93+
let activeSents = []; // { row, startCol, text, alpha, hold }
94+
let sentSpawnTimer = 0;
9395

9496
// ── Helpers ────────────────────────────────────────────────────────────────
9597

@@ -148,61 +150,48 @@
148150
}
149151
}
150152

151-
// ── Radiation sentences ──────────────────────────────────────────────────
152-
153-
function eligibleSentences() {
154-
return SENTENCES.filter(s => s.length <= cols);
155-
}
153+
// ── Radiation ────────────────────────────────────────────────────────────
156154

157-
function randomSentencePlacement() {
158-
const pool = eligibleSentences();
159-
if (!pool.length) return null;
160-
const text = pool[Math.random() * pool.length | 0];
161-
const col = Math.floor(Math.random() * Math.max(1, cols - text.length));
162-
const row = Math.floor(Math.random() * rows);
163-
return { text, col, row };
155+
function initRadiation() {
156+
activeSents = [];
157+
sentSpawnTimer = (SENT_SPAWN_MIN + Math.random() * (SENT_SPAWN_MAX - SENT_SPAWN_MIN)) | 0;
164158
}
165159

166-
function initSentences() {
167-
activeSentences = [];
168-
const count = Math.max(15, Math.floor(cols * rows / 160));
169-
for (let i = 0; i < count; i++) {
170-
const p = randomSentencePlacement();
171-
if (!p) continue;
172-
activeSentences.push({
173-
...p,
174-
flash: 0,
175-
t: (Math.random() * SENT_CYCLE_MAX) | 0,
176-
});
177-
}
160+
function spawnSentence() {
161+
const eligible = SENTENCES.filter(s => s.length <= cols);
162+
if (!eligible.length) return;
163+
const text = eligible[Math.random() * eligible.length | 0];
164+
const row = Math.floor(Math.random() * rows);
165+
const startCol = Math.floor(Math.random() * Math.max(1, cols - text.length));
166+
activeSents.push({ row, startCol, text, alpha: SENT_ALPHA, hold: SENT_HOLD });
178167
}
179168

180169
function updateRadiation() {
181170
updateStreaks();
182171

183-
const sentMax = Math.max(15, Math.floor(cols * rows / 160));
184-
185-
for (const s of activeSentences) {
186-
// Cycle: relocate + pick new sentence after timer expires
187-
if (--s.t <= 0) {
188-
const p = randomSentencePlacement();
189-
if (p) { s.text = p.text; s.col = p.col; s.row = p.row; }
190-
s.t = (SENT_CYCLE_MIN + Math.random() * (SENT_CYCLE_MAX - SENT_CYCLE_MIN)) | 0;
172+
// Per-cell random char cycling + flashes
173+
for (let i = 0; i < cells.length; i++) {
174+
const c = cells[i];
175+
if (--c.t <= 0) { c.ch = rchar(); c.t = (8 + Math.random() * 70) | 0; }
176+
if (c.flash > 0) {
177+
c.flash -= FLASH_DECAY;
178+
if (c.flash < 0) c.flash = 0;
179+
} else if (Math.random() < FLASH_CHANCE) {
180+
c.flash = FLASH_PEAK;
191181
}
182+
}
192183

193-
// Random flash
194-
if (s.flash > 0) {
195-
s.flash -= FLASH_DECAY;
196-
if (s.flash < 0) s.flash = 0;
197-
} else if (Math.random() < FLASH_CHANCE * s.text.length) {
198-
s.flash = FLASH_PEAK;
199-
}
184+
// Sentence spawn timer
185+
if (--sentSpawnTimer <= 0) {
186+
spawnSentence();
187+
sentSpawnTimer = (SENT_SPAWN_MIN + Math.random() * (SENT_SPAWN_MAX - SENT_SPAWN_MIN)) | 0;
200188
}
201189

202-
// Top up if needed
203-
if (activeSentences.length < sentMax && Math.random() < 0.05) {
204-
const p = randomSentencePlacement();
205-
if (p) activeSentences.push({ ...p, flash: 0, t: (SENT_CYCLE_MIN + Math.random() * (SENT_CYCLE_MAX - SENT_CYCLE_MIN)) | 0 });
190+
// Sentence lifecycle: hold then fade
191+
for (let i = activeSents.length - 1; i >= 0; i--) {
192+
const s = activeSents[i];
193+
if (s.hold > 0) { s.hold--; }
194+
else { s.alpha -= SENT_FADE; if (s.alpha <= 0) activeSents.splice(i, 1); }
206195
}
207196
}
208197

@@ -212,22 +201,35 @@
212201
ctx.textAlign = 'center';
213202
ctx.textBaseline = 'middle';
214203

215-
for (const s of activeSentences) {
204+
// Build sparse overlay map for active sentences
205+
const overlay = new Map();
206+
for (const s of activeSents) {
216207
for (let ci = 0; ci < s.text.length; ci++) {
217-
const col = s.col + ci;
208+
const col = s.startCol + ci;
218209
if (col >= cols) break;
219-
const cx = col * CELL + CELL * 0.5;
220-
const cy = s.row * CELL + CELL * 0.5;
210+
const idx = s.row * cols + col;
211+
if (!overlay.has(idx) || overlay.get(idx).alpha < s.alpha)
212+
overlay.set(idx, { ch: s.text[ci], alpha: s.alpha });
213+
}
214+
}
215+
216+
for (let row = 0; row < rows; row++) {
217+
const cy = row * CELL + CELL * 0.5;
218+
for (let col = 0; col < cols; col++) {
219+
const idx = row * cols + col;
220+
const cx = col * CELL + CELL * 0.5;
221+
const ov = overlay.get(idx);
222+
const c = cells[idx];
221223

222-
let a = BASE_A;
223-
a += s.flash;
224-
a += streakA[s.row * cols + col];
224+
const ch = ov ? ov.ch : c.ch;
225+
let a = ov ? ov.alpha + streakA[idx]
226+
: BASE_A + c.flash + streakA[idx];
225227

226228
if (a < 0.008) continue;
227229
if (a > 0.88) a = 0.88;
228230

229231
ctx.fillStyle = `rgba(0,200,71,${a.toFixed(3)})`;
230-
ctx.fillText(s.text[ci], cx, cy);
232+
ctx.fillText(ch, cx, cy);
231233
}
232234
}
233235
}
@@ -307,7 +309,7 @@
307309
for (let i = 0; i < n; i++) {
308310
cells[i] = { ch: rchar(), t: (Math.random() * 70) | 0, flash: 0 };
309311
}
310-
if (mode === 'radiation') { initStreakBuffer(); initSentences(); }
312+
if (mode === 'radiation') { initStreakBuffer(); initRadiation(); }
311313
if (mode === 'gol') initGol();
312314
}
313315

@@ -377,7 +379,7 @@
377379
btn.addEventListener('click', () => {
378380
mode = mode === 'radiation' ? 'gol' : 'radiation';
379381
if (mode === 'gol') { initGol(); golFrame = 0; }
380-
if (mode === 'radiation') { initStreakBuffer(); initSentences(); }
382+
if (mode === 'radiation') { initStreakBuffer(); initRadiation(); }
381383
buildLabel(btn, TOGGLE_LABELS[mode]);
382384
});
383385
}

0 commit comments

Comments
 (0)