fogón

← Basics3D assetfogon/portal

Portal mágico

by fogonCC011512 blocks
Portal mágicoDrag to turn it
// «Portal mágico» · gpt-6-sol (medium)
// A magic portal: a tall rectangular frame of dark obsidian blocks standing on a small square of grass and dirt, with swirling purple energy filling the opening, a few small plants and a red mushroom around it.

// A patch of earth and grass.
box(4, 7, 0, 43, 40, 2, "#694329");
box(4, 7, 3, 43, 40, 3, "#67a345");

for (let x = 4; x <= 43; x++) {
  for (let y = 7; y <= 40; y++) {
    const n = rand();
    if (n < 0.18) set(x, y, 3, "#78b552");
    else if (n < 0.31) set(x, y, 3, "#5b9841");
    else if (n > 0.96) set(x, y, 3, "#8bc15c");

    if (y === 7 || y === 40 || x === 4 || x === 43) {
      if (rand() < 0.29) set(x, y, 2, "#795035");
      if (rand() < 0.20) set(x, y, 0, "#573924");
    }
  }
}

// The solid obsidian frame. Its front is at y=20; the portal is recessed.
box(12, 21, 4, 17, 27, 42, "#17121f");
box(31, 21, 4, 36, 27, 42, "#17121f");
box(18, 21, 4, 30, 27, 8, "#17121f");
box(18, 21, 37, 30, 27, 42, "#17121f");

// Broad, irregular stone faces and deeply recessed joints.
for (let z = 4; z <= 42; z += 5) {
  for (const [a, b] of [[12, 17], [31, 36]]) {
    const end = Math.min(z + 4, 42);
    box(a, 20, z, b, 20, end, "#0f0d18");
    box(a + 1, 20, z + 1, b - 1, 20, Math.min(z + 3, end), "#292039");
    if (z + 2 <= end) {
      box(a + 1, 20, z + 2, a + 2, 20, z + 2, "#332743");
      set(b - 1, 20, z + 1, "#21192e");
    }
  }
}
for (const z0 of [4, 37]) {
  const z1 = z0 === 4 ? 8 : 42;
  box(18, 20, z0, 30, 20, z1, "#100e19");
  for (let x = 18; x <= 30; x += 4) {
    box(x, 20, z0 + 1, Math.min(x + 2, 30), 20, z1 - 1, "#292039");
    set(x, 20, z0 + 2, "#352846");
  }
}

// Dim violet glints along the inner edges, and a shaded top and side.
for (let z = 9; z <= 36; z++) {
  if (z % 5 !== 0) {
    set(17, 20, z, "#372245");
    set(31, 20, z, "#281c38");
  }
}
box(12, 21, 42, 36, 26, 42, "#30243f");
for (let x = 13; x <= 36; x += 4) {
  box(x, 22, 42, Math.min(x + 2, 36), 25, 42, "#3a2b4a");
}
box(36, 22, 5, 36, 27, 41, "#211a2d");

// Swirling energy, set back inside the opening.
part("portal", [24, 23, 23]);
for (let z = 9; z <= 36; z++) {
  const curl = 24 + 3.2 * Math.sin(z * 0.43 + 0.4)
                  + 1.1 * Math.sin(z * 0.91);
  for (let x = 18; x <= 30; x++) {
    const d = x - curl;
    let color = "#8429b7";
    if (d > -2.7 && d < -0.4) color = "#501880";
    if (d >= -0.4 && d < 0.8) color = "#662099";
    if (d >= 1.3 && d < 3.0) color = "#bb42dd";
    if (Math.abs(d - 3.1) < 0.65) color = "#d25aea";
    if (rand() < 0.13) color = d > 0 ? "#a735cd" : "#71239f";
    if (x === 18 || x === 30) color = "#76209f";
    box(x, 22, z, x, 24, z, color);
    if ((x + z) % 7 === 0 && d > 1) set(x, 21, z, "#b443df");
  }
}
animate("portal", {
  type: "colors",
  palette: ["#4d167f", "#7120af", "#9425cf", "#be37e7", "#e16bfa", "#a82ddd"],
  pattern: "noise",
  glow: 0.82
});

part("body");

// Sparse grass clumps, kept clear of the portal.
for (const [x, y] of [
  [9, 19], [10, 20], [11, 34], [17, 35], [20, 12],
  [23, 37], [29, 11], [34, 34], [38, 27], [39, 18]
]) {
  set(x, y, 4, "#43833b");
  set(x, y, 5, "#569b42");
  set(x - 1, y, 4, "#65a748");
  if (rand() < 0.65) set(x, y, 6, "#73ad4e");
}

// Two little red mushrooms with pale stems and spotted caps.
for (const [x, y] of [[15, 13], [36, 15]]) {
  box(x, y, 4, x, y, 5, "#e4d8b1");
  box(x - 1, y - 1, 6, x + 1, y + 1, 6, "#b92232");
  box(x, y, 7, x + 1, y, 7, "#dc3640");
  set(x - 1, y - 1, 6, "#f4e8d9");
  set(x + 1, y, 7, "#fff0dc");
  set(x + 1, y + 1, 6, "#821b2b");
}

// Tiny floating sparks in front of and behind the frame.
part("moteA", [18, 20, 17]);
set(18, 19, 17, "#d765fa");
set(18, 19, 18, "#f0b0ff");
set(19, 19, 17, "#8724c1");
animate("moteA", { type: "bob", axis: "z", speed: 1.1, amplitude: 1 });
animate("moteA", {
  type: "colors",
  palette: ["#8724c1", "#d765fa", "#f0b0ff"],
  pattern: "pulse",
  glow: 0.8
});

part("moteB", [30, 21, 31]);
set(30, 19, 31, "#e891ff");
set(31, 19, 31, "#bd47eb");
set(30, 19, 32, "#9c32ce");
animate("moteB", { type: "bob", axis: "z", speed: 0.85, amplitude: 1.4 });
animate("moteB", {
  type: "colors",
  palette: ["#9c32ce", "#e891ff", "#bd47eb"],
  pattern: "pulse",
  glow: 0.8
});

part("moteC", [21, 30, 36]);
set(21, 30, 36, "#dd7df7");
set(22, 30, 36, "#ac3cda");
animate("moteC", { type: "bob", axis: "z", speed: 1.3, amplitude: 0.8 });
animate("moteC", {
  type: "colors",
  palette: ["#8a2ab8", "#dd7df7", "#ac3cda"],
  pattern: "flicker",
  glow: 0.7
});