GuglielmoTor commited on
Commit
5455f54
·
verified ·
1 Parent(s): c61d44a

Update sync_animation.html

Browse files
Files changed (1) hide show
  1. sync_animation.html +83 -115
sync_animation.html CHANGED
@@ -6,39 +6,40 @@
6
  <title>CMD Ingaze Reveal Animation</title>
7
  <style>
8
  /* Styles for the animation when embedded */
9
- body {
10
  background-color: #000000; /* Black background for the animation area */
11
  color: #00FF00; /* Bright green text */
12
  font-family: 'Courier New', Courier, monospace; /* Classic CMD font */
13
- margin: 0; /* Remove default margin */
14
- padding: 0; /* Remove default padding */
15
- overflow: hidden; /* Prevent scrollbars on the body of the iframe content */
16
- display: flex; /* Flex container to center the animation content */
17
- justify-content: center; /* Center horizontally */
18
- align-items: center; /* Center vertically */
19
- min-height: 350px; /* Minimum height for the animation area, adjust as needed */
20
  }
21
 
22
  #cmd-animation-container {
23
- padding: 15px; /* Reduced padding slightly */
24
- border: 2px solid #00AA00; /* Darker green border */
25
- background-color: #080808; /* Slightly off-black for the "screen" */
26
- box-shadow: 0 0 10px #00FF00; /* Green glow effect, slightly reduced */
27
- border-radius: 8px; /* Rounded corners for the container */
28
- box-sizing: border-box; /* Include padding and border in the element's total width and height */
29
- /* width: 100%; */ /* Let it size based on pre content or set a max-width */
30
- max-width: calc(100% - 10px); /* Ensure it fits if iframe has padding */
31
- margin: 5px; /* Add a small margin around the container */
32
  }
33
 
34
  pre#cmd-animation {
35
- white-space: pre; /* Preserve whitespace and newlines */
36
  text-align: left;
37
- font-size: 12px; /* Adjusted for potentially smaller iframe, ensure legibility */
38
- line-height: 1.15; /* Compact lines, slightly increased for readability */
39
  margin: 0;
40
- overflow-x: auto; /* Add scroll if content is wider than container */
41
- /* The height of the pre will be determined by its content (number of lines) */
 
42
  }
43
  </style>
44
  </head>
@@ -48,11 +49,13 @@
48
  </div>
49
 
50
  <script>
 
 
51
  // --- Configuration ---
52
- const scene_width = 65; // Characters
53
- const scene_height = 22; // Lines
54
- const frameDuration = 150; // Milliseconds per frame
55
- const MAX_DATA_PARTICLES = 100; // Reduced slightly
56
  const FLOOR_LEVEL = scene_height - 1;
57
 
58
  // --- ASCII Art Definitions ---
@@ -61,34 +64,24 @@
61
  const stick_man_art_walk_2 = [" O ", " /|\\ ", " < \\ "];
62
  const stick_man_art_surprise = [" \\O/ ", " | ", " / \\ "];
63
  const stick_man_art_gone = [" ", " ", " "];
64
-
65
  const linked_in_art = ["+----+", "|i n |", "+----+"];
66
  const linked_in_art_hit = ["x----x", "|BOOM|", "x----x"];
67
-
68
  const lightning_strike_segment = "\\";
69
-
70
  const explosion_art_frames = [
71
- [" * ", " *#* ", " * "],
72
- [" @!% ", " @*#*& ", " X%O "],
73
- [" $*~+@ ", "$#@!%*&", " X*O#~ ", " !+%$ "],
74
- [" ~ ", " +*% ", " $ "]
75
  ];
76
-
77
  const ingaze_logo_art = [
78
- "IIIII N N GGG AAA ZZZZZ EEEEE",
79
- " I NN N G A A Z E ",
80
- " I N N N G GG AAAAA Z EEE ",
81
- " I N NN G G A A Z E ",
82
  "IIIII N N GGG A A ZZZZZ EEEEE"
83
  ];
84
  const ingaze_logo_width = ingaze_logo_art[0].length;
85
  const ingaze_logo_height = ingaze_logo_art.length;
86
 
