fogón

← Fantasy3D assetfogon/libro-de-hechizos

Libro de hechizos

by fogonCC010200 blocks
Libro de hechizosDrag to turn it
// «Libro de hechizos» · gpt-6-sol (medium)
// A big thick spellbook lying open on a small wooden lectern with a slanted top: dark purple leather cover with gold corner guards and a gold clasp, cream pages with tiny dark rune lines. Above the open pages floats a glowing magenta-and-gold rune symbol and a few sparkles.

const wood = "#493329", woodLight = "#73503a", woodDark = "#302525";
const leather = "#352044", leatherLight = "#583469", leatherDark = "#25172f";
const gold = "#e7b851", goldLight = "#ffe18a", goldDark = "#a87735";
const cream = "#f6e9bf", pageShade = "#dfcda0", ink = "#62516d";

const deskZ = y => 17 + Math.floor((y - 11) * 0.27);
const bookZ = y => deskZ(y) + 2;

// Broad, sturdy feet and a tapered wooden pedestal.
box(13, 17, 0, 35, 33, 2, woodDark);
box(15, 18, 2, 33, 32, 3, wood);
box(17, 17, 1, 19, 33, 2, woodLight);
box(29, 17, 1, 31, 33, 2, woodLight);
box(21, 21, 4, 27, 28, 15, wood);
box(22, 20, 5, 23, 21, 14, woodLight);
box(25, 20, 5, 26, 21, 14, woodLight);
box(19, 19, 14, 29, 31, 16, woodDark);
box(20, 20, 15, 28, 30, 17, woodLight);
line(20, 19, 8, 12, 15, 18, 1, wood);
line(28, 19, 8, 36, 15, 18, 1, wood);
line(21, 29, 9, 15, 34, 21, 1, wood);
line(27, 29, 9, 33, 34, 21, 1, wood);

// Slanted, thick reading board, with visible grain and brass pegs.
for (let y = 11; y <= 37; y++) {
  const z = deskZ(y);
  box(6, y, z - 2, 42, y, z, y % 5 === 0 ? woodLight : wood);
  for (let x = 8; x <= 40; x++)
    if (rand() < 0.10) set(x, y, z, rand() < 0.5 ? woodLight : woodDark);
  set(6, y, z, woodDark);
  set(42, y, z, woodDark);
}
for (let x = 6; x <= 42; x++) {
  set(x, 11, deskZ(11) + 1, woodLight);
  set(x, 37, deskZ(37) + 1, woodDark);
}
for (const x of [9, 39])
  for (const y of [13, 35])
    set(x, y, deskZ(y) + 1, goldDark);

// A little retaining lip at the low edge.
box(7, 11, 18, 41, 12, 19, woodDark);
box(9, 11, 19, 39, 11, 19, woodLight);
for (const x of [10, 38]) set(x, 11, 20, gold);

// Spine and the left half of the open book.
for (let y = 14; y <= 35; y++) {
  const b = bookZ(y);
  box(22, y, b, 26, y, b + 2, leatherDark);
  box(23, y, b + 2, 25, y, b + 3, leatherLight);

  box(8, y, b, 23, y, b + 1, leather);
  set(8, y, b + 2, leatherLight);
  set(9, y, b + 1, leatherLight);
}
for (let y = 16; y <= 33; y++) {
  const b = bookZ(y);
  for (let x = 10; x <= 22; x++) {
    const top = b + 6 + (x <= 12 ? 1 : 0);
    box(x, y, b + 2, x, y, top - 1,
      y % 3 === 0 ? pageShade : cream);
    set(x, y, top, cream);
    if (x === 10) set(x, y, b + 3, pageShade);
  }
}
for (let y = 17; y <= 32; y += 3) {
  const z = bookZ(y) + 6;
  for (let x = 14; x <= 20; x++)
    if ((x + y) % 4 !== 0) set(x, y, z, ink);
  set(12, y, z + 1, goldDark);
  set(13, y + 1, bookZ(y + 1) + 6, ink);
}
for (const y of [14, 33]) {
  const b = bookZ(y);
  box(8, y, b + 1, 10, y + 2, b + 2, goldDark);
  set(8, y, b + 3, goldLight);
  set(9, y + 1, b + 3, gold);
}
for (let y = 18; y <= 31; y += 4)
  set(8, y, bookZ(y) + 2, goldDark);

