← Monstruos y enemigosObjeto 3Dfogon/demonio-de-fuego
Demonio de fuego
Arrastrá para girarlo// «Demonio de fuego» · gpt-6-sol (medium)
// A cartoon fire demon facing -y: a body of dark charcoal rock with glowing orange-red cracks, curved black horns, blazing yellow eyes, big clawed arms, and flames rising from its head, shoulders and back.
const rock = "#292731";
const shadow = "#17171f";
const lightRock = "#403a42";
const ember = "#b52d1c";
const orange = "#ff681c";
const gold = "#ffbd35";
// Broad feet, with separated toes.
for (const x of [17, 31]) {
box(x - 4, 20, 0, x + 4, 30, 5, shadow);
box(x - 4, 17, 0, x + 4, 24, 3, rock);
for (const dx of [-3, 0, 3]) {
box(x + dx - 1, 15, 0, x + dx + 1, 19, 2, lightRock);
}
}
// Stocky rocky body and high shoulders.
ellipsoid(24, 25, 17, 12, 9, 12, rock);
ellipsoid(24, 25, 11, 11, 8, 6, shadow);
ellipsoid(24, 24, 24, 12, 8, 6, lightRock);
ellipsoid(24, 22, 32, 11, 9, 9, rock);
ellipsoid(24, 22, 27, 9, 8, 4, shadow);
// A short, pointed tail visible behind the body.
line(24, 32, 12, 26, 40, 8, 3, shadow);
line(26, 40, 8, 25, 43, 14, 2, rock);
line(25, 43, 14, 24, 44, 17, 1, ember);
// Flecks in the large stone surfaces.
forEach((x, y, z, color) => {
if (color === rock && rand() < 0.12) set(x, y, z, lightRock);
if (color === lightRock && z < 15 && rand() < 0.2) set(x, y, z, rock);
});
// Curved, nearly black horns: outward, upward, then curling inward.
for (const side of [-1, 1]) {
const hx = 24 + side * 8;
line(hx, 21, 37, hx + side * 4, 21, 40, 3, shadow);
line(hx + side * 4, 21, 40, hx + side * 8, 21, 44, 2, "#101117");
line(hx + side * 8, 21, 44, hx + side * 5, 20, 45, 1, "#101117");
line(hx + side * 3, 18, 40, hx + side * 6, 19, 43, 0, "#504048");
}
// Lightning-like cracks follow the visible front of the torso.
function chestY(x, z) {
const d = ((x - 24) / 12) ** 2 + ((z - 17) / 12) ** 2;
return Math.round(25 - 9 * Math.sqrt(Math.max(0, 1 - d))) - 1;
}
function crack(points) {
for (let i = 1; i < points.length; i++) {
const [ax, az] = points[i - 1], [bx, bz] = points[i];
const steps = Math.max(Math.abs(bx - ax), Math.abs(bz - az));
for (let j = 0; j <= steps; j++) {
const x = Math.round(ax + (bx - ax) * j / steps);
const z = Math.round(az + (bz - az) * j / steps);
const y = chestY(x, z);
set(x, y, z, ember);
if (j % 2 === 0) set(x, y - 1, z, j % 4 === 0 ? gold : orange);
}
}
}
crack([[21, 26], [23, 23], [21, 20], [24, 18], [22, 15], [24, 11]]);
crack([[29, 25], [27, 22], [29, 19], [27, 16], [30, 13]]);
crack([[24, 18], [27, 18]]);
crack([[21, 20], [18, 18]]);
// Huge glowing eyes with dark outlines and mischievous slanted brows.
for (const x of [19, 29]) {
box(x - 3, 12, 30, x + 3, 16, 35, shadow);
box(x - 2, 11, 31, x + 2, 12, 34, orange);
box(x - 1, 10, 32, x + 1, 11, 34, "#fff26a");
set(x, 9, 33, "#fffbd0");
}
line(16, 10, 36, 21, 10, 35, 1, lightRock);
line(27, 10, 35, 32, 10, 36, 1, lightRock);
// Wide, friendly wicked grin.
box(19, 13, 26, 29, 14, 28, shadow);
box(21, 12, 25, 27, 13, 26, shadow);
for (const x of [20, 23, 26, 29]) set(x, 12, 28, "#ffac31");
set(21, 12, 26, "#e6bd8b");
set(27, 12, 26, "#e6bd8b");
box(23, 11, 25, 25, 11, 25, ember);
// Each chunky arm swings separately from its shoulder.
for (const side of [-1, 1]) {
const name = side < 0 ? "leftArm" : "rightArm";
part(name, [24 + side * 12, 24, 26]);
ellipsoid(24 + side * 14, 24, 23, 5, 5, 7, rock);
ellipsoid(24 + side * 17, 23, 15, 5, 5, 7, shadow);
ellipsoid(24 + side * 17, 21, 10, 5, 5, 4, rock);
ellipsoid(24 + side * 14, 19, 25, 3, 2, 3, lightRock);
box(24 + side * 18 - 2, 18, 12, 24 + side * 18 + 2, 19, 15, lightRock);
// Three blunt, dark claws on each fist.
for (const dy of [-3, 0, 3]) {
line(24 + side * 18, 21 + dy, 9,
24 + side * 19, 18 + dy, 5, 1, "#11131a");
set(24 + side * 19, 18 + dy, 5, "#685352");
}
line(24 + side * 15, 18, 23,
24 + side * 18, 18, 18, 0, ember);
set(24 + side * 17, 17, 20, orange);
animate(name, {
type: "swing", axis: "x",
speed: side < 0 ? 3 : -3, amplitude: 0.3
});
}
part("body");
// All rising fire belongs to one color-cycling part.
part("flames", [24, 26, 30]);
function flame(x, y, z, height, lean) {
for (let i = 0; i < height; i++) {
const t = i / height;
const fx = Math.round(x + lean * t * t);
const radius = t < 0.3 ? 2 : t < 0.7 ? 1 : 0;
const color = t < 0.28 ? "#a62016"
: t < 0.58 ? "#f05216"
: t < 0.83 ? "#ffae22" : "#fff17c";
for (let dx = -radius; dx <= radius; dx++) {
for (let dy = -radius; dy <= radius; dy++) {
if (dx * dx + dy * dy <= radius * radius + 0.5)
set(fx + dx, y + dy, z + i, color);
}
}
}
}
flame(20, 23, 39, 8, -3);
flame(25, 24, 40, 7, 1);
flame(29, 25, 39, 7, 3);
flame(11, 25, 29, 10, -3);
flame(37, 25, 29, 10, 3);
flame(17, 32, 27, 13, -3);
flame(24, 34, 29, 12, 1);
flame(31, 33, 27, 12, 4);
flame(24, 39, 17, 9, -2);
animate("flames", {
type: "colors",
palette: ["#a62016", "#f05216", "#ffae22", "#fff17c"],
pattern: "noise",
glow: 0.9
});
part("body");import { draw } from "./assets/voxel";
import { demonioDeFuego } from "./assets/demonio-de-fuego";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, demonioDeFuego, 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 demonio-de-fuego
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["demonio-de-fuego"] })
# Queda en client/assets/demonio-de-fuego.ts
# https://fogon.page/object/demonio-de-fuego