← Monstruos y enemigosObjeto 3Dfogon/nigromante
Nigromante
Arrastrá para girarlo// «Nigromante» · gpt-6-sol (medium)
// A cartoon necromancer facing -y: a tall dark green hooded robe with bone ornaments and a skull belt buckle, a gaunt pale face under the hood with glowing green eyes, holding a twisted staff topped with a small skull whose eyes glow green.
const robeDark = "#102b24";
const robeShade = "#184436";
const robe = "#226447";
const robeLight = "#31855a";
const hoodDark = "#0b211d";
const boneDark = "#938f72";
const bone = "#d8d2a4";
const boneLight = "#f4e9bf";
const glow = "#aaff39";
// A broad, slightly uneven robe, tapering toward the shoulders.
for (let z = 0; z <= 30; z++) {
let rx, ry;
if (z < 5) { rx = 12; ry = 10; }
else if (z < 18) {
rx = 12 - (z - 5) * 0.27;
ry = 10 - (z - 5) * 0.24;
} else if (z < 25) {
rx = 8.5 + (z - 18) * 0.3;
ry = 7 + (z - 18) * 0.13;
} else {
rx = 10.5 - (z - 25) * 0.42;
ry = 8 - (z - 25) * 0.22;
}
for (let x = 10; x <= 36; x++) for (let y = 13; y <= 35; y++) {
const d = ((x - 23) / rx) ** 2 + ((y - 24) / ry) ** 2;
if (d > 1) continue;
let c = z < 4 ? robeDark : z < 9 ? robeShade : robe;
if (d > 0.77 && y < 24 && z >= 9) c = robeLight;
if (d > 0.84 && x > 26 && z >= 9) c = robeShade;
if (z >= 9 && rand() < 0.035) c = rand() < 0.5 ? robeLight : robeShade;
set(x, y, z, c);
}
}
// Heavy pointed hood, with a dark recess around the face.
ellipsoid(23, 22, 33, 10, 9, 9, robeShade);
ellipsoid(23, 23, 36, 8, 8, 6, robe);
box(21, 21, 40, 25, 26, 42, robeLight);
box(22, 23, 42, 24, 26, 43, robeShade);
ellipsoid(23, 13, 33, 7, 3, 7, hoodDark);
// Pale face inset beneath the hood.
ellipsoid(23, 12, 33, 5.5, 2.7, 5.5, boneDark);
ellipsoid(23, 11, 34, 5, 2, 4.5, bone);
box(20, 9, 34, 21, 9, 36, hoodDark);
box(25, 9, 34, 26, 9, 36, hoodDark);
box(20, 8, 35, 21, 8, 35, glow);
box(25, 8, 35, 26, 8, 35, glow);
set(20, 7, 35, "#e2ff77");
set(25, 7, 35, "#e2ff77");
box(22, 9, 31, 23, 9, 32, boneDark);
box(21, 9, 29, 25, 9, 29, boneLight);
for (const x of [22, 24]) set(x, 8, 29, boneDark);
// Thick hood rim frames the face without hiding the eyes.
line(17, 12, 30, 17, 13, 37, 1, robeDark);
line(29, 12, 30, 29, 13, 37, 1, robeDark);
line(18, 12, 38, 22, 12, 40, 1, robeShade);
line(24, 12, 40, 28, 12, 38, 1, robeShade);
line(17, 11, 32, 18, 11, 37, 0, robeLight);
line(29, 11, 32, 28, 11, 37, 0, robeLight);
// Two long front folds and a ragged, dark hem.
for (let z = 3; z <= 17; z++) {
set(19, 14 + Math.round((17 - z) / 7), z, z < 6 ? robeShade : robeLight);
set(27, 14 + Math.round((17 - z) / 8), z, robeShade);
}
for (let x = 13; x <= 33; x += 3) {
box(x, 14 + Math.round(Math.abs(x - 23) * 0.35), 0,
x + 1, 15 + Math.round(Math.abs(x - 23) * 0.35),
1 + Math.floor(rand() * 2), robeDark);
}
// Bone-studded belt and oversized cartoon skull buckle.
box(17, 15, 18, 29, 17, 20, robeDark);
for (const x of [17, 19, 27, 29]) {
box(x, 14, 19, x, 14, 20, boneDark);
set(x, 13, 20, boneLight);
}
box(21, 12, 18, 25, 14, 21, boneDark);
box(22, 11, 20, 24, 11, 21, boneLight);
box(22, 11, 18, 24, 12, 19, bone);
set(22, 10, 20, hoodDark);
set(24, 10, 20, hoodDark);
set(23, 10, 19, hoodDark);
// Crossed-bone clasp on the chest.
line(20, 13, 25, 26, 13, 28, 0, bone);
line(20, 13, 28, 26, 13, 25, 0, bone);
for (const [x, z] of [[20, 25], [20, 28], [26, 25], [26, 28]]) {
sphere(x, 13, z, 1, boneLight);
}
sphere(23, 12, 27, 1.5, boneDark);
set(23, 10, 27, glow);
// Empty sleeve on the left; staff-bearing arm swings at the right shoulder.
line(15, 21, 28, 12, 19, 21, 3, robeShade);
box(10, 16, 18, 14, 21, 21, robeDark);
box(11, 15, 19, 13, 15, 20, robeLight);
box(11, 16, 17, 13, 19, 18, boneDark);
part("staffArm", [32, 21, 27]);
line(31, 21, 28, 37, 17, 25, 3, robeShade);
line(32, 19, 29, 36, 17, 27, 1, robeLight);
box(36, 15, 22, 39, 20, 26, robeDark);
box(37, 14, 23, 39, 17, 24, bone);
box(38, 13, 22, 40, 16, 24, boneDark);
// Crooked, woody staff, with pale bindings and little thorn-like knots.
line(39, 16, 5, 40, 16, 15, 1, "#493725");
line(40, 16, 15, 39, 16, 24, 1, "#67482b");
line(39, 16, 24, 40, 16, 38, 1, "#493725");
for (let z = 8; z <= 35; z += 4) {
const x = z >= 15 && z < 24 ? 39 : 40;
set(x - 1, 15, z, "#80603a");
set(x + 1, 16, z + 1, "#31291f");
}
line(39, 16, 29, 41, 16, 32, 0, boneDark);
line(39, 15, 30, 41, 15, 33, 0, bone);
// The small enchanted skull is its own color-cycling part.
part("staffSkull", [40, 16, 41]);
ellipsoid(40, 16, 41, 3, 3, 3, "#317744");
box(39, 13, 38, 41, 17, 40, "#4ca65a");
box(38, 15, 42, 38, 17, 43, "#173d30");
box(42, 15, 42, 42, 17, 43, "#173d30");
animate("staffSkull", {
type: "colors",
palette: ["#173d30", "#329348", "#8ce968"],
pattern: "pulse",
glow: 0.8
});
// Fixed, bright facial markings stay legible throughout the color pulse.
part("body");
set(39, 12, 42, hoodDark);
set(41, 12, 42, hoodDark);
set(39, 11, 42, glow);
set(41, 11, 42, glow);
set(40, 12, 40, hoodDark);
for (const x of [39, 40, 41]) set(x, 12, 38, boneLight);
animate("staffArm", { type: "swing", axis: "x", speed: 2, amplitude: 0.2 });import { draw } from "./assets/voxel";
import { nigromante } from "./assets/nigromante";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, nigromante, 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 nigromante
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["nigromante"] })
# Queda en client/assets/nigromante.ts
# https://fogon.page/object/nigromante