← Medieval3D assetfogon/antorchero-de-pared
Antorchero de pared
Drag to turn it// «Antorchero de pared» · gpt-6-sol (medium)
// A piece of dark stone dungeon wall (a flat slab standing upright) with a black iron bracket holding a wooden torch with a big fire flame on top, and soot darkening the stone above the flame.
const mortar = "#302e2d";
const stone = ["#625f5b", "#6b6862", "#74716b", "#7c7870", "#565451"];
const iron = "#17191b";
const ironEdge = "#34373a";
// Thick dungeon-wall slab and its dark mortar face.
box(4, 25, 0, 43, 32, 40, "#494744");
box(4, 23, 0, 43, 24, 40, mortar);
const courses = [0, 7, 14, 21, 28, 35, 41];
for (let row = 0; row < courses.length - 1; row++) {
const bottom = courses[row] + 1;
const top = courses[row + 1] - 1;
let x = row % 2 ? 5 : 8;
// Partial stones at alternating ends make the joints stagger.
if (x > 5) {
box(5, 22, bottom, x - 2, 24, top, stone[(row + 1) % stone.length]);
}
while (x <= 42) {
const width = 8 + Math.floor(rand() * 5);
const end = Math.min(42, x + width - 1);
const color = stone[Math.floor(rand() * stone.length)];
box(x, 22, bottom, end, 24, top, color);
// Uneven, slightly brighter upper edges of hand-cut blocks.
for (let xx = x; xx <= end; xx++) {
if (rand() > 0.13) set(xx, 21, top, "#88847a");
if (rand() < 0.08 && top - bottom > 2)
set(xx, 21, bottom + 1 + Math.floor(rand() * (top - bottom - 1)), "#585650");
}
// A few protruding chips on the front.
if (end - x > 5 && rand() < 0.55)
set(x + 2, 21, bottom + 2, color);
x = end + 2;
}
}
// Visible dressed side edges and a projecting stone coping.
for (let z = 0; z <= 39; z++) {
if (z % 7 !== 0) {
set(4, 24, z, z % 7 === 6 ? "#858078" : "#68655f");
set(43, 24, z, z % 7 === 6 ? "#858078" : "#565450");
}
}
box(3, 22, 40, 44, 33, 41, "#464441");
box(3, 21, 41, 44, 33, 41, "#79756d");
box(4, 21, 40, 43, 22, 40, "#5c5954");
for (let x = 5; x <= 42; x += 8)
box(x, 21, 40, x + 1, 21, 41, "#302f2e");
// Scattered moss in the lower joints and along the left edge.
for (let i = 0; i < 85; i++) {
const x = 5 + Math.floor(rand() * 38);
const z = Math.floor(rand() * 29);
if (rand() < (z < 12 ? 0.82 : 0.24) &&
(z % 7 < 2 || x < 9 || rand() < 0.15))
set(x, 21, z, rand() < 0.5 ? "#4c5942" : "#687052");
}
// Smoke stain on the stones behind and above the torch.
for (let z = 29; z <= 39; z++) {
for (let x = 13; x <= 35; x++) {
const spread = 3.2 + (z - 29) * 0.68;
const drift = 24 + Math.sin(z * 0.8) * 1.2;
if (Math.abs(x - drift) < spread * (0.68 + rand() * 0.56) &&
rand() < (z < 34 ? 0.52 : 0.83))
set(x, 21, z, rand() < 0.72 ? "#262626" : "#393735");
}
}
for (let i = 0; i < 24; i++) {
const x = 15 + Math.floor(rand() * 19);
const z = 31 + Math.floor(rand() * 9);
if (get(x, 21, z)) set(x, 20, z, "#323130");
}
// Riveted backplate and solid diagonal bracket projecting toward the viewer.
box(20, 19, 13, 28, 22, 29, iron);
box(21, 18, 14, 27, 18, 28, "#292b2d");
box(22, 17, 16, 26, 21, 17, ironEdge);
box(22, 14, 21, 26, 20, 23, iron);
box(22, 14, 23, 26, 20, 23, ironEdge);
line(23, 15, 19, 23, 21, 26, 1, iron);
line(25, 15, 19, 25, 21, 26, 1, iron);
for (const x of [21, 27]) {
for (const z of [15, 27]) {
set(x, 17, z, "#77736a");
set(x, 16, z, "#a39b87");
}
}
// Chunky wooden torch shaft: warm edges, darker grain.
box(22, 11, 16, 26, 15, 33, "#42291c");
box(22, 10, 18, 25, 11, 32, "#694329");
box(23, 10, 18, 24, 10, 32, "#805636");
box(24, 9, 20, 24, 9, 29, "#92633d");
for (let z = 18; z < 32; z += 4) {
set(22, 9, z, "#38251b");
set(25, 10, z + 1, "#38251b");
}
// The bracket's iron grip, torch bands, and broad ember cup.
box(21, 9, 24, 27, 16, 25, iron);
box(22, 8, 25, 26, 9, 25, ironEdge);
box(21, 9, 30, 27, 16, 31, iron);
box(20, 9, 32, 28, 17, 33, iron);
box(21, 8, 33, 27, 9, 34, ironEdge);
box(21, 16, 33, 27, 17, 34, "#303133");
box(21, 9, 34, 27, 16, 34, "#74321b");
for (const x of [21, 27]) {
set(x, 8, 25, "#77766e");
set(x, 8, 31, "#77766e");
}
for (let x = 22; x <= 26; x++) {
set(x, 9, 33, x % 2 ? "#aa421c" : "#db691d");
}
// Only the fire belongs to the animated color part.
part("flame", [24, 13, 34]);
ellipsoid(24, 13, 36, 4, 4, 3, "#8f2519");
ellipsoid(24, 12, 39, 4, 3, 5, "#ed681d");
ellipsoid(24, 11, 40, 2, 2, 4, "#ffc13b");
line(24, 12, 39, 25, 12, 46, 1, "#ffd966");
line(22, 13, 38, 20, 12, 43, 1, "#ed681d");
line(27, 13, 37, 29, 14, 42, 1, "#ed681d");
line(23, 11, 40, 22, 10, 44, 1, "#ffb02b");
set(25, 12, 46, "#ffe784");
set(20, 12, 43, "#ffb02b");
set(29, 14, 42, "#b73119");
animate("flame", {
type: "colors",
palette: ["#8f2519", "#ed681d", "#ffb02b", "#ffe784"],
pattern: "flicker",
glow: 0.9
});import { draw } from "./assets/voxel";
import { antorcheroDePared } from "./assets/antorchero-de-pared";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, antorcheroDePared, 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 antorchero-de-pared
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["antorchero-de-pared"] })
# It lands in client/assets/antorchero-de-pared.ts
# https://fogon.page/object/antorchero-de-pared