fogón

← Fantasy3D assetfogon/arbol-de-cristal

Árbol de cristal

by fogonCC08656 blocks
Árbol de cristalDrag to turn it
// «Árbol de cristal» · gpt-6-sol (medium)
// A magical tree made of crystal: a twisting trunk and branches of pale violet crystal, with clusters of glowing cyan and pink crystal shards instead of leaves, growing from a small mound of dark stone.

// A crystal tree rooted in a mossy stone mound.
const stone = ["#303841", "#3c4650", "#505a62", "#667078"];
const moss = ["#3c6258", "#4e806d", "#70a382"];
const violet = ["#674781", "#8964a5", "#b191cf", "#ddc5ef"];
const glow = ["#40e7ea", "#ff79cd", "#a985f4", "#ecffff"];

// Rounded, uneven stone mound.
ellipsoid(24, 24, 2, 17, 12, 4, stone[1]);
ellipsoid(22, 23, 2, 13, 10, 4, stone[2]);
for (let i = 0; i < 32; i++) {
  const a = rand() * Math.PI * 2;
  const d = 10 + rand() * 7;
  sphere(24 + Math.cos(a) * d, 24 + Math.sin(a) * d * 0.72,
         1 + rand() * 1.5, 1 + rand() * 1.6, stone[Math.floor(rand() * 4)]);
}

// Moss follows the upper surface rather than covering the stone completely.
for (let x = 9; x <= 39; x++) {
  for (let y = 14; y <= 34; y++) {
    if (rand() > 0.54) continue;
    for (let z = 6; z >= 2; z--) {
      if (get(x, y, z) && !get(x, y, z + 1)) {
        set(x, y, z + 1, moss[Math.floor(rand() * moss.length)]);
        break;
      }
    }
  }
}

// Small storybook mushrooms on the front of the mound.
for (const [x, y, z, cap] of [
  [12, 19, 3, "#f49aba"], [35, 20, 3, "#e69a65"],
  [17, 14, 3, "#ba8be2"], [32, 15, 4, "#f49aba"]
]) {
  box(x, y, z, x, y, z + 2, "#e8d8bb");
  ellipsoid(x, y, z + 3, 2, 2, 1, cap);
  set(x - 1, y - 1, z + 3, "#fff0d7");
}

// Thick, gently twisting quartz trunk.
let previous = [24, 24, 5];
for (let z = 6; z <= 32; z += 2) {
  const x = 24 + Math.sin(z * 0.31) * 2.4;
  const y = 24 + Math.cos(z * 0.27) * 1.5;
  const r = z < 13 ? 4 : z < 24 ? 3 : 2;
  line(...previous, x, y, z, r, violet[0]);
  line(previous[0] - 1, previous[1] - 1, previous[2],
       x - 1, y - 1, z, Math.max(1, r - 1), violet[2]);
  previous = [x, y, z];
}

// Long pale facets on the front face of the twisting trunk.
line(22, 20, 7, 24, 20, 17, 0, violet[3]);
line(25, 20, 13, 22, 21, 24, 0, "#efdafa");
line(23, 21, 25, 25, 22, 32, 0, violet[3]);

// Root claws spread over the mound.
for (const [x, y] of [[13, 20], [35, 20], [18, 32], [31, 32], [24, 13]]) {
  line(24, 24, 7, x, y, 4, 2, violet[0]);
  line(23, 23, 8, x, y - 1, 5, 1, violet[2]);
}

// Branches are solid crystal, visible through gaps in the glowing canopy.
const crowns = [
  [10, 18, 30], [15, 13, 35], [23, 12, 36], [32, 14, 35],
  [38, 20, 30], [37, 29, 31], [31, 35, 34], [21, 36, 34],
  [12, 30, 29], [17, 23, 37], [29, 24, 38], [24, 25, 35]
];
for (let i = 0; i < crowns.length; i++) {
  const [x, y, z] = crowns[i];
  const fromZ = i % 3 === 0 ? 21 : 25;
  const midX = 24 + (x - 24) * 0.48;
  const midY = 24 + (y - 24) * 0.48;
  const midZ = fromZ + (z - fromZ) * 0.58;
  line(24, 24, fromZ, midX, midY, midZ, 2, violet[0]);
  line(midX, midY, midZ, x, y, z, 2, violet[1]);
  line(midX, midY - 1, midZ + 1, x, y - 1, z, 1, violet[2]);
}

// A few exposed angular knots and twigs beneath the leaves.
for (const [x, y, z] of crowns) {
  line(x, y, z - 3, x, y, z + 1, 1, violet[2]);
  set(x, y - 2, z - 1, violet[3]);
}

// All luminous foliage belongs to one color-cycling part.
part("crystalLeaves", [24, 24, 28]);

function shard(x, y, z, dx, dy, dz, c, large = false) {
  const w = large ? 2 : 1;
  line(x, y, z, x + dx * 0.35, y + dy * 0.35, z + dz * 0.38, w, c);
  line(x + dx * 0.35, y + dy * 0.35, z + dz * 0.38,
       x + dx * 0.77, y + dy * 0.77, z + dz * 0.78, 1, c);
  line(x + dx * 0.77, y + dy * 0.77, z + dz * 0.78,
       x + dx, y + dy, z + dz, 0, "#f1ffff");
}

for (let i = 0; i < crowns.length; i++) {
  const [x, y, z] = crowns[i];
  const c = glow[i % glow.length];
  ellipsoid(x, y, z, 2, 2, 2, c);

  // A tall central point plus outward-fanning crystal leaves.
  shard(x, y, z, (rand() - 0.5) * 2, (rand() - 0.5) * 2,
        i === 11 ? 10 : 6 + rand() * 2, c, true);
  for (let j = 0; j < 7; j++) {
    const a = j * Math.PI * 2 / 7 + i * 0.35;
    const reach = 3 + rand() * 2.5;
    const height = 2 + rand() * 4;
    shard(x + Math.cos(a) * 0.7, y + Math.sin(a) * 0.7, z,
          Math.cos(a) * reach, Math.sin(a) * reach, height,
          glow[(i + j) % glow.length], j % 3 === 0);
  }
}

// Floating chips give the canopy a bright, sparkling outline.
for (let i = 0; i < 55; i++) {
  const [x, y, z] = crowns[Math.floor(rand() * crowns.length)];
  const ox = Math.round((rand() - 0.5) * 10);
  const oy = Math.round((rand() - 0.5) * 9);
  const oz = Math.round((rand() - 0.5) * 9);
  if (Math.abs(ox) + Math.abs(oy) + Math.abs(oz) > 8) continue;
  set(x + ox, y + oy, z + oz, glow[Math.floor(rand() * glow.length)]);
}

animate("crystalLeaves", {
  type: "colors",
  palette: ["#36f2ee", "#ff75cb", "#b48cff", "#f0ffff"],
  pattern: "noise",
  glow: 0.7
});