87
- // --- Global State (scoped within this script) ---
88
- let data_particles_state = []; // Renamed to avoid conflict if script is ever not isolated
89
  let current_lightning_y_state = -1;
90
 
91
- // --- Helper Functions ---
92
  function overlay(baseLines, artLines, startX, startY, ignoreSpaces = true) {
93
  artLines.forEach((artLine, i) => {
94
  const y = startY + i;
@@ -125,19 +118,14 @@
125
  currentExplosionArt, explosionPos,
126
  showIngazeLogo, ingazeArt, ingazePos) {
127
  let sceneLines = Array(scene_height).fill(" ".repeat(scene_width));
128
-
129
  data_particles_state.forEach(p => {
130
- const px = Math.round(p.x);
131
- const py = Math.round(p.y);
132
  if (py >= 0 && py < sceneLines.length && px >= 0 && px < scene_width) {
133
  if (sceneLines[py][px] === ' ') {
134
- let lineArr = sceneLines[py].split('');
135
- lineArr[px] = p.char;
136
- sceneLines[py] = lineArr.join('');
137
  }
138
  }
139
  });
140
-
141
  overlay(sceneLines, stickmanArt, stickmanPos.x, stickmanPos.y);
142
  if (showLogo) overlay(sceneLines, currentLogoArt, currentLogoPos.x, currentLogoPos.y);
143
  if (showLightningBolt && lightningTipY >=0) {
@@ -147,7 +135,6 @@
147
  overlay(sceneLines, currentExplosionArt, explosionPos.x, explosionPos.y, false);
148
  }
149
  if (showIngazeLogo) overlay(sceneLines, ingazeArt, ingazePos.x, ingazePos.y);
150
-
151
  return sceneLines.join('\n');
152
  }
153
 
@@ -161,25 +148,20 @@
161
  }
162
 
163
  function generateAnimationFrames() {
 
164
  const sequence = [];
165
- data_particles_state = []; // Reset particles for this generation
166
- current_lightning_y_state = -1; // Reset lightning state
167
-
168
  const stickman_height = stick_man_art_normal.length;
169
  const stickman_width = stick_man_art_normal[0].length;
170
  const logo_width = linked_in_art[0].length;
171
  const logo_height = linked_in_art.length;
172
-
173
  const stickman_base_y = FLOOR_LEVEL - stickman_height;
174
  const logo_base_y = stickman_base_y;
175
  const stickman_initial_pos = { x: 2, y: stickman_base_y };
176
- const logo_initial_pos = { x: scene_width - logo_width - 15, y: logo_base_y }; // Adjusted position
177
  const stickman_walk_target_x = Math.max(stickman_initial_pos.x + 1, logo_initial_pos.x - stickman_width - 1);
178
-
179
- const ingaze_pos = {
180
- x: Math.floor((scene_width - ingaze_logo_width) / 2),
181
- y: Math.floor((scene_height - ingaze_logo_height) / 2)
182
- };
183
  const explosion_center_x = logo_initial_pos.x + Math.floor(logo_width / 2);
184
  const explosion_center_y = logo_initial_pos.y + Math.floor(logo_height / 2);
185
 
@@ -187,7 +169,6 @@
187
  const walk_frames = Math.max(10, Math.floor(Math.abs(stickman_walk_target_x - stickman_initial_pos.x) / 1.0) );
188
  let current_stickman_x = stickman_initial_pos.x;
189
  const walk_step_x = walk_frames > 0 ? (stickman_walk_target_x - stickman_initial_pos.x) / walk_frames : 0;
190
-
191
  for (let i = 0; i < walk_frames; i++) {
192
  current_stickman_x += walk_step_x;
193
  const walk_art = (i % 4 < 2) ? stick_man_art_walk_1 : stick_man_art_walk_2;
@@ -197,22 +178,16 @@
197
  let current_stickman_pos = { x: Math.round(current_stickman_x), y: stickman_base_y };
198
 
199
  // Phase 1: Pause
200
- for (let i = 0; i < 3; i++) {
201
- sequence.push(buildSceneFrame(stick_man_art_normal, current_stickman_pos, true, linked_in_art, logo_initial_pos, false,0,0,0, [], {}, false, [], {}));
202
- }
203
 
204
  // Phase 2: Shaking & Data Fall
205
  let current_logo_pos_phase2 = { ...logo_initial_pos };
206
- const shake_frames = 20; // Reduced shake frames
207
  for (let i = 0; i < shake_frames; i++) {
208
- let logoAdj = { x: 0, y: 0 };
209
- if (i % 6 < 2) logoAdj = { x: 1, y: 0 }; else if (i % 6 < 4) logoAdj = { x: -1, y: 0 };
210
  current_logo_pos_phase2.x = logo_initial_pos.x + logoAdj.x;
211
  if (i % 3 === 0) spawnNewDataParticle(current_logo_pos_phase2.x, current_logo_pos_phase2.y, logo_width);
212
-
213
- data_particles_state.forEach(p => {
214
- if (p.active) { p.y += p.vy; if (p.y >= FLOOR_LEVEL) { p.y = FLOOR_LEVEL; p.vy = 0; p.active = false; } }
215
- });
216
  sequence.push(buildSceneFrame(stick_man_art_normal, current_stickman_pos, true, linked_in_art, current_logo_pos_phase2, false,0,0,0, [], {}, false, [], {}));
217
  }
218
  current_logo_pos_phase2 = { ...logo_initial_pos };
@@ -221,74 +196,55 @@
221
  const settle_frames = 8;
222
  for (let i = 0; i < settle_frames; i++) {
223
  let stickmanArtPhase3 = (i < settle_frames / 2) ? stick_man_art_normal : stick_man_art_surprise;
224
- data_particles_state.forEach(p => {
225
- if (p.active) { p.y += p.vy; if (p.y >= FLOOR_LEVEL) { p.y = FLOOR_LEVEL; p.vy = 0; p.active = false; } }
226
- });
227
  sequence.push(buildSceneFrame(stickmanArtPhase3, current_stickman_pos, true, linked_in_art, logo_initial_pos, false,0,0,0, [], {}, false, [], {}));
228
  }
229
 
230
  // Phase 4: Lightning Strike
231
- const lightning_target_y = logo_initial_pos.y;
232
- const lightning_strike_frames = lightning_target_y + 2;
233
- const lightning_bolt_length = 4;
234
- const lightning_tip_x_strike = logo_initial_pos.x + Math.floor(logo_width / 2);
235
-
236
  for (let i = 0; i < lightning_strike_frames; i++) {
237
- current_lightning_y_state = i; // This is the tip's current y as it descends
238
- let logo_art_to_use = linked_in_art;
239
- if (current_lightning_y_state >= lightning_target_y) {
240
- logo_art_to_use = linked_in_art_hit;
241
- current_lightning_y_state = lightning_target_y; // Hold at target
242
- }
243
  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, [], {}));
244
  }
245
- current_lightning_y_state = -1; // Reset lightning state
246
 
247
  // Phase 5: Explosion
248
- const explosion_duration_per_frame = 2;
249
- let stickman_art_explosion = stick_man_art_surprise;
250
  for (let i = 0; i < explosion_art_frames.length; i++) {
251
  const explosion_art = explosion_art_frames[i];
252
- const explosion_art_width = Math.max(...explosion_art.map(l => l.length));
253
- const explosion_art_height = explosion_art.length;
254
- const current_explosion_pos = {
255
- x: explosion_center_x - Math.floor(explosion_art_width / 2),
256
- y: explosion_center_y - Math.floor(explosion_art_height / 2)
257
- };
258
  for (let j = 0; j < explosion_duration_per_frame; j++) {
259
- if (i === 0 && j === 0) {
260
- data_particles_state = [];
261
- stickman_art_explosion = stick_man_art_gone;
262
- }
263
  sequence.push(buildSceneFrame(stickman_art_explosion, current_stickman_pos, false, [], {}, false,0,0,0, explosion_art, current_explosion_pos, false, [], {}));
264
  }
265
  }
266
 
267
  // Phase 6: "Ingaze" Logo Reveal
268
  const ingaze_reveal_pause_frames = 4;
269
- for(let i=0; i < ingaze_reveal_pause_frames; i++) {
270
- sequence.push(buildSceneFrame(stick_man_art_gone, current_stickman_pos, false, [], {}, false,0,0,0, [], {}, false, [], {}));
271
- }
272
  const ingaze_display_frames = 25;
273
- for (let i = 0; i < ingaze_display_frames; i++) {
274
- sequence.push(buildSceneFrame(stick_man_art_gone, current_stickman_pos, false, [], {}, false,0,0,0, [], {}, true, ingaze_logo_art, ingaze_pos));
275
- }
276
  return sequence;
277
  }
