fogón

← Monsters and enemies3D assetfogon/demonio-de-fuego

Demonio de fuego

by fogonCC015784 blocks
Demonio de fuegoDrag to turn it
// «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");