← BásicoObjeto 3Dfogon/trompeta
Trompeta
Arrastrá para girarlo// «Trompeta» · gpt-6-sol (medium)
// Trumpet («Trompeta»).
// Move the entire trumpet down ten blocks so its lowest blocks rest at z = 0.
function buildTrumpet(rawSet, rawSphere, rawCylinder, rawLine, rawBox) {
const set = (x, y, z, color) => rawSet(x, y, z - 10, color);
const sphere = (x, y, z, r, color) => rawSphere(x, y, z - 10, r, color);
const cylinder = (x, y, z, r, h, color, axis) =>
rawCylinder(x, y, z - 10, r, h, color, axis);
const line = (x0, y0, z0, x1, y1, z1, r, color) =>
rawLine(x0, y0, z0 - 10, x1, y1, z1 - 10, r, color);
const box = (x0, y0, z0, x1, y1, z1, color) =>
rawBox(x0, y0, z0 - 10, x1, y1, z1 - 10, color);
const gold = "#d9a43a";
const light = "#f3c95f";
const bright = "#ffe18a";
const shadow = "#a97224";
const dark = "#78501d";
function pipeX(x0, x1, y, z, r = 1.6) {
for (let x = x0; x <= x1; x++) {
for (let yy = Math.floor(y - r); yy <= Math.ceil(y + r); yy++) {
for (let zz = Math.floor(z - r); zz <= Math.ceil(z + r); zz++) {
if ((yy - y) ** 2 + (zz - z) ** 2 > r * r + 0.4) continue;
let c = yy < y ? light : gold;
if (zz > z) c = bright;
if (zz < z - 0.5 || yy > y + 0.5) c = shadow;
if (rand() < 0.055) c = light;
set(x, yy, zz, c);
}
}
}
}
function pipeY(x, y0, y1, z, r = 1.5) {
line(x, y0, z, x, y1, z, r, gold);
line(x, y0, z + 1, x, y1, z + 1, 0, light);
}
// Long, parallel runs of tubing and the curved return at the narrow end.
pipeX(9, 36, 17, 25, 1.65);
pipeX(10, 34, 29, 21, 1.65);
pipeX(13, 35, 25, 27, 1.45);
pipeX(9, 32, 20, 20, 1.2);
for (let i = 0; i <= 12; i++) {
const t = Math.PI * i / 12;
const y = 17 + 12 * (i / 12);
const x = 8 - 2.7 * Math.sin(t);
const z = 23 - 2 * (i / 12);
sphere(x, y, z, 1.65, i < 5 ? light : gold);
set(Math.round(x), Math.round(y), Math.round(z + 1), bright);
}
// Silvery mouthpiece.
pipeX(5, 10, 29, 21, 1.15);
cylinder(4, 29, 21, 2, 2, "#d7d9c9", "x");
cylinder(5, 29, 21, 1, 3, "#a5aaa1", "x");
set(4, 28, 22, "#f3f0dc");
// Three upright piston-valve casings.
for (const x of [18, 24, 30]) {
cylinder(x, 22, 11, 2.5, 17, shadow);
cylinder(x, 21, 12, 2.15, 17, gold);
box(x - 1, 19, 13, x, 19, 27, light);
box(x + 2, 21, 13, x + 2, 23, 26, dark);
cylinder(x, 22, 10, 3, 2, gold);
cylinder(x, 21, 10, 2, 1, bright);
cylinder(x, 22, 27, 3, 2, light);
cylinder(x, 22, 29, 1, 4, shadow);
cylinder(x, 22, 33, 3, 2, gold);
cylinder(x, 21, 35, 2.5, 1, "#f7df9e");
box(x - 2, 19, 34, x + 1, 19, 34, bright);
for (const z of [15, 25]) {
cylinder(x, 22, z, 3, 1, light);
set(x + 2, 23, z, shadow);
}
}
// Connecting bends between and below the pistons.
for (const x of [15, 21, 27, 33]) {
pipeY(x, 23, 29, 18, 1.1);
line(x, 28, 18, x + 2, 29, 20, 1.1, light);
}
for (const x of [19, 25, 31]) {
line(x, 19, 25, x + 2, 17, 25, 1, bright);
}
pipeX(12, 35, 16, 23, 1.2);
// Rising bell throat.
for (let x = 31; x <= 36; x++) {
const z = 26 + (x - 31) * 0.25;
pipeX(x, x, 24, z, 2.6 + (x - 31) * 0.38);
}
// Wide, hollow, faceted brass bell.
const profile = [4.4, 5.0, 5.8, 6.7, 7.5, 8.3, 9.0, 9.6, 10.0, 10.2, 10.1, 9.8];
const cy = 24, cz = 28;
for (let i = 0; i < profile.length; i++) {
const x = 33 + i;
const outer = profile[i];
const inner = Math.max(2, outer - (i < 7 ? 2.7 : 2.1));
for (let y = Math.floor(cy - outer); y <= Math.ceil(cy + outer); y++) {
for (let z = Math.floor(cz - outer); z <= Math.ceil(cz + outer); z++) {
const d = Math.hypot(y - cy, z - cz);
if (d > outer + 0.25 || d < inner) continue;
let c = gold;
if (z > cz + 2 || y < cy - 3) c = light;
if (z > cz + 6 && y < cy) c = bright;
if (z < cz - 3 || y > cy + 3) c = shadow;
if (i % 3 === 0 && d > outer - 1.1) c = z >= cz ? bright : gold;
if (rand() < 0.075) c = z >= cz ? "#f8d978" : "#bb842c";
set(x, y, z, c);
}
}
}
// Recessed interior and bright rolled lip.
for (let y = 16; y <= 32; y++) {
for (let z = 20; z <= 36; z++) {
const d = Math.hypot(y - cy, z - cz);
if (d < 7.7) {
set(42, y, z, d < 4.5 ? "#946321" : "#b78330");
if (z > cz && rand() < 0.3) set(42, y, z, "#cb9b43");
}
}
}
for (let y = 14; y <= 34; y++) {
for (let z = 18; z <= 38; z++) {
const d = Math.hypot(y - cy, z - cz);
if (d >= 8.0 && d <= 10.25) {
set(44, y, z, z >= cz || y < cy ? bright : gold);
if (d >= 9.35) set(43, y, z, z < cz ? shadow : light);
}
}
}
}
buildTrumpet(set, sphere, cylinder, line, box);import { draw } from "./assets/voxel";
import { trompeta } from "./assets/trompeta";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, trompeta, 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 trompeta
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["trompeta"] })
# Queda en client/assets/trompeta.ts
# https://fogon.page/object/trompeta