fogón

← Medieval3D assetfogon/mago-medieval

Mago

by fogonCC08876 blocks
MagoDrag to turn it
// «Mago» · gpt-6-sol (medium)
// A chunky wizard standing: a tall pointed royal blue hat with gold stars and a wide brim, a long white beard down to the belly, a long blue robe with gold stars and wide sleeves, and a tall gnarled wooden staff in the right hand with a glowing purple crystal on top. Arms and legs are moving parts, and the crystal glows.

const blue = "#244aa0", blueLight = "#3565bd", blueDark = "#19346f";
const gold = "#e9b94c", goldLight = "#ffe095", goldDark = "#a97928";
const skin = "#dca77d", skinLight = "#f1c49a";
const white = "#f4f0df", whiteShade = "#d4d5d2", whiteDark = "#aeb9c3";
const wood = "#67442b", woodLight = "#95643b", woodDark = "#422c22";

function robeWidth(z) { return 7.4 + (27 - z) * 0.24; }
function robeDepth(z) { return 5.8 + (27 - z) * 0.16; }
function robeFront(x, z) {
  const u = (x - 24) / robeWidth(z);
  return Math.round(24 - robeDepth(z) * Math.sqrt(Math.max(0, 1 - u * u)));
}
function star(x, y, z) {
  set(x, y, z, goldLight);
  set(x - 1, y, z, gold);
  set(x + 1, y, z, gold);
  set(x, y, z - 1, goldDark);
  set(x, y, z + 1, goldLight);
}

// Walking boots and the trouser legs visible beneath the robe.
for (const [name, x, speed] of [["leftLeg", 20, 3], ["rightLeg", 28, -3]]) {
  part(name, [x, 24, 9]);
  box(x - 2, 21, 3, x + 2, 26, 9, blueDark);
  box(x - 2, 19, 0, x + 2, 27, 3, woodDark);
  box(x - 2, 17, 0, x + 2, 22, 2, wood);
  box(x - 2, 18, 3, x + 2, 24, 3, goldDark);
  box(x - 1, 17, 1, x + 1, 17, 1, woodLight);
  animate(name, { type: "swing", axis: "x", speed, amplitude: 0.25 });
}
part("body");

// Heavy, flared robe, with a softly irregular woven surface.
for (let z = 6; z <= 27; z++) {
  const rx = robeWidth(z), ry = robeDepth(z);
  for (let x = 12; x <= 36; x++) for (let y = 14; y <= 34; y++) {
    const d = ((x - 24) / rx) ** 2 + ((y - 24) / ry) ** 2;
    if (d <= 1) {
      let c = z < 9 ? blueDark : blue;
      if (y < 21 && z >= 9) c = blueLight;
      if (x > 29 && y > 22) c = blueDark;
      if (d > 0.77 && rand() < 0.085) c = y < 23 ? "#426fc0" : blueDark;
      set(x, y, z, c);
    }
  }
}
for (let x = 14; x <= 34; x++) {
  const y = robeFront(x, 7);
  box(x, y - 1, 6, x, y - 1, 7, x % 3 === 0 ? gold : goldDark);
}
// Gold seam and a broad waist sash.
for (let z = 9; z <= 21; z++) {
  const y = robeFront(24, z);
  set(24, y - 1, z, z % 3 === 0 ? goldLight : gold);
}
for (let x = 18; x <= 30; x++) {
  const y = robeFront(x, 20);
  box(x, y - 1, 19, x, y - 1, 20, x % 4 === 0 ? goldLight : goldDark);
}
box(22, robeFront(24, 20) - 2, 19, 26, robeFront(24, 20) - 2, 21, gold);
box(23, robeFront(24, 20) - 3, 20, 25, robeFront(24, 20) - 3, 20, goldLight);
for (const [x, z] of [[18, 13], [30, 14], [19, 24], [29, 25], [18, 9], [30, 9]]) {
  star(x, robeFront(x, z) - 2, z);
}

// Neck, rosy face, and large readable eyes.
ellipsoid(24, 23, 29, 5, 4, 6, skin);
box(21, 17, 30, 22, 17, 31, "#322b31");
box(26, 17, 30, 27, 17, 31, "#322b31");
set(22, 16, 31, "#f9f4df");
set(26, 16, 31, "#f9f4df");
box(23, 16, 28, 25, 18, 29, skinLight);
set(24, 15, 28, "#e8ad85");
box(20, 17, 32, 22, 17, 32, whiteShade);
box(26, 17, 32, 28, 17, 32, whiteShade);