// The clasp buckles across the front edges.
box(20, 13, bookZ(14) + 1, 24, 14, bookZ(14) + 2, goldDark);
box(21, 13, bookZ(14) + 2, 24, 13, bookZ(14) + 3, gold);
set(23, 12, bookZ(14) + 3, goldLight);

// Stationary magical motes surrounding the sigil.
for (const [x, y, z, c] of [
  [15, 22, 39, "#ff70df"], [33, 25, 39, "#ffe38b"],
  [19, 28, 35, "#b46bff"], [30, 16, 35, "#ff84e4"],
  [13, 25, 34, "#f8bdef"], [35, 23, 42, "#ffeaa0"]
]) {
  set(x, y, z, c);
  set(x - 1, y, z, "#773968");
  set(x + 1, y, z, "#773968");
  set(x, y, z - 1, "#773968");
  set(x, y, z + 1, c);
}

// Right cover, pages, and their ink all swing together at the spine.
part("right cover and pages", [24, 24, 26]);
for (let y = 14; y <= 35; y++) {
  const b = bookZ(y);
  box(25, y, b, 40, y, b + 1, leather);
  set(40, y, b + 2, leatherLight);
  set(39, y, b + 1, leatherLight);
}
for (let y = 16; y <= 33; y++) {
  const b = bookZ(y);
  for (let x = 26; x <= 38; x++) {
    const top = b + 6 + (x >= 36 ? 1 : 0);
    box(x, y, b + 2, x, y, top - 1,
      y % 3 === 0 ? pageShade : cream);
    set(x, y, top, cream);
    if (x === 38) set(x, y, b + 3, pageShade);
  }
}
for (let y = 17; y <= 32; y += 3) {
  const z = bookZ(y) + 6;
  for (let x = 28; x <= 34; x++)
    if ((x + y) % 5 !== 0) set(x, y, z, ink);
  set(36, y, z + 1, goldDark);
  set(35, y + 1, bookZ(y + 1) + 6, ink);
}
for (const y of [14, 33]) {
  const b = bookZ(y);
  box(38, y, b + 1, 40, y + 2, b + 2, goldDark);
  set(40, y, b + 3, goldLight);
  set(39, y + 1, b + 3, gold);
}
for (let y = 18; y <= 31; y += 4)
  set(40, y, bookZ(y) + 2, goldDark);
box(24, 13, bookZ(14) + 1, 28, 14, bookZ(14) + 2, goldDark);
box(24, 13, bookZ(14) + 2, 27, 13, bookZ(14) + 3, gold);
set(25, 12, bookZ(14) + 3, goldLight);
animate("right cover and pages",
  { type: "swing", axis: "y", speed: 0.8, amplitude: 0.25 });

// A hovering, double-thick luminous rune, readable from the front.
part("floating rune", [24, 23, 40]);
const points = [
  [24, 45], [27, 43], [29, 40], [27, 37],
  [24, 35], [21, 37], [19, 40], [21, 43]
];
for (const y of [22, 23, 24])
  for (let i = 0; i < points.length; i++) {
    const a = points[i], b = points[(i + 1) % points.length];
    line(a[0], y, a[1], b[0], y, b[1], 0,
      i % 2 ? "#ff61ce" : "#e4a8ff");
  }
line(24, 22, 36, 24, 22, 44, 0, goldLight);
line(20, 22, 40, 28, 22, 40, 0, gold);
line(22, 21, 38, 26, 21, 42, 0, "#ffdc75");
line(26, 21, 38, 22, 21, 42, 0, "#ff78d8");
set(24, 20, 40, "#fff2ad");
set(24, 21, 40, "#fff2ad");
set(24, 23, 40, "#fff2ad");
animate("floating rune", { type: "spin", axis: "z", speed: 1.5 });
animate("floating rune", {
  type: "colors",
  palette: ["#ff43c9", "#ffd269", "#ad65ff"],
  pattern: "pulse",
  glow: 0.9
});