← MedievalObjeto 3Dfogon/hoguera-de-campamento
Hoguera de campamento
Arrastrá para girarlo// «Hoguera de campamento» · gpt-6-sol (medium)
// A medieval camp bonfire: a ring of grey stones around crossed logs burning with a big tall fire, a spit on two forked sticks over it with a roasting chunk of meat, and two short log stools beside it.
const wood = ["#3b251d", "#513022", "#68402a", "#815232"];
const stone = ["#666762", "#85847b", "#a6a397", "#c3bfb0"];
const iron = "#26272a";
// Scorched earth and scattered embers beneath the bonfire.
for (let i = 0; i < 115; i++) {
const x = 24 + Math.floor((rand() - 0.5) * 17);
const y = 24 + Math.floor((rand() - 0.5) * 17);
const d = Math.hypot(x - 24, y - 24);
if (d < 8.5) set(x, y, 0, rand() < 0.18 ? "#99451e" : "#39312a");
}
// Individual, irregular stones form a low ring.
for (let i = 0; i < 17; i++) {
const a = i * Math.PI * 2 / 17;
const cx = Math.round(24 + Math.cos(a) * (10 + rand() * 0.6));
const cy = Math.round(24 + Math.sin(a) * (10 + rand() * 0.6));
const rx = 1.7 + rand() * 0.5;
const ry = 1.6 + rand() * 0.5;
ellipsoid(cx, cy, 1.5, rx, ry, 1.8, stone[0]);
ellipsoid(cx, cy, 2.2, rx - 0.15, ry - 0.15, 1.25,
rand() < 0.5 ? stone[1] : stone[2]);
if (i % 5 === 1) {
set(cx, cy - 1, 3, stone[3]);
set(cx + 1, cy, 1, "#626f50");
}
}
// Two substantial crossed logs, with end grain and split bark.
function fireLog(x0, y0, x1, y1) {
line(x0, y0, 3, x1, y1, 3, 2, wood[0]);
line(x0, y0, 4, x1, y1, 4, 1, wood[2]);
line(x0, y0, 5, x1, y1, 5, 0, wood[3]);
for (const [x, y] of [[x0, y0], [x1, y1]]) {
ellipsoid(x, y, 3, 1.7, 1.7, 1.8, "#a47445");
set(x, y, 3, "#6e4428");
set(x, y, 4, "#c0945b");
}
}
fireLog(18, 19, 30, 29);
fireLog(30, 19, 18, 29);
for (let i = 0; i < 24; i++) {
const x = 19 + Math.floor(rand() * 11);
const y = 19 + Math.floor(rand() * 11);
if (get(x, y, 5)) set(x, y, 5, rand() < 0.5 ? "#301e1a" : "#a76a32");
}
// Upright forked sticks hold the spit above the flames.
for (const y of [12, 36]) {
line(24, y, 0, 24, y, 19, 1, wood[0]);
line(24, y - 1, 2, 24, y - 1, 17, 0, wood[2]);
line(24, y, 17, 22, y, 22, 0, wood[1]);
line(24, y, 17, 26, y, 22, 0, wood[1]);
set(22, y, 22, "#966641");
set(26, y, 22, "#966641");
box(23, y - 1, 10, 25, y + 1, 11, iron);
set(24, y - 1, 11, "#96938a");
}
// Fire is its own flickering color part.
part("fire", [24, 24, 0]);
for (let z = 5; z <= 31; z++) {
const radius = z < 12 ? 3.7 + z * 0.19 : 6 - (z - 12) * 0.27;
const cx = 24 + Math.sin(z * 0.37) * 1.15;
const cy = 24 + Math.sin(z * 0.24) * 0.7;
for (let x = 16; x <= 32; x++) {
for (let y = 16; y <= 32; y++) {
const d = Math.hypot(x - cx, (y - cy) * 1.12);
if (d < radius + (rand() - 0.5) * 1.15) {
const color = d > radius * 0.77 ? "#af3017"
: d > radius * 0.48 ? "#ed671c"
: z > 22 ? "#ffb12c" : "#ffe06a";
set(x, y, z, color);
}
}
}
}
line(25, 24, 27, 26, 23, 36, 1, "#ffb12c");
line(19, 24, 10, 18, 23, 22, 1, "#ed671c");
line(29, 25, 9, 31, 24, 25, 1, "#ed671c");
line(22, 19, 8, 21, 18, 19, 1, "#ffb12c");
line(26, 29, 9, 27, 30, 20, 1, "#af3017");
animate("fire", {
type: "colors",
palette: ["#a82418", "#ed6419", "#ffae26", "#ffe36d"],
pattern: "flicker",
glow: 0.9
});
part("body");
// Two short log stools, with bark, roots, and visible growth rings.
for (const [cx, cy] of [[8, 25], [40, 26]]) {
for (let x = cx - 5; x <= cx + 5; x++) {
for (let y = cy - 5; y <= cy + 5; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d <= 4.25) {
for (let z = 0; z <= 6; z++) {
let c = d > 3.35 ? wood[0] : wood[1];
if (z > 2 && rand() < 0.15) c = wood[2];
if (d > 3.4 && rand() < 0.12) c = "#28211c";
set(x, y, z, c);
}
const top = d > 3.35 ? "#644027"
: d > 2.55 ? "#c4975b"
: d > 1.75 ? "#81502d"
: d > 0.8 ? "#d3a76c" : "#a47545";
set(x, y, 7, top);
}
}
}
for (const dx of [-3, 3]) {
box(cx + dx - 1, cy - 1, 0, cx + dx + 1, cy + 1, 1, wood[0]);
}
line(cx - 4, cy - 1, 3, cx - 4, cy - 1, 6, 0, "#271d19");
line(cx + 3, cy + 2, 1, cx + 3, cy + 2, 4, 0, "#887044");
}
// Spit, roast, and hand crank all rotate together around the long axle.
part("spit", [24, 24, 22]);
line(24, 10, 22, 24, 38, 22, 0, iron);
for (const y of [14, 17, 32, 35]) {
box(23, y, 21, 25, y, 23, "#393836");
set(24, y - 1, 23, "#a19a86");
}
// An uneven, richly browned roast wrapped around the skewer.
ellipsoid(24, 24, 22, 3.1, 5.1, 2.8, "#74351f");
ellipsoid(25, 24, 22, 2.4, 4.5, 2.4, "#a94e25");
ellipsoid(24, 23, 24, 2.2, 3.6, 0.8, "#c87935");
ellipsoid(22, 26, 21, 0.9, 2.1, 0.9, "#522a20");
for (const y of [21, 25, 28]) {
set(26, y, 23, "#e5a052");
set(23, y, 24, "#54291e");
}
line(24, 18, 22, 24, 19, 22, 1, "#d6b996");
line(24, 29, 22, 24, 30, 22, 1, "#d6b996");
// Bent iron crank and a small wooden grip at the viewer's end.
line(24, 10, 22, 20, 10, 22, 0, iron);
line(20, 10, 22, 20, 10, 18, 0, iron);
line(20, 10, 18, 20, 7, 18, 1, wood[2]);
set(20, 7, 18, wood[3]);
animate("spit", { type: "spin", axis: "y", speed: 1 });import { draw } from "./assets/voxel";
import { hogueraDeCampamento } from "./assets/hoguera-de-campamento";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, hogueraDeCampamento, 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 hoguera-de-campamento
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["hoguera-de-campamento"] })
# Queda en client/assets/hoguera-de-campamento.ts
# https://fogon.page/object/hoguera-de-campamento