fogón

← Monsters and enemies3D assetfogon/babosa

Babosa

by fogonCC015206 blocks
BabosaDrag to turn it
// «Babosa» · gpt-6-sol (medium)
// A big cartoon slug, horizontal and low on the ground: a long soft body in sickly yellow-green with a lighter belly and dark spots, a slimy trail behind, and at the front (-y) two long eye stalks with glowing orange eyes and a wide grumpy mouth.

// A slick trail stays on the floor while the slug bobs above it.
for (let y = 30; y <= 47; y++) {
  const width = y < 39 ? 9 + (y - 30) * 0.55 : 14 - (y - 39) * 0.95;
  for (let x = 9; x <= 39; x++) {
    const wobble = Math.sin(y * 0.75) * 1.5;
    if (Math.abs(x - 24 - wobble) > width || rand() < 0.09) continue;
    set(x, y, 0, rand() < 0.28 ? "#69b486" : "#4b9475");
    if (rand() < 0.12) set(x, y, 1, "#9bd9a0");
  }
}
for (let i = 0; i < 45; i++) {
  const x = 12 + Math.floor(rand() * 25);
  const y = 39 + Math.floor(rand() * 9);
  if (!get(x, y, 0)) set(x, y, 0, "#7ac99a");
}

part("body", [24, 24, 1]);

// Overlapping rounded volumes make a broad head, plump back, and tapered tail.
const lobes = [
  [24, 25, 9, 16, 18, 10],
  [24, 14, 10, 13, 10, 9],
  [24, 36, 6, 11, 10, 6]
];
for (let x = 7; x <= 41; x++) {
  for (let y = 3; y <= 45; y++) {
    for (let z = 0; z <= 20; z++) {
      let inside = false;
      for (const [cx, cy, cz, rx, ry, rz] of lobes) {
        const d = ((x - cx) / rx) ** 2 +
                  ((y - cy) / ry) ** 2 +
                  ((z - cz) / rz) ** 2;
        if (d <= 1) { inside = true; break; }
      }
      if (!inside) continue;

      let color;
      const side = Math.abs(x - 24);
      if (z <= 2) color = "#536d29";
      else if (z <= 5 && (side > 9 || y < 11)) color = "#cfda77";
      else if (z >= 14) color = "#b1cc43";
      else if (side > 12 || z < 7) color = "#789630";
      else color = "#99b936";
      if (rand() < 0.055 && z > 4) color = "#a9c447";
      set(x, y, z, color);
    }
  }
}

// Broad, readable patches on the back, following its actual surface.
for (const [sx, sy, radius] of [
  [17, 19, 2], [29, 20, 2], [23, 25, 3],
  [32, 29, 2], [16, 32, 2], [25, 35, 2]
]) {
  for (let x = sx - radius; x <= sx + radius; x++) {
    for (let y = sy - radius; y <= sy + radius; y++) {
      if ((x - sx) ** 2 + (y - sy) ** 2 > radius ** 2) continue;
      for (let z = 20; z >= 7; z--) {
        if (get(x, y, z)) {
          set(x, y, z, rand() < 0.2 ? "#637e2b" : "#718b2b");
          break;
        }
      }
    }
  }
}

// Smaller spots run down both flanks.
for (const [sy, sz, radius] of [
  [16, 12, 2], [22, 9, 2], [28, 13, 2],
  [34, 8, 2], [39, 6, 1]
]) {
  for (const side of [-1, 1]) {
    for (let y = sy - radius; y <= sy + radius; y++) {
      for (let z = sz - radius; z <= sz + radius; z++) {
        if ((y - sy) ** 2 + (z - sz) ** 2 > radius ** 2) continue;
        for (let x = side < 0 ? 7 : 41;
             side < 0 ? x <= 24 : x >= 24;
             x -= side) {
          if (get(x, y, z)) {
            set(x, y, z, "#566f28");
            break;
          }
        }
      }
    }
  }
}

// Find the visible front surface so the expression follows the round face.
function front(x, z) {
  for (let y = 2; y <= 16; y++) if (get(x, y, z)) return y;
  return -1;
}

// Wide, downturned grumpy mouth and a pale lower lip.
for (let x = 15; x <= 33; x++) {
  const t = 1 - Math.abs(x - 24) / 9;
  const upper = 8 + Math.round(2 * t);
  const lower = 7 + Math.round(t);
  for (let z = lower; z <= upper; z++) {
    const y = front(x, z);
    if (y >= 0) set(x, y - 1, z, "#344522");
  }
  const lipY = front(x, lower - 1);
  if (lipY >= 0) set(x, lipY - 1, lower - 1, "#e0df87");
}
for (const x of [19, 29]) {
  const z = 8;
  const y = front(x, z);
  if (y >= 0) set(x, y - 2, z, "#f1e9a5");
}
for (const x of [21, 27]) {
  const y = front(x, 13);
  if (y >= 0) set(x, y - 1, 13, "#5b7429");
}
animate("body", { type: "bob", axis: "z", speed: 1.5, amplitude: 0.7 });

// Both stalks sway together from their base at the front of the head.
part("eye stalks", [24, 10, 16]);
for (const side of [-1, 1]) {
  const baseX = 24 + side * 7;
  const eyeX = 24 + side * 9;

  line(baseX, 10, 16, eyeX, 8, 27, 2, "#68882c");
  line(baseX - side, 9, 18, eyeX - side, 7, 26, 1, "#b6cf50");
  sphere(eyeX, 8, 28, 4, "#536e2b");
  ellipsoid(eyeX, 5, 28, 3, 2, 3, "#e56820");
  ellipsoid(eyeX, 3, 28, 2, 1, 2, "#ffb329");
  set(eyeX, 2, 28, "#ffe26a");
  set(eyeX, 1, 28, "#7a3522");

  // Heavy slanted lids give the bright eyes their grumpy look.
  line(eyeX - 3, 3, 31, eyeX + 3, 3, 30, 1, "#4d6729");
}
animate("eye stalks", {
  type: "swing", axis: "x", speed: 2, amplitude: 0.25
});