// Layered beard, full at the cheeks and tapering below the belt.
for (let z = 13; z <= 29; z++) {
  const width = z >= 24 ? 5 : Math.max(1, Math.round((z - 12) * 0.42));
  const front = z >= 25 ? 15 : 14;
  for (let x = 24 - width; x <= 24 + width; x++) {
    const edge = Math.abs(x - 24) / (width + 0.4);
    const y0 = front + Math.round(edge * 2);
    for (let y = y0; y <= 19; y++) {
      set(x, y, z, y === y0 ? (x % 3 === 0 ? whiteShade : white) : whiteDark);
    }
  }
}
for (let x = 20; x <= 28; x++) {
  const y = 13 + Math.round(Math.abs(x - 24) * 0.35);
  box(x, y, 27, x, y, 28, x === 24 ? white : whiteShade);
}
for (const x of [21, 24, 27]) {
  for (let z = 17; z <= 26; z++) {
    const width = z >= 24 ? 5 : Math.max(1, Math.round((z - 12) * 0.42));
    if (Math.abs(x - 24) <= width) set(x, z >= 25 ? 13 : 12, z, z % 4 ? white : whiteShade);
  }
}

// Wide, stiff brim and a high pointed royal-blue hat.
ellipsoid(24, 23, 35, 11, 9, 2, blueDark);
ellipsoid(24, 23, 36, 10, 8, 1, blue);
for (let x = 15; x <= 33; x++) {
  const u = (x - 24) / 11;
  const y = Math.round(23 - 9 * Math.sqrt(Math.max(0, 1 - u * u)));
  set(x, y - 1, 35, gold);
}
for (let z = 37; z <= 45; z++) {
  const rx = Math.max(0.8, 7.5 * (46 - z) / 10);
  const ry = Math.max(0.8, 6.5 * (46 - z) / 10);
  for (let x = 16; x <= 32; x++) for (let y = 16; y <= 30; y++) {
    if (((x - 24) / rx) ** 2 + ((y - 23) / ry) ** 2 <= 1)
      set(x, y, z, y < 23 ? (rand() < 0.08 ? blueLight : blue) : blueDark);
  }
}
for (let x = 18; x <= 30; x++) set(x, 17, 37, x % 3 === 0 ? goldLight : gold);
star(24, 16, 39);
star(21, 18, 37);
star(27, 18, 37);
set(24, 22, 45, goldLight);

// Left sleeve and hand, swinging forward opposite the staff hand.
part("leftArm", [17, 24, 25]);
ellipsoid(16, 23, 22, 4, 5, 5, blueDark);
ellipsoid(15, 21, 20, 3, 4, 4, blue);
box(12, 17, 17, 17, 22, 18, goldDark);
box(12, 17, 19, 16, 18, 19, gold);
ellipsoid(15, 20, 16, 2, 2, 2, skin);
set(15, 17, 16, skinLight);
star(15, 16, 23);
animate("leftArm", { type: "swing", axis: "x", speed: -3, amplitude: 0.25 });

part("rightArm", [31, 24, 25]);
ellipsoid(33, 23, 22, 4, 5, 5, blueDark);
ellipsoid(35, 21, 20, 3, 4, 4, blue);
box(34, 17, 17, 38, 22, 18, goldDark);
box(35, 17, 19, 38, 18, 19, gold);
ellipsoid(37, 20, 17, 2, 2, 2, skin);
box(37, 18, 16, 39, 20, 17, skinLight);
star(34, 16, 23);
animate("rightArm", { type: "swing", axis: "x", speed: 3, amplitude: 0.25 });

// Gnarled staff: its crooked shaft passes through the wizard's grip.
part("body");
const knots = [
  [38, 20, 0], [38, 20, 9], [37, 20, 15], [38, 19, 22],
  [37, 19, 29], [38, 20, 36], [38, 20, 41]
];
for (let i = 0; i < knots.length - 1; i++) {
  line(...knots[i], ...knots[i + 1], 1, wood);
}
for (let z = 1; z <= 39; z += 4) {
  const x = z >= 25 && z < 33 ? 37 : 38;
  set(x, 18, z, woodLight);
}
line(37, 20, 11, 35, 21, 14, 0, woodLight);
line(38, 20, 27, 40, 21, 30, 0, woodDark);
line(38, 20, 34, 40, 19, 36, 0, woodLight);
box(37, 19, 39, 39, 21, 40, goldDark);
box(37, 19, 41, 39, 21, 41, gold);
for (const x of [37, 39]) set(x, 18, 40, goldLight);

// Crystal and its animated violet radiance.
part("crystal", [38, 20, 43]);
ellipsoid(38, 20, 44, 3, 3, 2, "#a659eb");
box(37, 19, 42, 39, 21, 45, "#bb76f5");
set(38, 20, 46, "#f2d3ff");
set(38, 17, 44, "#ebc5ff");
set(35, 20, 44, "#d99aff");
set(41, 20, 44, "#d99aff");
animate("crystal", {
  type: "colors",
  palette: ["#8037c5", "#aa56e9", "#ce8dff", "#f2d3ff"],
  pattern: "pulse",
  glow: 0.7
});