278
 
279
- // --- Animation Player ---
280
  const animationElement = document.getElementById('cmd-animation');
281
  let currentFrameIndex = 0;
282
  let animationIntervalId;
283
  let allAnimationFrames = [];
284
 
285
  function runAnimation() {
 
286
  if (!animationElement) {
287
- console.error("Animation element 'cmd-animation' not found.");
288
  return;
289
  }
290
  if (allAnimationFrames.length === 0) {
291
- console.error("Animation frames are empty. Cannot play animation.");
292
  animationElement.textContent = "Error: No frames.";
293
  return;
294
  }
@@ -302,41 +258,53 @@
302
  currentFrameIndex = 0; // Loop animation
303
  }
304
  }, frameDuration);
 
305
  }
306
 
307
  function initializeAnimation() {
 
308
  if (!animationElement) {
309
- // console.warn("Animation element not ready yet in initializeAnimation.");
310
- return; // Element not ready
 
 
311
  }
312
  try {
 
313
  allAnimationFrames = generateAnimationFrames();
314
  if (allAnimationFrames.length > 0 && animationElement) {
315
  animationElement.textContent = allAnimationFrames[0];
 
316
  runAnimation();
317
  } else if (animationElement) {
318
  animationElement.textContent = "Error: Could not generate animation frames.";
 
319
  }
320
  } catch (error) {
321
- console.error("Error during animation generation or initial play:", error);
322
  if(animationElement) animationElement.textContent = "Error initializing: " + error.message;
323
  }
324
  }
