← BásicoObjeto 3Dfogon/piano-de-cola
Piano de cola
Arrastrá para girarlo// «Piano de cola» · gpt-6-sol (medium)
// Grand piano («Piano de cola»).
// Grand piano, facing -y.
const black = "#101115";
const edge = "#08090c";
const gloss = "#202127";
const gold = "#a47b37";
const ivory = "#eee9db";
function sides(y) {
const t = Math.max(0, Math.min(1, (y - 15) / 26));
return [
Math.round(8 + 10 * Math.pow(t, 1.35)),
Math.round(39 - 9 * Math.pow(t, 0.8))
];
}
// Three sturdy piano legs, with brass-colored feet.
for (const [x, y] of [[12, 17], [35, 17], [25, 35]]) {
box(x - 2, y - 2, 3, x + 2, y + 2, 19, black);
box(x - 2, y - 2, 2, x + 2, y + 2, 4, gold);
box(x - 1, y - 1, 0, x + 1, y + 1, 2, "#342a1a");
box(x - 2, y - 2, 16, x + 2, y + 2, 19, gloss);
}
// Curved, solid grand-piano case.
for (let y = 15; y <= 41; y++) {
const [l, r] = sides(y);
for (let x = l; x <= r; x++) {
for (let z = 19; z <= 25; z++) {
const border = x <= l + 1 || x >= r - 1 || y >= 40;
let c = border ? black : (z === 25 ? "#775727" : "#16171a");
if (z === 25 && !border && rand() < 0.1) c = "#906d35";
set(x, y, z, c);
}
}
box(l, y, 22, l, y, 22, gold);
box(r, y, 22, r, y, 22, "#654c29");
box(l, y, 25, l + 1, y, 26, edge);
box(r - 1, y, 25, r, y, 26, edge);
}
box(9, 14, 19, 38, 16, 24, black);
box(10, 14, 22, 37, 14, 22, "#775b30");
// A glimpse of the golden soundboard and strings beside the raised lid.
for (let x = 29; x <= 35; x += 2) {
line(x, 20, 26, Math.min(x, 31), 36, 26, 0, "#c39a4a");
}
box(29, 22, 26, 30, 34, 26, "#332719");
// Raised lid: a long tapered wing, with narrow glossy ribs.
for (let y = 19; y <= 41; y++) {
const [bodyL, bodyR] = sides(y);
const l = bodyL;
const r = Math.min(bodyR - 3, Math.round(31 - (y - 19) * 0.04));
const height = Math.round(31 + (y - 19) * 0.48);
for (let x = l; x <= r; x++) {
const rib = (x - 8) % 3;
const top = height + (rib === 0 ? 1 : 0);
for (let z = height - 2; z <= top; z++) {
let c = z < height ? "#101115" :
rib === 0 ? "#292a30" : rib === 1 ? "#191a20" : "#0d0e12";
if (x === l || x === r) c = edge;
set(x, y, z, c);
}
}
}
// Visible dark edge of the lid and its slender gold prop.
line(10, 19, 29, 18, 40, 39, 1, "#090a0d");
line(31, 25, 26, 31, 25, 35, 0, "#b59558");
set(31, 25, 36, "#252226");
// Keyboard shelf and its projecting front lip.
box(9, 9, 19, 39, 15, 23, black);
box(10, 9, 20, 38, 9, 21, gloss);
box(10, 11, 24, 38, 16, 24, "#ded9ca");
for (let x = 11; x <= 37; x++) {
box(x, 11, 25, x, 15, 25, x % 5 === 0 ? "#fffdf2" : ivory);
set(x, 10, 24, "#bbb5a6");
if (x < 37) box(x, 11, 25, x, 11, 25, "#77746d");
}
// Raised black keys, in repeating two-and-three groups.
for (let x = 12; x <= 36; x++) {
if (![0, 3].includes((x - 12) % 7)) {
box(x, 14, 26, x, 16, 26, "#0a0b0e");
set(x, 14, 27, "#24252a");
}
}
box(9, 10, 24, 10, 16, 26, edge);
box(38, 10, 24, 39, 16, 26, edge);
box(10, 16, 26, 38, 16, 27, black);
// Open music rest with two cream pages and tiny printed notes.
box(19, 17, 27, 36, 18, 28, black);
box(20, 18, 29, 35, 18, 35, edge);
box(21, 17, 30, 34, 17, 34, "#dcd5bd");
box(21, 17, 30, 27, 17, 34, "#f3eddc");
box(28, 17, 30, 34, 17, 34, "#e9e2cf");
box(27, 17, 30, 27, 17, 34, "#a59a7e");
for (const x of [23, 25, 29, 31, 33]) {
set(x, 16, 31 + (x % 2), "#45413b");
set(x + 1, 16, 31 + (x % 2), "#45413b");
set(x + 1, 16, 33 + (x % 2), "#6b6458");
}
box(19, 17, 29, 19, 18, 36, edge);
box(35, 17, 29, 35, 18, 36, edge);
box(19, 17, 36, 35, 18, 36, black);
// Matching padded bench in front of the keyboard.
for (const x of [21, 37]) {
for (const y of [3, 8]) {
box(x - 1, y - 1, 1, x + 1, y + 1, 10, "#171719");
box(x - 1, y - 1, 0, x + 1, y + 1, 2, "#a17a3a");
}
}
box(19, 2, 10, 39, 9, 12, edge);
box(20, 3, 13, 38, 8, 13, "#24252a");
box(21, 4, 13, 37, 7, 13, "#2e2f34");
for (const [x, y] of [[25, 5], [31, 5], [36, 5], [28, 7], [34, 7]]) {
set(x, y, 14, "#111216");
}
box(19, 2, 11, 39, 2, 12, gloss);import { draw } from "./assets/voxel";
import { pianoDeCola } from "./assets/piano-de-cola";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, pianoDeCola, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: lo que mide en px su lado más largo
// angle: giro sobre el piso, en radianes
// t: segundos; si se mueve, se anima solo con eso# En una terminal, en la carpeta del juego
fogon assets add piano-de-cola
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["piano-de-cola"] })
# Queda en client/assets/piano-de-cola.ts
# https://fogon.page/object/piano-de-cola