fogón

← Parties and Christmas3D assetfogon/fuegos-artificiales

Fuegos artificiales

by fogonCC06976 blocks
Fuegos artificialesDrag to turn it
// «Fuegos artificiales» · gpt-6-sol (medium)
// A fireworks launch: a small wooden crate with three thick tubes in red, blue and gold pointing up, and above them three big exploding star bursts of glowing sparks in different colors, held up by thin trails of sparks rising from the tubes.

// Wooden launch crate
box(9, 17, 0, 39, 32, 8, "#a66b39");
box(10, 17, 7, 38, 31, 9, "#d69850");
box(11, 18, 9, 37, 30, 9, "#f1bc70");

// Planks and their darker seams
for (const z of [1, 4, 7]) {
  box(10, 16, z, 38, 16, z + 2, z === 4 ? "#c48647" : "#d99a56");
  box(9, 18, z, 9, 31, z + 2, "#b6783e");
  box(39, 18, z, 39, 31, z + 2, "#a96c37");
}
for (const z of [3, 6]) {
  box(10, 16, z, 38, 16, z, "#754526");
  box(9, 18, z, 9, 31, z, "#754526");
  box(39, 18, z, 39, 31, z, "#754526");
}
for (const x of [12, 36]) {
  box(x, 15, 0, x + 1, 16, 8, "#f0bd68");
  for (const z of [2, 7]) set(x, 14, z, "#fff0b5");
}
box(9, 16, 0, 39, 17, 0, "#734627");
box(10, 16, 8, 38, 16, 8, "#f4c47a");

// Three upright launch tubes
const tubes = [
  { x: 15, body: "#d9393d", light: "#ff7372", dark: "#961e35", rim: "#ffb0a0" },
  { x: 24, body: "#3289d7", light: "#82d5f5", dark: "#22528e", rim: "#c4f5ff" },
  { x: 33, body: "#e9ad30", light: "#ffe17a", dark: "#a66a22", rim: "#fff1ae" }
];
for (const t of tubes) {
  cylinder(t.x, 24, 9, 3, 9, t.dark);
  cylinder(t.x, 24, 11, 3, 6, t.body);
  box(t.x - 1, 21, 11, t.x + 1, 21, 16, t.light);
  cylinder(t.x, 24, 17, 4, 2, t.rim);
  cylinder(t.x, 24, 19, 3, 1, t.dark);
  cylinder(t.x, 24, 19, 2, 1, "#342f45");
  set(t.x, 24, 19, "#fff4ce");
  box(t.x - 2, 20, 12, t.x - 2, 20, 14, "#fff1c3");
}

// Fine rising spark trails, kept separate from the animated bursts
const trails = [
  { x0: 15, x1: 11, y1: 18, top: 29, colors: ["#ffca58", "#ff8055", "#fff0a5"] },
  { x0: 24, x1: 24, y1: 26, top: 33, colors: ["#91e9ff", "#e4fcff", "#50bddb"] },
  { x0: 33, x1: 37, y1: 18, top: 30, colors: ["#ffe58a", "#ffb4de", "#fff5cf"] }
];
for (const t of trails) {
  for (let z = 20; z <= t.top; z++) {
    const f = (z - 20) / (t.top - 20);
    const x = Math.round(t.x0 + (t.x1 - t.x0) * f);
    const y = Math.round(24 + (t.y1 - 24) * f);
    if (z % 4 !== 1) set(x, y, z, t.colors[z % 3]);
    if (z % 3 === 0) {
      set(x - 1, y - 1, z + 1, t.colors[(z + 1) % 3]);
      set(x + 1, y, z - 1, t.colors[(z + 2) % 3]);
    }
  }
}

// Each burst is its own flickering part. Rays spread across the front
// silhouette, with shorter rays reaching toward and away from the viewer.
function burst(name, cx, cy, cz, reach, colors) {
  part(name, [cx, cy, cz]);
  sphere(cx, cy, cz, 2, colors[0]);
  sphere(cx, cy - 1, cz + 1, 1, colors[2]);

  const rays = [
    [1, 0, 0], [-1, 0, 0], [0, 0, 1], [0, 0, -1],
    [0.72, 0, 0.72], [-0.72, 0, 0.72],
    [0.72, 0, -0.72], [-0.72, 0, -0.72],
    [0.42, -0.43, 0.8], [-0.42, -0.43, 0.8],
    [0.42, -0.43, -0.8], [-0.42, -0.43, -0.8],
    [0.75, 0.48, 0.35], [-0.75, 0.48, 0.35],
    [0, -0.85, 0.45], [0, -0.85, -0.45]
  ];
  rays.forEach(([dx, dy, dz], i) => {
    const length = reach - (i % 5 === 0 ? 1 : 0);
    const ex = Math.round(cx + dx * length);
    const ey = Math.round(cy + dy * length);
    const ez = Math.round(cz + dz * length);
    line(cx, cy, cz, ex, ey, ez, 0, colors[i % colors.length]);
    sphere(ex, ey, ez, i % 3 === 0 ? 1.4 : 1, colors[(i + 1) % colors.length]);

    // Little detached glints make the explosions look lively.
    if (i % 2 === 0) {
      set(ex + (dx >= 0 ? 1 : -1), ey - 1, ez + (dz >= 0 ? 1 : -1), colors[2]);
    }
  });
  animate(name, {
    type: "colors",
    palette: colors,
    pattern: "flicker",
    glow: 1
  });
}

burst("redBurst", 11, 18, 33, 7, ["#ff4949", "#ff9a3e", "#ffe766", "#fff3b2"]);
burst("blueBurst", 24, 26, 38, 7, ["#409aff", "#51e4ef", "#f4ffff", "#acebff"]);
burst("pinkBurst", 37, 18, 34, 7, ["#ff86cf", "#bc83f5", "#ffda69", "#fff0ba"]);