325
-
326
- // Start animation once DOM is ready
327
  if (document.readyState === "complete" || document.readyState === "interactive") {
328
- // DOM already loaded
329
- setTimeout(initializeAnimation, 0); // Use setTimeout to ensure it runs after current execution block
330
  } else {
331
- document.addEventListener('DOMContentLoaded', initializeAnimation);
 
 
 
 
332
  }
333
 
334
- // Clean up interval when the window/iframe is unloaded
335
  window.addEventListener('unload', () => {
 
336
  if (animationIntervalId) {
337
  clearInterval(animationIntervalId);
338
  }
339
  });
 
340
  </script>
341
  </body>
342
  </html>
 
6
  <title>CMD Ingaze Reveal Animation</title>
7
  <style>
8
  /* Styles for the animation when embedded */
9
+ html, body { /* Apply to html as well for full height */
10
  background-color: #000000; /* Black background for the animation area */
11
  color: #00FF00; /* Bright green text */
12
  font-family: 'Courier New', Courier, monospace; /* Classic CMD font */
13
+ margin: 0;
14
+ padding: 0;
15
+ overflow: hidden;
16
+ height: 100%; /* Make body fill the iframe height */
17
+ display: flex;
18
+ justify-content: center;
19
+ align-items: center;
20
  }
21
 
22
  #cmd-animation-container {
23
+ padding: 10px; /* Adjusted padding */
24
+ border: 2px solid #00AA00;
25
+ background-color: #080808;
26
+ box-shadow: 0 0 10px #00FF00;
27
+ border-radius: 8px;
28
+ box-sizing: border-box;
29
+ max-width: calc(100% - 20px); /* Max width with some margin */
30
+ margin: 10px; /* Margin around container */
31
+ /* Height will be determined by content or flex centering */
32
  }
33
 
34
  pre#cmd-animation {
35
+ white-space: pre;
36
  text-align: left;
37
+ font-size: 13px; /* Slightly increased font size */
38
+ line-height: 1.2; /* Adjusted line height */
39
  margin: 0;
40
+ overflow-x: auto;
41
+ color: #00FF00; /* Explicitly set text color here too */
42
+ background-color: #080808; /* Ensure pre background matches container */
43
  }
