Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>CMD Ingaze Reveal Animation</title> | |
<style> | |
/* Styles for the animation when embedded */ | |
html, body { /* Apply to html as well for full height */ | |
background-color: #000000; /* Black background for the animation area */ | |
color: #00FF00; /* Bright green text */ | |
font-family: 'Courier New', Courier, monospace; /* Classic CMD font */ | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
height: 100%; /* Make body fill the iframe height */ | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
#cmd-animation-container { | |
padding: 10px; /* Adjusted padding */ | |
border: 2px solid #00AA00; | |
background-color: #080808; | |
box-shadow: 0 0 10px #00FF00; | |
border-radius: 8px; | |
box-sizing: border-box; | |
max-width: calc(100% - 20px); /* Max width with some margin */ | |
margin: 10px; /* Margin around container */ | |
/* Height will be determined by content or flex centering */ | |
} | |
pre#cmd-animation { | |
white-space: pre; | |
text-align: left; | |
font-size: 13px; /* Slightly increased font size */ | |
line-height: 1.2; /* Adjusted line height */ | |
margin: 0; | |
overflow-x: auto; | |
color: #00FF00; /* Explicitly set text color here too */ | |
background-color: #080808; /* Ensure pre background matches container */ | |
} | |
</style> | |
</head> | |
<body> | |
<div id="cmd-animation-container"> | |
<pre id="cmd-animation">Loading Animation...</pre> | |
</div> | |
<script> | |
console.log("SYNC ANIMATION: Script execution started."); // LOG 1 | |
// --- Configuration --- | |
const scene_width = 65; | |
const scene_height = 22; | |
const frameDuration = 150; | |
const MAX_DATA_PARTICLES = 100; | |
const FLOOR_LEVEL = scene_height - 1; | |
// --- ASCII Art Definitions --- | |
const stick_man_art_normal = [" O ", " /|\\ ", " / \\ "]; | |
const stick_man_art_walk_1 = [" O ", " /|\\ ", " / > "]; | |
const stick_man_art_walk_2 = [" O ", " /|\\ ", " < \\ "]; | |
const stick_man_art_surprise = [" \\O/ ", " | ", " / \\ "]; | |
const stick_man_art_gone = [" ", " ", " "]; | |
const linked_in_art = ["+----+", "|i n |", "+----+"]; | |
const linked_in_art_hit = ["x----x", "|BOOM|", "x----x"]; | |
const lightning_strike_segment = "\\"; | |
const explosion_art_frames = [ | |
[" * ", " *#* ", " * "],[" @!% ", " @*#*& ", " X%O "], | |
[" $*~+@ ", "$#@!%*&"," X*O#~ ", " !+%$ "],[" ~ ", " +*% ", " $ "] | |
]; | |
const ingaze_logo_art = [ | |
"IIIII N N GGG AAA ZZZZZ EEEEE", " I NN N G A A Z E ", | |
" I N N N G GG AAAAA Z EEE ", " I N NN G G A A Z E ", | |
"IIIII N N GGG A A ZZZZZ EEEEE" | |
]; | |
const ingaze_logo_width = ingaze_logo_art[0].length; | |
const ingaze_logo_height = ingaze_logo_art.length; | |
let data_particles_state = []; | |
let current_lightning_y_state = -1; | |
function overlay(baseLines, artLines, startX, startY, ignoreSpaces = true) { | |
artLines.forEach((artLine, i) => { | |
const y = startY + i; | |
if (y >= 0 && y < baseLines.length && artLine) { | |
let baseLineArr = baseLines[y].split(''); | |
for (let j = 0; j < artLine.length; j++) { | |
const x = startX + j; | |
if (x >= 0 && x < baseLineArr.length) { | |
if (ignoreSpaces && artLine[j] === ' ') continue; | |
baseLineArr[x] = artLine[j]; | |
} | |
} | |
baseLines[y] = baseLineArr.join(''); | |
} | |
}); | |
} | |
function drawLightningBoltInScene(sceneLines, tipX, tipY, length) { | |
for (let i = 0; i < length; i++) { | |
const y = tipY - i; | |
const x = tipX + (i % 2 === 0 ? 0 : (i % 4 === 1 ? -1 : 1)); | |
if (y >= 0 && y < scene_height && x >= 0 && x < scene_width) { | |
if (sceneLines[y][x] === ' ') { | |
let lineArr = sceneLines[y].split(''); | |
lineArr[x] = lightning_strike_segment; | |
sceneLines[y] = lineArr.join(''); | |
} | |
} | |
} | |
} | |
function buildSceneFrame(stickmanArt, stickmanPos, showLogo, currentLogoArt, currentLogoPos, | |
showLightningBolt, lightningTipX, lightningTipY, lightningLength, | |
currentExplosionArt, explosionPos, | |
showIngazeLogo, ingazeArt, ingazePos) { | |
let sceneLines = Array(scene_height).fill(" ".repeat(scene_width)); | |
data_particles_state.forEach(p => { | |
const px = Math.round(p.x); const py = Math.round(p.y); | |
if (py >= 0 && py < sceneLines.length && px >= 0 && px < scene_width) { | |
if (sceneLines[py][px] === ' ') { | |
let lineArr = sceneLines[py].split(''); lineArr[px] = p.char; sceneLines[py] = lineArr.join(''); | |
} | |
} | |
}); | |
overlay(sceneLines, stickmanArt, stickmanPos.x, stickmanPos.y); | |
if (showLogo) overlay(sceneLines, currentLogoArt, currentLogoPos.x, currentLogoPos.y); | |
if (showLightningBolt && lightningTipY >=0) { | |
drawLightningBoltInScene(sceneLines, lightningTipX, lightningTipY, lightningLength); | |
} | |
if (currentExplosionArt && currentExplosionArt.length > 0) { | |
overlay(sceneLines, currentExplosionArt, explosionPos.x, explosionPos.y, false); | |
} | |
if (showIngazeLogo) overlay(sceneLines, ingazeArt, ingazePos.x, ingazePos.y); | |
return sceneLines.join('\n'); | |
} | |
function spawnNewDataParticle(logoX, logoY, logoWidth) { | |
if (data_particles_state.length >= MAX_DATA_PARTICLES) return; | |
const char = Math.random() > 0.5 ? '1' : '0'; | |
const x = logoX + 1 + Math.floor(Math.random() * (logoWidth - 2)); | |
const y = logoY + linked_in_art.length; | |
const vy = 0.2 + Math.random() * 0.3; | |
data_particles_state.push({ char, x, y, vy, active: true }); | |
} | |
function generateAnimationFrames() { | |
console.log("SYNC ANIMATION: generateAnimationFrames() called."); // LOG | |
const sequence = []; | |
data_particles_state = []; | |
current_lightning_y_state = -1; | |
const stickman_height = stick_man_art_normal.length; | |
const stickman_width = stick_man_art_normal[0].length; | |
const logo_width = linked_in_art[0].length; | |
const logo_height = linked_in_art.length; | |
const stickman_base_y = FLOOR_LEVEL - stickman_height; | |
const logo_base_y = stickman_base_y; | |
const stickman_initial_pos = { x: 2, y: stickman_base_y }; | |
const logo_initial_pos = { x: scene_width - logo_width - 15, y: logo_base_y }; | |
const stickman_walk_target_x = Math.max(stickman_initial_pos.x + 1, logo_initial_pos.x - stickman_width - 1); | |
const ingaze_pos = { x: Math.floor((scene_width - ingaze_logo_width) / 2), y: Math.floor((scene_height - ingaze_logo_height) / 2)}; | |
const explosion_center_x = logo_initial_pos.x + Math.floor(logo_width / 2); | |
const explosion_center_y = logo_initial_pos.y + Math.floor(logo_height / 2); | |
// Phase 0: Stickman Walks | |
const walk_frames = Math.max(10, Math.floor(Math.abs(stickman_walk_target_x - stickman_initial_pos.x) / 1.0) ); | |
let current_stickman_x = stickman_initial_pos.x; | |
const walk_step_x = walk_frames > 0 ? (stickman_walk_target_x - stickman_initial_pos.x) / walk_frames : 0; | |
for (let i = 0; i < walk_frames; i++) { | |
current_stickman_x += walk_step_x; | |
const walk_art = (i % 4 < 2) ? stick_man_art_walk_1 : stick_man_art_walk_2; | |
sequence.push(buildSceneFrame(walk_art, { x: Math.round(current_stickman_x), y: stickman_base_y }, true, linked_in_art, logo_initial_pos, false,0,0,0, [], {}, false, [], {})); | |
} | |
current_stickman_x = stickman_walk_target_x; | |
let current_stickman_pos = { x: Math.round(current_stickman_x), y: stickman_base_y }; | |
// Phase 1: Pause | |
for (let i = 0; i < 3; i++) { sequence.push(buildSceneFrame(stick_man_art_normal, current_stickman_pos, true, linked_in_art, logo_initial_pos, false,0,0,0, [], {}, false, [], {})); } | |
// Phase 2: Shaking & Data Fall | |
let current_logo_pos_phase2 = { ...logo_initial_pos }; | |
const shake_frames = 20; | |
for (let i = 0; i < shake_frames; i++) { | |
let logoAdj = { x: 0, y: 0 }; if (i % 6 < 2) logoAdj = { x: 1, y: 0 }; else if (i % 6 < 4) logoAdj = { x: -1, y: 0 }; | |
current_logo_pos_phase2.x = logo_initial_pos.x + logoAdj.x; | |
if (i % 3 === 0) spawnNewDataParticle(current_logo_pos_phase2.x, current_logo_pos_phase2.y, logo_width); | |
data_particles_state.forEach(p => { if (p.active) { p.y += p.vy; if (p.y >= FLOOR_LEVEL) { p.y = FLOOR_LEVEL; p.vy = 0; p.active = false; } } }); | |
sequence.push(buildSceneFrame(stick_man_art_normal, current_stickman_pos, true, linked_in_art, current_logo_pos_phase2, false,0,0,0, [], {}, false, [], {})); | |
} | |
current_logo_pos_phase2 = { ...logo_initial_pos }; | |
// Phase 3: Data Settles, Stickman Surprised | |
const settle_frames = 8; | |
for (let i = 0; i < settle_frames; i++) { | |
let stickmanArtPhase3 = (i < settle_frames / 2) ? stick_man_art_normal : stick_man_art_surprise; | |
data_particles_state.forEach(p => { if (p.active) { p.y += p.vy; if (p.y >= FLOOR_LEVEL) { p.y = FLOOR_LEVEL; p.vy = 0; p.active = false; } } }); | |
sequence.push(buildSceneFrame(stickmanArtPhase3, current_stickman_pos, true, linked_in_art, logo_initial_pos, false,0,0,0, [], {}, false, [], {})); | |
} | |
// Phase 4: Lightning Strike | |
const lightning_target_y = logo_initial_pos.y; const lightning_strike_frames = lightning_target_y + 2; | |
const lightning_bolt_length = 4; const lightning_tip_x_strike = logo_initial_pos.x + Math.floor(logo_width / 2); | |
for (let i = 0; i < lightning_strike_frames; i++) { | |
current_lightning_y_state = i; let logo_art_to_use = linked_in_art; | |
if (current_lightning_y_state >= lightning_target_y) { logo_art_to_use = linked_in_art_hit; current_lightning_y_state = lightning_target_y; } | |
sequence.push(buildSceneFrame(stick_man_art_surprise, current_stickman_pos, true, logo_art_to_use, logo_initial_pos, true, lightning_tip_x_strike, current_lightning_y_state, lightning_bolt_length, [], {}, false, [], {})); | |
} | |
current_lightning_y_state = -1; | |
// Phase 5: Explosion | |
const explosion_duration_per_frame = 2; let stickman_art_explosion = stick_man_art_surprise; | |
for (let i = 0; i < explosion_art_frames.length; i++) { | |
const explosion_art = explosion_art_frames[i]; | |
const explosion_art_width = Math.max(...explosion_art.map(l => l.length)); const explosion_art_height = explosion_art.length; | |
const current_explosion_pos = { x: explosion_center_x - Math.floor(explosion_art_width / 2), y: explosion_center_y - Math.floor(explosion_art_height / 2) }; | |
for (let j = 0; j < explosion_duration_per_frame; j++) { | |
if (i === 0 && j === 0) { data_particles_state = []; stickman_art_explosion = stick_man_art_gone; } | |
sequence.push(buildSceneFrame(stickman_art_explosion, current_stickman_pos, false, [], {}, false,0,0,0, explosion_art, current_explosion_pos, false, [], {})); | |
} | |
} | |
// Phase 6: "Ingaze" Logo Reveal | |
const ingaze_reveal_pause_frames = 4; | |
for(let i=0; i < ingaze_reveal_pause_frames; i++) { sequence.push(buildSceneFrame(stick_man_art_gone, current_stickman_pos, false, [], {}, false,0,0,0, [], {}, false, [], {}));} | |
const ingaze_display_frames = 25; | |
for (let i = 0; i < ingaze_display_frames; i++) { sequence.push(buildSceneFrame(stick_man_art_gone, current_stickman_pos, false, [], {}, false,0,0,0, [], {}, true, ingaze_logo_art, ingaze_pos));} | |
console.log(`SYNC ANIMATION: Generated ${sequence.length} frames.`); // LOG | |
return sequence; | |
} | |
const animationElement = document.getElementById('cmd-animation'); | |
let currentFrameIndex = 0; | |
let animationIntervalId; | |
let allAnimationFrames = []; | |
function runAnimation() { | |
console.log("SYNC ANIMATION: runAnimation() called."); // LOG | |
if (!animationElement) { | |
console.error("SYNC ANIMATION ERROR: Animation element 'cmd-animation' not found in runAnimation."); | |
return; | |
} | |
if (allAnimationFrames.length === 0) { | |
console.error("SYNC ANIMATION ERROR: Animation frames are empty. Cannot play animation."); | |
animationElement.textContent = "Error: No frames."; | |
return; | |
} | |
animationIntervalId = setInterval(() => { | |
if (allAnimationFrames[currentFrameIndex]) { | |
animationElement.textContent = allAnimationFrames[currentFrameIndex]; | |
} | |
currentFrameIndex++; | |
if (currentFrameIndex >= allAnimationFrames.length) { | |
currentFrameIndex = 0; // Loop animation | |
} | |
}, frameDuration); | |
console.log("SYNC ANIMATION: Animation interval started."); // LOG | |
} | |
function initializeAnimation() { | |
console.log("SYNC ANIMATION: initializeAnimation() called."); // LOG | |
if (!animationElement) { | |
console.warn("SYNC ANIMATION WARNING: Animation element not ready yet in initializeAnimation."); | |
// It might be too early, try again shortly | |
// setTimeout(initializeAnimation, 100); // Be careful with recursive setTimeout | |
return; | |
} | |
try { | |
console.log("SYNC ANIMATION: Attempting to generate frames..."); // LOG | |
allAnimationFrames = generateAnimationFrames(); | |
if (allAnimationFrames.length > 0 && animationElement) { | |
animationElement.textContent = allAnimationFrames[0]; | |
console.log("SYNC ANIMATION: First frame set. Calling runAnimation()."); // LOG | |
runAnimation(); | |
} else if (animationElement) { | |
animationElement.textContent = "Error: Could not generate animation frames."; | |
console.error("SYNC ANIMATION ERROR: Could not generate frames or animationElement is null."); // LOG | |
} | |
} catch (error) { | |
console.error("SYNC ANIMATION ERROR: Error during animation generation or initial play:", error); // LOG | |
if(animationElement) animationElement.textContent = "Error initializing: " + error.message; | |
} | |
} | |
console.log("SYNC ANIMATION: Adding DOMContentLoaded listener."); // LOG | |
if (document.readyState === "complete" || document.readyState === "interactive") { | |
console.log("SYNC ANIMATION: DOM already loaded or interactive. Calling initializeAnimation via setTimeout."); // LOG | |
setTimeout(initializeAnimation, 0); | |
} else { | |
console.log("SYNC ANIMATION: DOM not yet loaded. Adding event listener for DOMContentLoaded."); // LOG | |
document.addEventListener('DOMContentLoaded', () => { | |
console.log("SYNC ANIMATION: DOMContentLoaded event fired."); // LOG | |
initializeAnimation(); | |
}); | |
} | |
window.addEventListener('unload', () => { | |
console.log("SYNC ANIMATION: Unload event. Clearing interval."); // LOG | |
if (animationIntervalId) { | |
clearInterval(animationIntervalId); | |
} | |
}); | |
console.log("SYNC ANIMATION: Script execution finished."); // LOG | |
</script> | |
</body> | |
</html> | |