fogón

← Piratas y marObjeto 3Dfogon/isla-con-palmera

Isla con palmera

de fogonCC06489 bloques
Isla con palmeraArrastrá para girarlo
// «Isla con palmera» · gpt-6-sol (medium)
// A small round sandy island surrounded by a ring of turquoise shallow water: sandy beige mound with a tall curved palm tree with big green fronds and three brown coconuts, a few small rocks and a shell.

const C = { x: 24, y: 24 };
const dist = (x, y) => Math.hypot(x - C.x, y - C.y);

// The shallow turquoise ring.
part("water", [24, 24, 0]);
for (let x = 2; x <= 46; x++) {
  for (let y = 2; y <= 46; y++) {
    const r = dist(x, y);
    const edge = 21.1 + 0.25 * Math.sin(x * 0.8 + y * 0.4);
    if (r < 14.2 || r > edge) continue;
    box(x, y, 0, x, y, 1,
      rand() < 0.22 ? "#39bfc4" : rand() < 0.28 ? "#62d8d2" : "#43ccc9");
    if (r > 15.5 && r < 19.8 && rand() < 0.11)
      set(x, y, 2, "#a1eee1");
  }
}
animate("water", {
  type: "colors",
  palette: ["#35bdbf", "#48d0ce", "#75e3dc", "#a3f1e4"],
  pattern: "wave",
  glow: 0
});

part("body");

// A low, chunky beach, rising toward its middle.
for (let x = 8; x <= 40; x++) {
  for (let y = 8; y <= 40; y++) {
    const r = dist(x, y);
    const shore = 15.15 + 0.28 * Math.sin(x * 0.9) * Math.cos(y * 0.7);
    if (r > shore) continue;
    const top = r < 4.5 ? 5 : r < 8.3 ? 4 : r < 11.3 ? 3 : r < 13.5 ? 2 : 1;
    for (let z = 0; z <= top; z++) {
      const color = z === top
        ? (rand() < 0.14 ? "#f9dfa0" : rand() < 0.18 ? "#e7bd78" : "#f1cf8c")
        : (z < 2 ? "#c99d60" : "#ddaf6d");
      set(x, y, z, color);
    }
    if (rand() < 0.045) set(x, y, top + 1, "#ffe6a9");
  }
}

// Broken white surf, just where the water meets the beach.
for (let a = 0; a < Math.PI * 2; a += 0.075) {
  if (rand() < 0.38) continue;
  const r = 15.5 + 0.32 * Math.sin(a * 13);
  set(24 + Math.cos(a) * r, 24 + Math.sin(a) * r, 2,
      rand() < 0.5 ? "#d9fff0" : "#a8eee5");
}

// Palm roots and a gently bending, banded trunk.
const trunk = z => {
  const t = (z - 5) / 27;
  return {
    x: 18 + 9 * t + 0.8 * Math.sin(Math.PI * t),
    y: 27 - 4 * t
  };
};
for (const [dx, dy] of [[-4, 1], [-2, 4], [2, 3], [4, 0], [-3, -2]]) {
  line(18, 27, 6, 18 + dx, 27 + dy, 4, 1.1, "#a26839");
  line(18, 27, 7, 18 + dx * 0.65, 27 + dy * 0.65, 5, 0.7, "#d49a53");
}
for (let z = 5; z <= 32; z++) {
  const p = trunk(z);
  const radius = 2.35 - 0.6 * (z - 5) / 27;
  sphere(p.x, p.y, z, radius,
    z % 5 === 0 ? "#89532e" : z % 5 === 1 ? "#b77a3f" : "#a96d39");
  // Warm sunlit bark on the front-left of the trunk.
  if (z % 5 > 1)
    set(p.x - 1, p.y - 1, z, z % 3 === 0 ? "#dfa65b" : "#c98b49");
}
sphere(27, 23, 32, 2.2, "#80502d");

// Three distinct coconuts beneath the leaves.
for (const [x, y, z] of [[25, 21, 31], [28, 20, 30], [29, 25, 31]]) {
  sphere(x, y, z, 1.7, "#754423");
  set(x - 1, y - 1, z + 1, "#ae7540");
  set(x, y - 2, z, "#4c301e");
}

// Little stones on the sand.
for (const [x, y, z, r] of [
  [12, 22, 3, 2], [14, 20, 3, 1.3],
  [32, 33, 3, 1.8], [34, 32, 2, 1.2]
]) {
  ellipsoid(x, y, z, r, r * 0.72, r * 0.65, "#827e70");
  set(x - 1, y - 1, z + 1, "#b9afa0");
  set(x + 1, y, z, "#666c66");
}

// A small ivory fan shell on the front beach.
ellipsoid(28, 15, 4, 3.2, 2.1, 0.8, "#fff0ce");
for (let i = -3; i <= 3; i++)
  line(28, 17, 4, 28 + i, 13, 4, 0, i % 2 ? "#e6bda9" : "#f8d8b6");
line(25, 13, 4, 31, 13, 4, 0, "#fff9e4");
sphere(28, 17, 4, 0.9, "#e7ac9b");

// All fronds share the joint at the crown.
part("fronds", [27, 23, 33]);
const directions = [0, 0.61, 1.28, 1.95, 2.65, 3.35, 4.02, 4.65, 5.30, 5.84];
for (let k = 0; k < directions.length; k++) {
  const a = directions[k];
  const dx = Math.cos(a), dy = Math.sin(a);
  const px = -dy, py = dx;
  const length = 12.8 + (k % 3) * 1.65;
  const at = t => ({
    x: 27 + dx * length * t,
    y: 23 + dy * length * t,
    z: 33 + 3.6 * Math.sin(Math.PI * t) - 7.5 * t * t
  });

  // Thick curved central rib and broad, highlighted leaf blade.
  for (let j = 0; j <= 24; j++) {
    const t = j / 24, p = at(t);
    const width = 1.9 * Math.sin(Math.PI * t);
    for (let w = -width; w <= width; w += 0.8) {
      const x = p.x + px * w, y = p.y + py * w;
      const z = p.z - Math.abs(w) * 0.25;
      set(x, y, z - 1, "#267e42");
      set(x, y, z, w < 0 ? "#44a94e" : "#54bb54");
    }
    set(p.x, p.y, p.z + 1, j % 4 === 0 ? "#a4dc62" : "#80cb58");
  }

  // Separate pointed leaflets give the palm its unmistakable silhouette.
  for (let j = 2; j <= 9; j++) {
    const t = j / 11;
    const p = at(t);
    const reach = (3.1 + 1.2 * Math.sin(Math.PI * t)) * (1 - 0.18 * t);
    for (const side of [-1, 1]) {
      const tipX = p.x + px * side * reach + dx * 2.3;
      const tipY = p.y + py * side * reach + dy * 2.3;
      const tipZ = p.z - 1.2 - 1.4 * t;
      line(p.x, p.y, p.z, tipX, tipY, tipZ, 0.65,
        side === -1 ? "#56bc54" : "#32984a");
      line(p.x + px * side, p.y + py * side, p.z + 1,
           tipX - dx, tipY - dy, tipZ + 1, 0, "#8bd35e");
    }
  }
}
animate("fronds", { type: "swing", axis: "y", speed: 1.5, amplitude: 0.08 });