44
  </style>
45
  </head>
 
49
  </div>
50
 
51
  <script>
52
+ console.log("SYNC ANIMATION: Script execution started."); // LOG 1
53
+
54
  // --- Configuration ---
55
+ const scene_width = 65;
56
+ const scene_height = 22;
57
+ const frameDuration = 150;
58
+ const MAX_DATA_PARTICLES = 100;
59
  const FLOOR_LEVEL = scene_height - 1;
60
 
61
  // --- ASCII Art Definitions ---
 
64
  const stick_man_art_walk_2 = [" O ", " /|\\ ", " < \\ "];
65
  const stick_man_art_surprise = [" \\O/ ", " | ", " / \\ "];
66
  const stick_man_art_gone = [" ", " ", " "];
 
67
  const linked_in_art = ["+----+", "|i n |", "+----+"];
68
  const linked_in_art_hit = ["x----x", "|BOOM|", "x----x"];
 
69
  const lightning_strike_segment = "\\";
 
70
  const explosion_art_frames = [
71
+ [" * ", " *#* ", " * "],[" @!% ", " @*#*& ", " X%O "],
72
+ [" $*~+@ ", "$#@!%*&"," X*O#~ ", " !+%$ "],[" ~ ", " +*% ", " $ "]
 
 
73
  ];
 
74
  const ingaze_logo_art = [
75
+ "IIIII N N GGG AAA ZZZZZ EEEEE", " I NN N G A A Z E ",
76
+ " I N N N G GG AAAAA Z EEE ", " I N NN G G A A Z E ",
 
 
77
  "IIIII N N GGG A A ZZZZZ EEEEE"
78
  ];
79
  const ingaze_logo_width = ingaze_logo_art[0].length;
80
  const ingaze_logo_height = ingaze_logo_art.length;
81
 
82
+ let data_particles_state = [];
 
83
  let current_lightning_y_state = -1;
84
 
 
85
  function overlay(baseLines, artLines, startX, startY, ignoreSpaces = true) {
86
  artLines.forEach((artLine, i) => {
87
  const y = startY + i;
 
118
  currentExplosionArt, explosionPos,
119
  showIngazeLogo, ingazeArt, ingazePos) {
120
  let sceneLines = Array(scene_height).fill(" ".repeat(scene_width));
 
121
  data_particles_state.forEach(p => {
122
+ const px = Math.round(p.x); const py = Math.round(p.y);
 
123
  if (py >= 0 && py < sceneLines.length && px >= 0 && px < scene_width) {
124
  if (sceneLines[py][px] === ' ') {
125
+ let lineArr = sceneLines[py].split(''); lineArr[px] = p.char; sceneLines[py] = lineArr.join('');
 
 
126
  }
127
  }
128
  });
 
129
  overlay(sceneLines, stickmanArt, stickmanPos.x, stickmanPos.y);
130
  if (showLogo) overlay(sceneLines, currentLogoArt, currentLogoPos.x, currentLogoPos.y);
131
  if (showLightningBolt && lightningTipY >=0) {
 
135
  overlay(sceneLines, currentExplosionArt, explosionPos.x, explosionPos.y, false);
136
  }
137
  if (showIngazeLogo) overlay(sceneLines, ingazeArt, ingazePos.x, ingazePos.y);
 
138
  return sceneLines.join('\n');
139
  }
140
 
 
148
  }
149
 
150
  function generateAnimationFrames() {
151
+ console.log("SYNC ANIMATION: generateAnimationFrames() called."); // LOG
152
  const sequence = [];
153
+ data_particles_state = [];
154
+ current_lightning_y_state = -1;
 
155
  const stickman_height = stick_man_art_normal.length;
156
  const stickman_width = stick_man_art_normal[0].length;
157
  const logo_width = linked_in_art[0].length;
158
  const logo_height = linked_in_art.length;
 
159
  const stickman_base_y = FLOOR_LEVEL - stickman_height;
160
  const logo_base_y = stickman_base_y;
161
  const stickman_initial_pos = { x: 2, y: stickman_base_y };
162
+ const logo_initial_pos = { x: scene_width - logo_width - 15, y: logo_base_y };
163
  const stickman_walk_target_x = Math.max(stickman_initial_pos.x + 1, logo_initial_pos.x - stickman_width - 1);
164
+ const ingaze_pos = { x: Math.floor((scene_width - ingaze_logo_width) / 2), y: Math.floor((scene_height - ingaze_logo_height) / 2)};
 
 
 
 
165
  const explosion_center_x = logo_initial_pos.x + Math.floor(logo_width / 2);
166
  const explosion_center_y = logo_initial_pos.y + Math.floor(logo_height / 2);
167
 
 
169
  const walk_frames = Math.max(10, Math.floor(Math.abs(stickman_walk_target_x - stickman_initial_pos.x) / 1.0) );
170
  let current_stickman_x = stickman_initial_pos.x;
171
  const walk_step_x = walk_frames > 0 ? (stickman_walk_target_x - stickman_initial_pos.x) / walk_frames : 0;
 
172
  for (let i = 0; i < walk_frames; i++) {
173
  current_stickman_x += walk_step_x;
174
  const walk_art = (i % 4 < 2) ? stick_man_art_walk_1 : stick_man_art_walk_2;
 
178
  let current_stickman_pos = { x: Math.round(current_stickman_x), y: stickman_base_y };
179
 
180
  // Phase 1: Pause
181
+ 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, [], {})); }
 
 
182
 
