fogón

← Monstruos y enemigosObjeto 3Dfogon/planta-carnivora

Planta carnívora

de fogonCC011962 bloques
Planta carnívoraArrastrá para girarlo
// «Planta carnívora» · gpt-6-sol (medium)
// A giant cartoon carnivorous plant in the ground: a thick green stem curving up from a cluster of big leaves, topped by a huge round head that is a mouth facing -y: red with white spots outside, pink inside with rows of white pointy teeth and a tongue.

// A little patch of ground for the plant to burst out of.
for (let x = 7; x <= 41; x++) {
  for (let y = 7; y <= 41; y++) {
    const d = Math.hypot(x - 24, y - 25);
    if (d < 15 + rand() * 0.8) {
      set(x, y, 0, d > 13 ? "#41672d" : "#513923");
      if (d < 13 && rand() < 0.17) set(x, y, 1, "#715038");
    }
  }
}

// Broad, pointed leaves, with raised centers and visible veins.
function leaf(tx, ty, tipZ) {
  const ox = 24, oy = 25;
  const dx = tx - ox, dy = ty - oy;
  const length = Math.hypot(dx, dy);
  const px = -dy / length, py = dx / length;

  for (let i = 0; i <= 40; i++) {
    const t = i / 40;
    const cx = ox + dx * t;
    const cy = oy + dy * t;
    const arch = 3 + 6 * Math.sin(Math.PI * t) + tipZ * t;
    const width = 5.8 * Math.pow(Math.sin(Math.PI * t), 0.8);

    for (let w = -Math.ceil(width); w <= Math.ceil(width); w++) {
      if (Math.abs(w) > width) continue;
      const x = Math.round(cx + px * w);
      const y = Math.round(cy + py * w);
      const z = Math.round(arch - 2.2 * Math.abs(w) / Math.max(1, width));
      set(x, y, z - 1, "#174f2c");
      set(x, y, z, Math.abs(w) > width - 1.5 ? "#247438" :
        rand() < 0.16 ? "#48b34d" : "#319743");
      if (Math.abs(w) < 1) set(x, y, z + 1, "#8bdb61");
    }
  }
  line(ox, oy, 5, tx, ty, 3 + tipZ, 0, "#a1dc62");
}
leaf(5, 23, 1);
leaf(42, 20, 2);
leaf(11, 8, 1);
leaf(37, 8, 2);
leaf(9, 41, 0);
leaf(39, 42, 1);
leaf(23, 6, 1);

// Thick, slightly crooked stalk.
line(24, 25, 5, 27, 27, 13, 4, "#205e31");
line(27, 27, 13, 24, 26, 24, 3, "#287c39");
line(23, 22, 6, 25, 23, 15, 1, "#55b747");
line(25, 23, 15, 23, 23, 22, 1, "#59bb4b");
line(27, 29, 11, 25, 28, 20, 1, "#164c30");

// Everything from here on pivots with the snapping head.
part("head", [24, 26, 23]);

// Round red head, with its front hollowed out into a wide oval mouth.
for (let x = 10; x <= 38; x++) {
  for (let y = 10; y <= 34; y++) {
    for (let z = 20; z <= 44; z++) {
      const shape = ((x - 24) / 14) ** 2 +
                    ((y - 22) / 12) ** 2 +
                    ((z - 32) / 12) ** 2;
      if (shape > 1) continue;
      const opening = ((x - 24) / 10.7) ** 2 +
                      ((z - 31) / 8.1) ** 2;
      if (y < 19 && opening < 1) continue;

      let color = z < 27 ? "#901b32" : z > 37 ? "#ed3442" : "#cf2639";
      if (y > 27) color = z < 28 ? "#7e1932" : "#b82339";
      if (rand() < 0.055) color = z > 35 ? "#fa4a4d" : "#ae2136";
      set(x, y, z, color);
    }
  }
}

// Deep, dark mouth at the back, with rosy gums along its bottom.
for (let x = 14; x <= 34; x++) {
  for (let z = 23; z <= 39; z++) {
    const e = ((x - 24) / 10.2) ** 2 + ((z - 31) / 7.6) ** 2;
    if (e < 1) {
      for (let y = 16; y <= 19; y++)
        set(x, y, z, z < 27 ? "#a93c70" : e > 0.78 ? "#672041" : "#350e2d");
      if (z < 27 && e < 0.72) set(x, 15, z, "#db6190");
    }
  }
}

// Chunky red lips project in front of the mouth.
for (let x = 12; x <= 36; x++) {
  for (let z = 21; z <= 41; z++) {
    const e = ((x - 24) / 11.1) ** 2 + ((z - 31) / 8.5) ** 2;
    if (e > 0.76 && e < 1.13) {
      set(x, 14, z, z < 31 ? "#a71e39" : "#dd3041");
      if (e > 0.89) set(x, 15, z, "#a91d35");
      if (e < 0.94) set(x, 13, z, z < 30 ? "#e64865" : "#f04755");
    }
  }
}

// A curled, cheerful pink tongue reaches toward the viewer.
ellipsoid(24, 15, 26, 6, 3, 2, "#e86898");
ellipsoid(24, 12, 26, 4, 3, 2, "#f78ab0");
line(24, 10, 27, 24, 15, 27, 0, "#d95283");

// Uneven pointed teeth descending from the upper jaw.
for (const [x, length] of [[16, 3], [19, 4], [22, 3], [25, 5], [28, 4], [31, 3], [33, 2]]) {
  const edge = Math.sqrt(Math.max(0, 1 - ((x - 24) / 11) ** 2));
  const top = Math.round(31 + 7.6 * edge);
  for (let j = 0; j < length; j++) {
    const half = j < 2 ? 1 : 0;
    for (let xx = x - half; xx <= x + half; xx++) {
      set(xx, 12, top - j, j === length - 1 ? "#fff9dd" : "#fffdf0");
      if (j < 2) set(xx, 13, top - j, "#d9e5d8");
    }
  }
}
// Short teeth pointing up from the lower jaw.
for (const [x, length] of [[17, 2], [20, 3], [23, 2], [27, 3], [30, 2]]) {
  const edge = Math.sqrt(Math.max(0, 1 - ((x - 24) / 11) ** 2));
  const bottom = Math.round(31 - 7.5 * edge);
  for (let j = 0; j < length; j++) {
    for (let xx = x - (j < 1 ? 1 : 0); xx <= x + (j < 1 ? 1 : 0); xx++) {
      set(xx, 12, bottom + j, "#fffced");
      if (j === 0) set(xx, 13, bottom, "#dce8d8");
    }
  }
}

// Oversized white spots on the outside of the red head.
ellipsoid(24, 17, 42, 3, 2, 1, "#fff4dc");
ellipsoid(14, 19, 39, 2, 2, 2, "#fff4dc");
ellipsoid(34, 19, 39, 2, 2, 2, "#fff4dc");
ellipsoid(12, 19, 30, 1, 2, 2, "#fff4dc");
ellipsoid(36, 19, 30, 1, 2, 2, "#fff4dc");
ellipsoid(18, 25, 43, 2, 2, 1, "#ffe6d2");
ellipsoid(31, 25, 42, 2, 2, 1, "#ffe6d2");

// Glowing yellow eyes peek over the mouth.
for (const x of [18, 30]) {
  ellipsoid(x, 14, 40, 3, 2, 2, "#771a37");
  ellipsoid(x, 12, 40, 2, 1, 2, "#ffeb52");
  set(x, 11, 40, "#40322c");
  set(x - 1, 10, 41, "#ffffff");
}

animate("head", { type: "swing", axis: "x", speed: 3, amplitude: 0.3 });