← Medieval3D assetfogon/monje
Monje
Drag to turn it// «Monje» · gpt-6-sol (medium)
// A chunky cartoon medieval monk: a long brown hooded robe tied with a white rope belt, the hood down showing a round bald head with a ring of brown hair (tonsure), black dot eyes, rosy cheeks, holding a big old book with a red cover against his chest, sandals.
const robe = ["#49301f", "#634027", "#795033", "#8b6040"];
const skin = "#e8b991";
const hair = "#5b3825";
function robeVolume(cx, cy, cz, rx, ry, rz) {
for (let x = Math.floor(cx - rx); x <= cx + rx; x++)
for (let y = Math.floor(cy - ry); y <= cy + ry; y++)
for (let z = Math.floor(cz - rz); z <= cz + rz; z++) {
const d = ((x-cx)/rx)**2 + ((y-cy)/ry)**2 + ((z-cz)/rz)**2;
if (d > 1) continue;
let shade = y < cy - 3 ? 2 : y > cy + 3 ? 0 : 1;
if (z > cz + 4) shade++;
if (rand() < 0.065) shade += rand() < 0.5 ? -1 : 1;
set(x, y, z, robe[Math.max(0, Math.min(3, shade))]);
}
}
// The skirt is split into two swaying, heavy robe panels.
part("leftLeg", [19, 24, 17]);
box(17, 21, 2, 21, 27, 7, skin);
box(15, 15, 0, 22, 25, 1, "#3b281d");
box(16, 14, 1, 22, 22, 2, "#69432c");
box(17, 16, 2, 21, 20, 3, skin);
box(16, 16, 3, 22, 17, 3, "#553522");
robeVolume(19, 24, 12, 7, 8, 8);
box(14, 17, 6, 15, 28, 10, "#634027");
part("rightLeg", [29, 24, 17]);
box(27, 21, 2, 31, 27, 7, skin);
box(25, 15, 0, 33, 25, 1, "#3b281d");
box(25, 14, 1, 32, 22, 2, "#69432c");
box(27, 16, 2, 31, 20, 3, skin);
box(25, 16, 3, 31, 17, 3, "#553522");
robeVolume(29, 24, 12, 7, 8, 8);
box(33, 17, 6, 34, 28, 10, "#49301f");
part("body");
animate("leftLeg", { type: "swing", axis: "x", speed: 5, amplitude: 0.3 });
animate("rightLeg", { type: "swing", axis: "x", speed: -5, amplitude: 0.3 });
// Broad, rounded shoulders and a sturdy robed torso.
robeVolume(24, 24, 23, 11, 9, 10);
ellipsoid(24, 27, 29, 10, 6, 5, "#49301f");
ellipsoid(24, 29, 29, 8, 5, 4, "#634027");
box(20, 16, 28, 28, 18, 30, "#795033");
// Folded-down hood: thick rolls behind and beside the neck.
ellipsoid(24, 30, 32, 8, 5, 4, "#553723");
line(17, 27, 32, 19, 21, 31, 2, "#795033");
line(31, 27, 32, 29, 21, 31, 2, "#795033");
line(19, 32, 34, 29, 32, 34, 1, "#8b6040");
// Rope belt wraps around the waist, with a conspicuous side knot.
box(15, 16, 19, 33, 17, 20, "#e7dfc4");
box(14, 18, 19, 15, 29, 20, "#cbbf9e");
box(33, 18, 19, 34, 29, 20, "#cbbf9e");
box(18, 16, 19, 19, 18, 21, "#fff0ce");
box(17, 14, 18, 20, 17, 20, "#e7dfc4");
line(18, 15, 18, 17, 15, 12, 1, "#eee4c9");
line(20, 16, 18, 21, 15, 14, 1, "#cbbf9e");
set(17, 15, 12, "#b4a98f");
// Round face and pale, bare crown.
ellipsoid(24, 23, 35, 7, 6, 7, skin);
ellipsoid(24, 21, 39, 5, 4, 2, "#f2c9a3");
// Tonsure: a dark ring surrounding the bald crown.
for (let x = 17; x <= 31; x++)
for (let y = 17; y <= 29; y++)
for (let z = 37; z <= 41; z++) {
const radial = ((x-24)/7)**2 + ((y-23)/6)**2;
const head = radial + ((z-35)/7)**2;
if (head <= 1.13 && radial > 0.30 && radial < 0.78)
set(x, y, z, rand() < 0.22 ? "#785034" : hair);
}
ellipsoid(18, 24, 35, 2, 4, 3, hair);
ellipsoid(30, 24, 35, 2, 4, 3, hair);
box(19, 17, 37, 20, 18, 38, hair);
box(28, 17, 37, 29, 18, 38, hair);
// Eyes, nose, rosy cheeks and a tiny friendly smile.
box(21, 17, 35, 22, 17, 36, "#241d1a");
box(26, 17, 35, 27, 17, 36, "#241d1a");
set(21, 16, 36, "#fff0dc");
set(26, 16, 36, "#fff0dc");
box(23, 16, 32, 25, 17, 34, "#dfaa83");
box(19, 18, 32, 21, 18, 33, "#d88b81");
box(27, 18, 32, 29, 18, 33, "#d88b81");
box(23, 17, 30, 25, 17, 30, "#895b4f");
set(22, 18, 31, "#895b4f");
set(26, 18, 31, "#895b4f");
// Big red leather book pressed against his chest.
box(19, 12, 18, 32, 17, 28, "#4d2922");
box(20, 10, 19, 31, 13, 27, "#e8d6ad");
box(20, 10, 20, 31, 10, 20, "#b99c73");
box(20, 10, 26, 31, 10, 26, "#b99c73");
box(19, 9, 18, 32, 10, 28, "#922f32");
box(19, 9, 18, 21, 10, 28, "#692329");
box(22, 9, 19, 31, 9, 19, "#bf6743");
box(22, 9, 27, 31, 9, 27, "#bf6743");
box(23, 8, 21, 30, 8, 25, "#b44940");
box(24, 7, 22, 29, 7, 24, "#78262b");
box(24, 6, 23, 29, 6, 23, "#d5a453");
box(26, 7, 21, 27, 7, 25, "#d5a453");
for (const x of [20, 31])
for (const z of [19, 27]) set(x, 8, z, "#e8bb68");
set(26, 6, 23, "#f4d287");
// Sleeves swing opposite the leg on the same side.
part("leftArm", [14, 23, 29]);
line(14, 23, 29, 15, 17, 23, 3, "#634027");
ellipsoid(16, 17, 23, 4, 4, 4, "#795033");
ellipsoid(18, 13, 21, 2, 2, 2, skin);
box(18, 10, 20, 19, 13, 22, "#e8b991");
part("rightArm", [34, 23, 29]);
line(34, 23, 29, 33, 17, 23, 3, "#49301f");
ellipsoid(32, 17, 23, 4, 4, 4, "#634027");
ellipsoid(32, 12, 21, 2, 2, 2, skin);
box(31, 9, 20, 32, 12, 22, "#e8b991");
animate("leftArm", { type: "swing", axis: "x", speed: -5, amplitude: 0.25 });
animate("rightArm", { type: "swing", axis: "x", speed: 5, amplitude: 0.25 });import { draw } from "./assets/voxel";
import { monje } from "./assets/monje";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, monje, 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 monje
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["monje"] })
# It lands in client/assets/monje.ts
# https://fogon.page/object/monje