183
  // Phase 2: Shaking & Data Fall
184
  let current_logo_pos_phase2 = { ...logo_initial_pos };
185
+ const shake_frames = 20;
186
  for (let i = 0; i < shake_frames; i++) {
187
+ 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 };
 
188
  current_logo_pos_phase2.x = logo_initial_pos.x + logoAdj.x;
189
  if (i % 3 === 0) spawnNewDataParticle(current_logo_pos_phase2.x, current_logo_pos_phase2.y, logo_width);
190
+ 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; } } });
 
 
 
191
  sequence.push(buildSceneFrame(stick_man_art_normal, current_stickman_pos, true, linked_in_art, current_logo_pos_phase2, false,0,0,0, [], {}, false, [], {}));
192
  }
193
  current_logo_pos_phase2 = { ...logo_initial_pos };
 
196
  const settle_frames = 8;
197
  for (let i = 0; i < settle_frames; i++) {
198
  let stickmanArtPhase3 = (i < settle_frames / 2) ? stick_man_art_normal : stick_man_art_surprise;
199
+ 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; } } });
 
 
200
  sequence.push(buildSceneFrame(stickmanArtPhase3, current_stickman_pos, true, linked_in_art, logo_initial_pos, false,0,0,0, [], {}, false, [], {}));
201
  }
202
 
203
  // Phase 4: Lightning Strike
204
+ const lightning_target_y = logo_initial_pos.y; const lightning_strike_frames = lightning_target_y + 2;
205
+ const lightning_bolt_length = 4; const lightning_tip_x_strike = logo_initial_pos.x + Math.floor(logo_width / 2);
 
 
 
206
  for (let i = 0; i < lightning_strike_frames; i++) {
207
+ current_lightning_y_state = i; let logo_art_to_use = linked_in_art;
208
+ if (current_lightning_y_state >= lightning_target_y) { logo_art_to_use = linked_in_art_hit; current_lightning_y_state = lightning_target_y; }
 
 
 
 
209
  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, [], {}));
210
  }
211
+ current_lightning_y_state = -1;
212
 
213
  // Phase 5: Explosion
214
+ const explosion_duration_per_frame = 2; let stickman_art_explosion = stick_man_art_surprise;
 
215
  for (let i = 0; i < explosion_art_frames.length; i++) {
216
  const explosion_art = explosion_art_frames[i];
217
+ const explosion_art_width = Math.max(...explosion_art.map(l => l.length)); const explosion_art_height = explosion_art.length;
218
+ const current_explosion_pos = { x: explosion_center_x - Math.floor(explosion_art_width / 2), y: explosion_center_y - Math.floor(explosion_art_height / 2) };
 
 
 
 
219
  for (let j = 0; j < explosion_duration_per_frame; j++) {
220
+ if (i === 0 && j === 0) { data_particles_state = []; stickman_art_explosion = stick_man_art_gone; }
 
 
 
221
  sequence.push(buildSceneFrame(stickman_art_explosion, current_stickman_pos, false, [], {}, false,0,0,0, explosion_art, current_explosion_pos, false, [], {}));
222
  }
223
  }
