← Fiestas y NavidadObjeto 3Dfogon/fuegos-artificiales
Fuegos artificiales
Arrastrá para girarlo// «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"]);import { draw } from "./assets/voxel";
import { fuegosArtificiales } from "./assets/fuegos-artificiales";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, fuegosArtificiales, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: lo que mide en px su lado más largo
// angle: giro sobre el piso, en radianes
// t: segundos; si se mueve, se anima solo con eso# En una terminal, en la carpeta del juego
fogon assets add fuegos-artificiales
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["fuegos-artificiales"] })
# Queda en client/assets/fuegos-artificiales.ts
# https://fogon.page/object/fuegos-artificiales