← Kit de nivelesObjeto 3Dfogon/nivel-puerta
Puerta
Arrastrá para girarlo// «Puerta» · gpt-6-sol (medium)
// A modular wall segment with a door, matching the brick wall: exactly 48 blocks long on x (x 0..47), 10 thick on y (y 19..28), 40 tall, red bricks in running bond with light grey mortar and a light grey stone cap on top. In the middle, an arched opening 18 wide and 28 tall with a light stone arch frame. Inside it, a wooden door leaf (brown vertical planks in 2 shades, two dark iron bands, a round gold knob on the right) 2 blocks thick, set at the front of the opening. The door leaf is a separate part hinged on its left edge.
const brick = ["#c95740", "#dc694b", "#e77755"];
const mortar = "#deddd4";
const stone = ["#c5c9c8", "#d9dcda", "#edf0eb"];
function opening(x, z) {
if (z < 0 || z > 27 || x < 15 || x > 32) return false;
if (z <= 18) return true;
const t = (z - 18) / 10;
return Math.abs(x - 23.5) <= 9 * Math.sqrt(1 - t * t);
}
function nearOpening(x, z) {
for (let dz = -2; dz <= 2; dz++) {
for (let dx = -2; dx <= 2; dx++) {
if (opening(x + dx, z + dz)) return true;
}
}
return false;
}
// Running-bond brickwork, with mortar joints continuing through the wall.
for (let z = 0; z <= 36; z++) {
const course = Math.floor(z / 4);
const shift = course % 2 ? 4 : 0;
for (let x = 0; x < 48; x++) {
if (opening(x, z)) continue;
const frame = nearOpening(x, z);
let color;
if (frame) {
// Large, clean stone voussoirs around the arch.
const joint = z <= 18
? (z % 5 === 0)
: ((x + 48) % 5 === 0 && z >= 21);
color = joint ? stone[0] : stone[z % 6 === 0 ? 2 : 1];
} else if (z % 4 === 0 || (x + shift) % 8 === 0) {
color = mortar;
} else {
color = brick[(Math.floor((x + shift) / 8) + course * 2) % 3];
if (z % 4 === 3) color = brick[2];
}
for (let y = 19; y <= 28; y++) set(x, y, z, color);
}
}
// Continuous light-stone cap, kept inside the modular footprint.
box(0, 19, 37, 47, 28, 37, stone[0]);
box(0, 19, 38, 47, 28, 38, stone[1]);
box(0, 19, 39, 47, 28, 39, stone[2]);
// The leaf is attached at its left edge, independently of the masonry.
part("puerta", [15, 20, 0]);
function inDoor(x, z) {
if (x < 16 || x > 31 || z < 0 || z > 25) return false;
if (z <= 17) return true;
const t = (z - 17) / 9;
return Math.abs(x - 23.5) <= 8 * Math.sqrt(1 - t * t);
}
for (let z = 0; z <= 25; z++) {
for (let x = 16; x <= 31; x++) {
if (!inDoor(x, z)) continue;
const plank = Math.floor((x - 16) / 3);
const wood = plank % 2 ? "#a95e32" : "#c5773b";
set(x, 20, z, "#824828");
set(x, 19, z, (x - 16) % 3 === 2 ? "#874923" : wood);
}
}
// Chunky iron straps and hinge plates on the visible face.
for (const z of [6, 7, 17, 18]) {
for (let x = 16; x <= 31; x++) {
if (inDoor(x, z)) set(x, 19, z, z === 7 || z === 18 ? "#485158" : "#303940");
}
}
for (const z of [4, 5, 14, 15]) {
box(16, 19, z, 17, 19, z, "#41494e");
set(17, 19, z, "#87908c");
}
// Round gold knob on the right, with a bright highlight.
for (let z = 10; z <= 12; z++) {
for (let x = 28; x <= 30; x++) {
if (Math.abs(x - 29) + Math.abs(z - 11) <= 2) {
set(x, 19, z, "#d99520");
}
}
}
set(29, 19, 11, "#ffe277");
set(28, 19, 12, "#fff0a1");
animate("puerta", { type: "swing", axis: "z", speed: 0.7, amplitude: 0.9 });import { draw } from "./assets/voxel";
import { nivelPuerta } from "./assets/nivel-puerta";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, nivelPuerta, 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 nivel-puerta
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["nivel-puerta"] })
# Queda en client/assets/nivel-puerta.ts
# https://fogon.page/object/nivel-puerta