224
 
225
  // Phase 6: "Ingaze" Logo Reveal
226
  const ingaze_reveal_pause_frames = 4;
227
+ 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, [], {}));}
 
 
228
  const ingaze_display_frames = 25;
229
+ 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));}
230
+
231
+ console.log(`SYNC ANIMATION: Generated ${sequence.length} frames.`); // LOG
232
  return sequence;
233
  }
234
 
 
235
  const animationElement = document.getElementById('cmd-animation');
236
  let currentFrameIndex = 0;
237
  let animationIntervalId;
238
  let allAnimationFrames = [];
239
 
240
  function runAnimation() {
241
+ console.log("SYNC ANIMATION: runAnimation() called."); // LOG
242
  if (!animationElement) {
243
+ console.error("SYNC ANIMATION ERROR: Animation element 'cmd-animation' not found in runAnimation.");
244
  return;
245
  }
246
  if (allAnimationFrames.length === 0) {
247
+ console.error("SYNC ANIMATION ERROR: Animation frames are empty. Cannot play animation.");
248
  animationElement.textContent = "Error: No frames.";
249
  return;
250
  }
 
258
  currentFrameIndex = 0; // Loop animation
259
  }
260
  }, frameDuration);
261
+ console.log("SYNC ANIMATION: Animation interval started."); // LOG
262
  }
263
 
264
  function initializeAnimation() {
265
+ console.log("SYNC ANIMATION: initializeAnimation() called."); // LOG
266
  if (!animationElement) {
267
+ console.warn("SYNC ANIMATION WARNING: Animation element not ready yet in initializeAnimation.");
268
+ // It might be too early, try again shortly
269
+ // setTimeout(initializeAnimation, 100); // Be careful with recursive setTimeout
270
+ return;
271
  }
272
  try {
273
+ console.log("SYNC ANIMATION: Attempting to generate frames..."); // LOG
274
  allAnimationFrames = generateAnimationFrames();
275
  if (allAnimationFrames.length > 0 && animationElement) {
276
  animationElement.textContent = allAnimationFrames[0];
277
+ console.log("SYNC ANIMATION: First frame set. Calling runAnimation()."); // LOG
278
  runAnimation();
279
  } else if (animationElement) {
280
  animationElement.textContent = "Error: Could not generate animation frames.";
281
+ console.error("SYNC ANIMATION ERROR: Could not generate frames or animationElement is null."); // LOG
282
  }
283
  } catch (error) {
284
+ console.error("SYNC ANIMATION ERROR: Error during animation generation or initial play:", error); // LOG
285
  if(animationElement) animationElement.textContent = "Error initializing: " + error.message;
286
  }
287
  }
288
+
289
+ console.log("SYNC ANIMATION: Adding DOMContentLoaded listener."); // LOG
290
  if (document.readyState === "complete" || document.readyState === "interactive") {
291
+ console.log("SYNC ANIMATION: DOM already loaded or interactive. Calling initializeAnimation via setTimeout."); // LOG
292
+ setTimeout(initializeAnimation, 0);
293
  } else {
294
+ console.log("SYNC ANIMATION: DOM not yet loaded. Adding event listener for DOMContentLoaded."); // LOG
295
+ document.addEventListener('DOMContentLoaded', () => {
296
+ console.log("SYNC ANIMATION: DOMContentLoaded event fired."); // LOG
297
+ initializeAnimation();
298
+ });
299
  }
300
 
 
301
  window.addEventListener('unload', () => {
302
+ console.log("SYNC ANIMATION: Unload event. Clearing interval."); // LOG
303
  if (animationIntervalId) {
304
  clearInterval(animationIntervalId);
305
  }
306
  });
307
+ console.log("SYNC ANIMATION: Script execution finished."); // LOG
308
  </script>
309
  </body>
310
  </html>