← Fiestas y NavidadObjeto 3Dfogon/globos
Globos
Arrastrá para girarlo// «Globos» · gpt-6-sol (medium)
// A bunch of six shiny party balloons in red, yellow, blue, green, pink and purple floating at different heights, each egg-shaped with a small knot at the bottom and a light highlight, their thin white strings gathered down to a small gift-box weight on the floor.
// Gift-box weight
box(20, 21, 0, 28, 27, 4, "#d73343");
box(20, 21, 4, 28, 27, 5, "#f04b56");
box(20, 21, 0, 20, 27, 3, "#ad2537");
box(21, 21, 0, 27, 21, 3, "#ef4050");
// Gold ribbon and bow
box(23, 20, 0, 25, 28, 5, "#f5c950");
box(20, 23, 0, 28, 24, 5, "#f5c950");
box(23, 20, 2, 25, 20, 4, "#ffe58a");
box(21, 23, 5, 27, 24, 5, "#ffe58a");
box(23, 22, 6, 25, 24, 7, "#ffdf70");
box(20, 22, 6, 22, 24, 7, "#ffdf70");
box(26, 22, 6, 28, 24, 7, "#ffdf70");
box(22, 22, 7, 26, 24, 8, "#fff0a6");
const balloons = [
{ x: 9, y: 20, z: 32, c: ["#b72236", "#f0444e", "#ff6970"] }, // red
{ x: 21, y: 29, z: 37, c: ["#d99620", "#ffd348", "#ffeb86"] }, // yellow
{ x: 38, y: 20, z: 32, c: ["#2365b9", "#3999eb", "#77c8ff"] }, // blue
{ x: 11, y: 32, z: 39, c: ["#258552", "#46c878", "#86eaa0"] }, // green
{ x: 25, y: 15, z: 29, c: ["#c05291", "#f28bc2", "#ffc0df"] }, // pink
{ x: 39, y: 31, z: 39, c: ["#6849aa", "#a17be2", "#cbb2ff"] } // purple
];
part("balloons", [24, 24, 7]);
// Draw strings first so the balloon bodies sit visibly in front of them.
for (const b of balloons) {
const kx = b.x, ky = b.y, kz = b.z - 8;
line(24, 24, 8, 24 + (kx - 24) * 0.27, 24 + (ky - 24) * 0.27,
15, 0, "#e7e8f0");
line(24 + (kx - 24) * 0.27, 24 + (ky - 24) * 0.27, 15,
kx - (kx - 24) * 0.12, ky - (ky - 24) * 0.12,
kz - 4, 0, "#ffffff");
line(kx - (kx - 24) * 0.12, ky - (ky - 24) * 0.12,
kz - 4, kx, ky, kz, 0, "#e7e8f0");
}
for (const b of balloons) {
const rx = 4.5, ry = 3.7, rz = 6;
// Rounded upper body, with a brighter upper/front face.
for (let z = b.z - 5; z <= b.z + 6; z++) {
for (let y = b.y - 4; y <= b.y + 4; y++) {
for (let x = b.x - 5; x <= b.x + 5; x++) {
const d = ((x - b.x) / rx) ** 2 +
((y - b.y) / ry) ** 2 +
((z - b.z) / rz) ** 2;
if (d > 1) continue;
let color = b.c[1];
if (x > b.x + 2 || z < b.z - 2) color = b.c[0];
if (z >= b.z + 1 && x <= b.x + 1 && y <= b.y)
color = b.c[2];
set(x, y, z, color);
}
}
}
// Tapered neck and the little tied knot.
ellipsoid(b.x, b.y, b.z - 6, 2, 2, 1, b.c[1]);
box(b.x - 1, b.y - 1, b.z - 7, b.x + 1, b.y + 1, b.z - 7, b.c[0]);
box(b.x - 1, b.y - 1, b.z - 8, b.x + 1, b.y + 1, b.z - 8, b.c[2]);
// Curved, toy-like glint on the front-left surface.
for (let z = b.z; z <= b.z + 4; z++) {
const x = b.x - (z >= b.z + 3 ? 1 : 2);
const inside = 1 - ((x - b.x) / rx) ** 2 -
((z - b.z) / rz) ** 2;
if (inside <= 0) continue;
const y = b.y - Math.floor(ry * Math.sqrt(inside));
set(x, y, z, "#ffffff");
}
set(b.x - 3, b.y - 2, b.z - 1, b.c[2]);
}
animate("balloons", { type: "swing", axis: "y", speed: 1.5, amplitude: 0.15 });
animate("balloons", { type: "bob", axis: "z", speed: 2, amplitude: 1 });import { draw } from "./assets/voxel";
import { globos } from "./assets/globos";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, globos, 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 globos
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["globos"] })
# Queda en client/assets/globos.ts
# https://fogon.page/object/globos