← FantasíaObjeto 3Dfogon/alfombra-voladora
Alfombra voladora
Arrastrá para girarlo// «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");
}
}
}import { draw } from "./assets/voxel";
import { alfombraVoladora } from "./assets/alfombra-voladora";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, alfombraVoladora, 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 alfombra-voladora
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["alfombra-voladora"] })
# Queda en client/assets/alfombra-voladora.ts
# https://fogon.page/object/alfombra-voladora