fogón

← Fantasy3D assetfogon/alfombra-voladora

Alfombra voladora

by fogonCC03361 blocks
Alfombra voladoraDrag to turn it
// «Alfombra voladora» · gpt-6-sol (medium)
// A flying magic carpet: a flat rectangular rug along y with a rich red and gold pattern, deep blue border and gold tassels at the corners, its edges slightly curled up, floating above the ground.

// The carpet bobs above a stationary magical shadow on the floor.
part("carpet", [24, 24, 17]);
animate("carpet", { type: "bob", axis: "z", speed: 1.5, amplitude: 1.5 });

const cx = 23.5, cy = 23.5;

function height(x, y) {
  const edge = Math.min(x - 6, 41 - x, y - 5, 42 - y);
  const curl = edge === 0 ? 3 : edge === 1 ? 2 : edge === 2 ? 1 : 0;
  const corner = (x < 9 || x > 38) && (y < 8 || y > 39) ? 1 : 0;
  return 17 + curl + corner;
}

for (let x = 6; x <= 41; x++) {
  for (let y = 5; y <= 42; y++) {
    const z = height(x, y);
    const edge = Math.min(x - 6, 41 - x, y - 5, 42 - y);
    const band = Math.min(x - 10, 37 - x, y - 9, 38 - y);

    let top;
    if (edge === 0) {
      top = "#3157a0";
    } else if (edge <= 3) {
      top = rand() < 0.07 ? "#526ec2" : "#263d83";
      if ((x + y * 2) % 5 === 0 && edge === 2) top = "#f2bd50";
    } else if (band === 0) {
      top = "#f4bd54";
    } else {
      top = rand() < 0.09 ? "#a93455" : "#922b49";

      const dx = Math.abs(x - cx), dy = Math.abs(y - cy);
      const diamond = dx / 12 + dy / 13;
      if (diamond > 1.18 && diamond < 1.35) top = "#c65061";
      if (diamond > 0.87 && diamond <= 1.18) top = "#e6a744";
      if (diamond > 0.72 && diamond <= 0.87) top = "#71336b";
      if (diamond < 0.72) top = "#b73960";

      const inner = dx / 6 + dy / 7;
      if (inner > 0.67 && inner < 0.94) top = "#ffcf68";
      if (inner < 0.42) top = "#673b98";
      if (inner < 0.24) top = "#63e5dc";

      for (const mx of [14, 33]) {
        for (const my of [14, 33]) {
          const d = Math.abs(x - mx) + Math.abs(y - my);
          if (d === 3) top = "#f3bb55";
          if (d <= 1) top = "#d960a2";
        }
      }
    }

    set(x, y, z - 1, edge <= 3 ? "#182c69" : "#63263f");
    set(x, y, z, top);
    if (edge === 0) set(x, y, z + 1, "#3c62ad");
  }
}

// Thick front hem.
for (let x = 6; x <= 41; x++) {
  box(x, 5, 17, x, 5, 19, "#1a306c");
  set(x, 5, height(x, 5) + 1, x % 3 === 0 ? "#e6ad50" : "#4268ad");
}

// Golden corner tassels.
for (const x of [8, 39]) {
  for (const front of [true, false]) {
    const rootY = front ? 5 : 42;
    box(x - 1, rootY, 20, x + 1, rootY, 21, "#f5c15b");

    for (let i = 1; i <= 3; i++) {
      const y = front ? rootY - i : rootY + i;
      for (let t = -1; t <= 1; t++) {
        set(x + t, y, 20 - Math.floor(i / 2),
            t === 0 ? "#ffe08a" : "#d99336");
      }
    }

    for (let t = -1; t <= 1; t++) {
      const tipY = front ? 2 : 45;
      line(x + t, tipY, 19, x + t, tipY, 15 + Math.abs(t), 0,
           t === 0 ? "#ffd778" : "#d99b43");
      set(x + t, tipY, 15 + Math.abs(t), "#fff0a4");
    }
  }
}

// Sparks moving with the carpet.
for (const [x, y, color] of [
  [10, 12, "#7cdbed"], [36, 15, "#b66af4"],
  [13, 35, "#c96eff"], [34, 36, "#64e7d5"],
  [24, 8, "#74e7e4"]
]) {
  set(x, y, 13, color);
  set(x, y, 12, "#7048b1");
}

// A stationary, faint spell-shadow touches the floor at z=0.
// Its bright rim emphasizes the clear gap beneath the flying carpet.
part("body", [24, 24, 0]);
for (let x = 8; x <= 39; x++) {
  for (let y = 8; y <= 39; y++) {
    const d = Math.sqrt(((x - cx) / 15) ** 2 + ((y - cy) / 15) ** 2);
    if (d < 0.72 && (x + y) % 3 === 0) {
      set(x, y, 0, "#302451");
    } else if (d >= 0.88 && d <= 1.02) {
      set(x, y, 0, (x + y) % 5 === 0 ? "#68e6dc" : "#63449d");
    }
  }
}