fogón

← Whole house3D assetfogon/consola-con-joystick

Consola con joystick

by fogonCC09531 blocks
Consola con joystickDrag to turn it
// «Consola con joystick» · gpt-6-sol (medium)
// A home video game console: a sleek black and white box lying flat with a glowing blue light strip, and two chunky game controllers (one red, one blue) in front of it connected with curly cables.

// Low feet and the softly rounded white console body.
box(9, 25, 0, 15, 35, 1, "#454a50");
box(33, 25, 0, 39, 35, 1, "#454a50");

function roundedLayer(x0, x1, y0, y1, z, corner, color) {
  for (let x = x0; x <= x1; x++) {
    for (let y = y0; y <= y1; y++) {
      const dx = Math.min(x - x0, x1 - x);
      const dy = Math.min(y - y0, y1 - y);
      if (dx < corner && dy < corner &&
          (dx - corner) ** 2 + (dy - corner) ** 2 > corner ** 2) continue;
      set(x, y, z, color);
    }
  }
}

for (let z = 1; z <= 7; z++) {
  const c = z <= 2 ? "#b8c1c6" : z <= 5 ? "#e5eaeb" : "#faf9f5";
  roundedLayer(5, 42, 22, 40, z, 3, c);
}
roundedLayer(6, 41, 23, 39, 8, 2, "#ffffff");

// Subtle variation on the broad, warm-white lid.
for (let x = 7; x <= 40; x++)
  for (let y = 24; y <= 38; y++)
    if (get(x, y, 8) === "#ffffff" && rand() < 0.10)
      set(x, y, 8, "#f0f2ef");

// A contrasting, slightly raised black panel with a diagonal leading edge.
for (let y = 25; y <= 38; y++) {
  const start = 18 + Math.floor((y - 25) * 0.38);
  for (let x = start; x <= 40; x++) {
    set(x, y, 8, y < 28 ? "#30363c" : "#252a30");
    if (x >= start + 2 && x <= 39 && y >= 27 && y <= 37)
      set(x, y, 9, rand() < 0.08 ? "#343a40" : "#191e24");
  }
  set(start, y, 8, "#747d82");
}
box(24, 32, 29, 9, 29, 9, "#41484d"); // tiny lid badge
box(26, 32, 29, 9, 28, 9, "#dce0df");

// Dark front fascia, a disc slot, and chunky little ports.
box(7, 21, 3, 40, 21, 5, "#292e34");
box(8, 21, 2, 39, 21, 2, "#626a70");
box(8, 20, 3, 40, 20, 5, "#22282e");
box(22, 20, 3, 36, 20, 3, "#0c1015");
box(23, 20, 4, 35, 20, 4, "#555f66");
for (const x of [11, 17]) {
  box(x, 20, 3, x + 3, 20, 4, "#090d12");
  box(x + 1, 20, 4, x + 2, 20, 4, "#69767d");
}
set(39, 20, 4, "#aebdc4");
set(39, 20, 3, "#49535a");

function controller(cx, shades) {
  const cy = 10;
  // Three overlapping rounded masses make the two broad handgrips.
  for (let x = cx - 8; x <= cx + 8; x++)
    for (let y = 4; y <= 16; y++)
      for (let z = 0; z <= 7; z++) {
        const oval = ((x - cx) / 7.0) ** 2 +
                     ((y - 10.5) / 5.0) ** 2 +
                     ((z - 3.1) / 3.25) ** 2 <= 1;
        const grips = [-5, 5].some(d =>
          ((x - cx - d) / 3.2) ** 2 +
          ((y - 7.7) / 4.2) ** 2 +
          ((z - 2.7) / 2.9) ** 2 <= 1);
        if (!oval && !grips) continue;
        let c = z <= 1 ? shades[0] : z <= 3 ? shades[1] : shades[2];
        if (z >= 5 && rand() < 0.13) c = shades[3];
        set(x, y, z, c);
      }

  // Pale inset around the controls and a curved shoulder seam.
  ellipsoid(cx, 10.5, 5.6, 4.7, 3.0, 1.0, shades[3]);
  line(cx - 6, 13, 5, cx - 3, 15, 5, 0, shades[0]);
  line(cx + 3, 15, 5, cx + 6, 13, 5, 0, shades[0]);

  // Raised cross-shaped D-pad.
  box(cx - 4, 10, 7, cx - 2, 10, 7, "#30353b");
  box(cx - 3, 9, 7, cx - 3, 11, 7, "#30353b");
  set(cx - 3, 10, 8, "#687279");

  // Four big, glossy face buttons.
  for (const [dx, dy, color] of [
    [3, 9, "#f5d36d"], [2, 10, "#89d5af"],
    [4, 10, "#f6a7ac"], [3, 11, "#bba9ec"]
  ]) {
    set(cx + dx, dy, 7, "#353941");
    set(cx + dx, dy, 8, color);
  }
  set(cx, 10, 7, "#464e53");
  set(cx, 10, 8, "#f8f5e9");
  set(cx - 1, 12, 7, "#697177");
  set(cx + 1, 12, 7, "#697177");

  // Dark triggers at the back edge.
  box(cx - 6, 15, 3, cx - 4, 16, 4, "#30353a");
  box(cx + 4, 15, 3, cx + 6, 16, 4, "#30353a");
}

controller(13, ["#813d45", "#ba5860", "#e57878", "#f6a49b"]);
controller(34, ["#315575", "#457faf", "#67a9d8", "#a2d4ed"]);

// Coiled cords sit in the gap between the controllers and console.
function cord(cx) {
  line(cx, 15, 4, cx, 17, 3, 0, "#293139");
  let previous = [cx, 17, 3];
  for (let i = 1; i <= 60; i++) {
    const t = i / 60;
    const angle = t * Math.PI * 6;
    const next = [
      cx + Math.round(2.0 * Math.sin(angle)),
      17 + 4.5 * t,
      2 + Math.round(Math.cos(angle))
    ];
    line(...previous, ...next, 0, "#293139");
    previous = next;
  }
  line(...previous, cx, 22, 3, 0, "#293139");
  set(cx, 18, 3, "#66747c");
  set(cx + 2, 20, 2, "#66747c");
}
cord(13);
cord(34);

// The only moving part: a luminous strip across the front lip.
part("light strip", [24, 20, 5]);
box(8, 20, 5, 39, 20, 5, "#197ec2");
box(10, 20, 6, 37, 20, 6, "#74e5f5");
set(8, 20, 6, "#319fd5");
set(39, 20, 6, "#319fd5");
animate("light strip", {
  type: "colors",
  palette: ["#1879bc", "#2baee0", "#78e9fa", "#b3f7ff"],
  pattern: "pulse",
  glow: 0.8
});