← Basics3D assetfogon/tambor
Tambor
Drag to turn it// «Tambor» · gpt-6-sol (medium)
// Drum («Tambor»).
const cx = 24, cy = 24;
const red = ["#782c2b", "#913633", "#a84038", "#b94c3d"];
const metal = ["#66737a", "#88969c", "#b8c2c3", "#e0e5df"];
function rimColor(x, y, z) {
const front = y < cy;
if (z <= 1) return front ? metal[0] : metal[1];
if (z >= 27) return rand() < 0.22 ? metal[2] : metal[3];
return front
? (rand() < 0.24 ? metal[1] : metal[2])
: (rand() < 0.3 ? metal[2] : metal[3]);
}
// Solid, stave-built red body.
for (let x = 7; x <= 41; x++) {
for (let y = 7; y <= 41; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r > 15.5) continue;
const a = (Math.atan2(y - cy, x - cx) + Math.PI * 2) % (Math.PI * 2);
const stave = (a / (Math.PI * 2)) * 24;
const seam = stave % 1;
for (let z = 3; z <= 25; z++) {
let shade = 2;
if (y > cy + 3) shade = 3;
if (y < cy - 4 || z < 7) shade = 1;
if (r > 13.4 && (seam < 0.095 || seam > 0.94)) shade = 0;
else if (r > 13.4 && rand() < 0.075) shade = Math.max(0, shade - 1);
set(x, y, z, red[shade]);
}
}
}
// Dark gaps immediately beneath the hoops.
for (let x = 7; x <= 41; x++) {
for (let y = 7; y <= 41; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r >= 14.3 && r <= 15.8) {
set(x, y, 5, "#642a29");
set(x, y, 22, "#642a29");
}
}
}
// Chunky lower and upper steel hoops.
for (let x = 6; x <= 42; x++) {
for (let y = 6; y <= 42; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r >= 14.5 && r <= 16.6) {
for (let z = 0; z <= 4; z++) set(x, y, z, rimColor(x, y, z));
for (let z = 23; z <= 27; z++) set(x, y, z, rimColor(x, y, z));
if (r >= 15.2 && r <= 16.4) {
set(x, y, 5, "#89979a");
set(x, y, 22, "#89979a");
}
}
}
}
// Taut ivory drumhead, with a slightly irregular pewter-white border.
for (let x = 8; x <= 40; x++) {
for (let y = 8; y <= 40; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r <= 14.8) {
set(x, y, 27, rand() < 0.065 ? "#e9e8dd" : "#f8f7ee");
if (r < 13.8) set(x, y, 28, rand() < 0.045 ? "#eeede3" : "#fffdf4");
}
if (r > 14.1 && r <= 16.5) {
set(x, y, 28, rand() < 0.2 ? "#b7c3c4" : "#e4e9e5");
}
}
}
// Small, faint scuff on the head.
set(25, 24, 29, "#e8e3d5");
set(26, 24, 29, "#eae5d9");
set(24, 25, 29, "#f0ece0");
// Twelve tall metal tension rods around the barrel.
for (let i = 0; i < 12; i++) {
const a = i * Math.PI / 6 + Math.PI / 12;
const x = Math.round(cx + Math.cos(a) * 16.2);
const y = Math.round(cy + Math.sin(a) * 16.2);
for (let z = 5; z <= 23; z++) {
set(x, y, z, z < 8 ? "#9ca9a9" : "#c3cecc");
if (z >= 7 && z <= 20) set(x + 1, y, z, "#738087");
}
for (let z = 21; z <= 26; z++) {
set(x, y, z, "#e1e7e2");
set(x + 1, y, z, "#9da9aa");
}
for (let z = 2; z <= 6; z++) set(x, y, z, "#b6c2c1");
}
// Broad tuning brackets on the visible front of the shell.
box(11, 11, 10, 14, 13, 17, "#849197");
box(12, 10, 11, 14, 10, 16, "#c5cfcc");
box(34, 11, 10, 37, 14, 17, "#77858c");
box(35, 10, 11, 37, 11, 16, "#c6ceca");
box(36, 9, 14, 37, 10, 15, "#e3e7df");
box(36, 10, 17, 37, 11, 18, "#e2e6de");
set(37, 9, 13, "#56646c");
set(37, 9, 16, "#64727a");
// Narrow raised red panels remain visible between the rods.
for (let x = 12; x <= 36; x++) {
for (let y = 9; y <= 14; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r > 14.9 && r < 16.1 && get(x, y, 15) === undefined) {
set(x, y, 15, "#a33d36");
}
}
}
// Two pale golden wooden drumsticks crossing over the head.
line(3, 29, 33, 44, 29, 33, 1, "#ae782f");
line(5, 29, 34, 42, 29, 34, 0, "#e5b65f");
line(3, 29, 33, 5, 29, 33, 1, "#d4a04b");
line(42, 29, 33, 45, 29, 33, 1, "#bd8738");
set(45, 29, 34, "#e8ba63");
line(17, 9, 30, 30, 42, 34, 1, "#ab7431");
line(18, 11, 31, 30, 41, 35, 0, "#e3b55f");
sphere(17, 9, 30, 1.5, "#d5a04a");
sphere(30, 42, 34, 1.5, "#e6bd69");import { draw } from "./assets/voxel";
import { tambor } from "./assets/tambor";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, tambor, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: its longest side, in px
// angle: turn on the floor, in radians
// t: seconds; if it moves, that animates it# In a terminal, in the game's folder
fogon assets add tambor
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["tambor"] })
# It lands in client/assets/tambor.ts
# https://fogon.page/object/tambor