Files
the-matrix/js/loading.js
Alexander Whitestone d759416fc6 feat: ASCII art Timmy logo with progressive loading reveal
Replace plain "INITIALIZING..." text with a block-character ASCII art
TIMMY logo that fills in character-by-character as each init step
completes. Shows a progress bar and percentage counter.

- js/loading.js: new module — ASCII art, initLoadingArt(), setLoadingProgress()
- js/main.js: import loading module; call setLoadingProgress() at each
  init stage (world 10%, effects 30%, agents 50%, controls 70%,
  UI 80%, WebSocket 90%, visitor 95%, done 100%)
- index.html: loading screen now uses <pre id="ascii-logo">, progress
  bar track/fill, percent label, and status message; CSS styles added
  for lit/unlit characters with green glow

Fixes #7

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 14:06:41 -04:00

87 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Loading screen — ASCII art Timmy logo with progressive character reveal.
*
* Usage:
* import { initLoadingArt, setLoadingProgress } from './loading.js';
* initLoadingArt(); // call once on page load
* setLoadingProgress(50, 'MSG'); // 0100, optional status message
*/
const TIMMY_ASCII = `
████████╗██╗███╗ ███╗███╗ ███╗██╗ ██╗
╚══██╔══╝██║████╗ ████║████╗ ████║╚██╗ ██╔╝
██║ ██║██╔████╔██║██╔████╔██║ ╚████╔╝
██║ ██║██║╚██╔╝██║██║╚██╔╝██║ ╚██╔╝
██║ ██║██║ ╚═╝ ██║██║ ╚═╝ ██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
┌───────────────────────────────┐
│ SOVEREIGN AI · SOUL ON BTC │
└───────────────────────────────┘
`.trimStart();
/** All non-whitespace char indices in the ASCII art, randomised for scatter reveal */
let _charSpans = [];
let _totalChars = 0;
/**
* Initialise the loading screen: build character spans for the ASCII art.
* Call once before the first setLoadingProgress().
*/
export function initLoadingArt() {
const logoEl = document.getElementById('ascii-logo');
if (!logoEl) return;
// Build span-per-char markup — whitespace stays as plain text nodes for layout.
const chars = [...TIMMY_ASCII];
let html = '';
let idx = 0;
for (const ch of chars) {
if (ch === '\n') {
html += '\n';
} else if (ch === ' ') {
html += ' ';
} else {
html += `<span class="ac" data-i="${idx}">${ch}</span>`;
idx++;
}
}
_totalChars = idx;
logoEl.innerHTML = html;
// Cache span elements for fast access
_charSpans = Array.from(logoEl.querySelectorAll('.ac'));
}
/**
* Update loading progress.
* @param {number} percent 0100
* @param {string} [msg] Optional status line text
*/
export function setLoadingProgress(percent, msg) {
const pct = Math.max(0, Math.min(100, percent));
// How many chars should be "lit" at this progress level
const litCount = Math.round((_totalChars * pct) / 100);
for (let i = 0; i < _charSpans.length; i++) {
if (i < litCount) {
_charSpans[i].classList.add('lit');
}
}
// Progress bar fill
const bar = document.getElementById('loading-bar-fill');
if (bar) bar.style.width = `${pct}%`;
// Percentage label
const pctEl = document.getElementById('loading-percent');
if (pctEl) pctEl.textContent = `${Math.round(pct)}%`;
// Status message
if (msg) {
const msgEl = document.getElementById('loading-msg');
if (msgEl) msgEl.textContent = msg;
}
}