← Pirates and sea3D assetfogon/barril-de-polvora
Barril de pólvora
Drag to turn it// «Barril de pólvora» · gpt-6-sol (medium)
// A wooden gunpowder barrel lying on its side on a small stand, warm brown staves with black iron hoops, a white skull painted on the front and a trail of black powder spilling from a small hole.
// Wooden gunpowder barrel, lying with its painted end toward the viewer.
const CX = 24, CZ = 18;
const wood = ["#75401f", "#8e5127", "#a76431", "#bd7840"];
const iron = "#20252a";
const ironLight = "#43494b";
// Two chunky wooden cradles.
for (const y of [17, 32]) {
box(12, y - 2, 0, 36, y + 2, 2, "#674022");
box(13, y - 1, 3, 35, y + 1, 4, "#986032");
box(13, y - 1, 5, 16, y + 1, 10, "#80502b");
box(32, y - 1, 5, 35, y + 1, 10, "#80502b");
line(16, y, 5, 20, y, 8, 1, "#a96b37");
line(32, y, 5, 28, y, 8, 1, "#a96b37");
box(12, y - 2, 1, 36, y - 2, 1, "#b67a42");
}
// Solid, gently bulging barrel. Longitudinal color changes suggest staves.
for (let y = 12; y <= 38; y++) {
const bulge = Math.sin(Math.PI * (y - 12) / 26);
const radius = 10.5 + 2.0 * bulge;
for (let x = 11; x <= 37; x++) {
for (let z = 5; z <= 31; z++) {
const dx = x - CX, dz = z - CZ;
const d = Math.hypot(dx, dz);
if (d > radius) continue;
const angle = (Math.atan2(dz, dx) + Math.PI) / (2 * Math.PI);
const stave = Math.floor(angle * 14);
const edge = angle * 14 - stave;
let shade = z >= CZ + 4 ? 3 : z >= CZ - 3 ? 2 : 1;
if (stave % 4 === 0) shade--;
if (d > radius - 2 && (edge < 0.045 || edge > 0.955)) shade = 0;
if (d > radius - 1.5 && rand() < 0.045) shade = Math.max(0, shade - 1);
set(x, y, z, wood[Math.max(0, shade)]);
}
}
}
// Iron hoops wrap all the way around the barrel.
for (const [y0, y1] of [[14, 16], [24, 25], [34, 36]]) {
for (let y = y0; y <= y1; y++) {
const radius = 10.5 + 2 * Math.sin(Math.PI * (y - 12) / 26);
for (let x = 10; x <= 38; x++) {
for (let z = 4; z <= 32; z++) {
const d = Math.hypot(x - CX, z - CZ);
if (d >= radius - 1.35 && d <= radius + 0.55) {
set(x, y, z, z > 24 && y === y0 ? ironLight : iron);
}
}
}
}
for (const x of [17, 24, 31]) {
const z = Math.round(CZ + Math.sqrt(Math.max(0, 11 * 11 - (x - CX) ** 2)));
set(x, y0, z, "#78807a");
}
}
// Front wooden end, dark rim, and subtle circular grain.
for (let x = 13; x <= 35; x++) {
for (let z = 7; z <= 29; z++) {
const d = Math.hypot(x - CX, z - CZ);
if (d > 10.4) continue;
set(x, 10, z, z > 20 ? "#ad6c36" : "#8e542b");
set(x, 9, z,
d > 9.1 ? iron :
d > 7.8 ? "#704021" :
z > 21 ? "#ad713b" : "#95592d");
}
}
// End-cap plank joints, mostly visible around the painted emblem.
for (const x of [19, 24, 29]) {
for (let z = 10; z <= 26; z++) {
if (Math.hypot(x - CX, z - CZ) < 8.7 && (z < 14 || z > 24)) {
set(x, 8, z, "#704526");
}
}
}
// White crossed bones, with rounded tips.
line(18, 8, 14, 30, 8, 25, 0, "#f5ebd1");
line(18, 8, 25, 30, 8, 14, 0, "#f5ebd1");
for (const [x, z] of [[18, 14], [30, 25], [18, 25], [30, 14]]) {
set(x - 1, 8, z, "#f5ebd1");
set(x, 8, z + 1, "#fff9e5");
}
// Bold little skull painted over the bones.
ellipsoid(24, 7, 21, 4, 0, 4, "#fff7dd");
box(21, 7, 16, 27, 7, 19, "#f4e7c8");
box(22, 6, 16, 26, 6, 17, "#fff9e6");
box(21, 6, 20, 22, 6, 22, "#30312e");
box(26, 6, 20, 27, 6, 22, "#30312e");
set(24, 6, 19, "#30312e");
set(23, 6, 18, "#e5d6b7");
set(25, 6, 18, "#e5d6b7");
for (const x of [22, 24, 26]) set(x, 5, 16, "#9d8e75");
// Small scorched powder hole, offset below the skull.
box(28, 7, 11, 30, 7, 13, "#603923");
set(29, 6, 12, "#14191a");
set(29, 6, 11, "#1c2020");
set(30, 6, 12, "#222526");
set(28, 6, 13, "#bd8144");
// Black powder dribbles down the end and scatters across the ground.
line(29, 6, 11, 30, 7, 7, 0, "#171b1b");
line(30, 7, 7, 31, 8, 2, 0, "#1c2020");
sphere(31, 8, 0, 1.5, "#202321");
for (const [x, y] of [
[31, 7], [31, 6], [30, 5], [30, 4], [29, 4], [29, 3],
[28, 3], [27, 2], [32, 6], [30, 2], [26, 3], [33, 7]
]) {
set(x, y, 0, "#1b1e1d");
if (rand() < 0.5) set(x + 1, y, 0, "#30312b");
}import { draw } from "./assets/voxel";
import { barrilDePolvora } from "./assets/barril-de-polvora";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, barrilDePolvora, 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 barril-de-polvora
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["barril-de-polvora"] })
# It lands in client/assets/barril-de-polvora.ts
# https://fogon.page/object/barril-de-polvora