← FantasíaObjeto 3Dfogon/torre-de-mago
Torre de mago
Arrastrá para girarlo// «Torre de mago» · gpt-6-sol (medium)
// A tall slim wizard's tower of round mossy grey stone, slightly crooked and wider at the base, with small arched windows glowing warm yellow, a wooden arched door with steps, a balcony ring near the top, and a tall pointy cone roof of deep purple-blue tiles with a little curl and a golden star at the tip. A small glowing crystal-like window at the top room.
// A slightly crooked, mossy stone tower.
const stone = ["#777f78", "#858c83", "#969b8e", "#69746e"];
const moss = ["#526f54", "#66835a", "#779261"];
const wood = ["#49362f", "#634637", "#79523a"];
const gold = "#eac76a";
const C = z => ({
x: z < 11 ? 23 : z < 23 ? 24 : z < 33 ? 25 : 26,
y: z < 20 ? 24 : 25
});
const R = z => z < 7 ? 12 : z < 18 ? 11 : z < 30 ? 10 : 8;
// Solid round walls, with irregular courses and moss in the crevices.
for (let z = 0; z <= 36; z++) {
const c = C(z), r = R(z);
for (let x = c.x-r; x <= c.x+r; x++)
for (let y = c.y-r; y <= c.y+r; y++) {
const d = Math.hypot(x-c.x, y-c.y);
if (d > r + (rand() < .12 ? .18 : 0)) continue;
let col = stone[Math.floor(rand()*stone.length)];
if (z < 30 && d > r-1.5 && rand() < (z < 12 ? .19 : .08))
col = moss[Math.floor(rand()*moss.length)];
if (d > r-1.4 && z % 4 === 0 && rand() < .24) col = "#59655f";
set(x,y,z,col);
}
}
// Chunky foundation and a few projecting stone courses.
for (let z of [0, 1, 8, 29]) {
let c=C(z), r=R(z)+1;
for (let x=c.x-r; x<=c.x+r; x++)
for (let y=c.y-r; y<=c.y+r; y++) {
let d=Math.hypot(x-c.x,y-c.y);
if (d>r-1.4 && d<=r)
set(x,y,z,rand()<.24 ? "#69736b" : "#92988b");
}
}
// Recessed arched wooden front door.
for (let z=1; z<=8; z++) {
let half=z===8 ? 1 : z===7 ? 2 : 3;
for (let x=23-half; x<=23+half; x++) {
for (let y=10; y<=16; y++) set(x,y,z,null);
set(x,16,z,"#292927");
set(x,12,z,wood[(x+z)%3]);
set(x,11,z,wood[(x+z+1)%3]);
}
}
for (let z=1; z<=7; z++) {
let edge=z===7 ? 3 : 4;
set(23-edge,11,z,"#b0a99a");
set(23+edge,11,z,"#777d73");
}
for (let x=21; x<=25; x++) set(x,11,9,"#aaa899");
for (let z=2; z<=6; z++) set(23,10,z,"#362b2a");
for (let x of [21,25]) {
set(x,10,3,"#a97d47");
set(x,10,6,"#a97d47");
}
set(25,9,4,gold);
set(25,8,4,"#fff0ad");
// Broad, welcoming steps.
box(19,8,0,27,11,0,"#909588");
box(20,9,1,26,11,1,"#aaa99a");
box(21,10,2,25,11,2,"#848a7f");
// Small arched windows set into the curved front wall.
function window(cx, z0, w, h, frontY) {
for (let dz=0; dz<h; dz++) {
let half=dz===h-1 ? w-1 : w;
for (let x=cx-half; x<=cx+half; x++) {
for (let y=frontY; y<=frontY+4; y++) set(x,y,z0+dz,null);
let edge=Math.abs(x-cx)===half || dz===0 || dz===h-1;
set(x,frontY+2,z0+dz,edge ? "#372e34" : "#ffc760");
set(x,frontY+1,z0+dz,edge ? "#b5a394" :
rand()<.28 ? "#fff1a3" : "#f6aa49");
}
}
for (let dz=0; dz<h-1; dz++) {
set(cx-w-1,frontY,z0+dz,"#aaa99a");
set(cx+w+1,frontY,z0+dz,"#747b72");
}
for (let x=cx-w; x<=cx+w; x++) {
set(x,frontY,z0-1,"#777c72");
set(x,frontY,z0+h,"#b0aa99");
}
set(cx,frontY,z0+1,"#fff1b0");
}
window(21,14,2,6,12);
window(28,23,2,5,14);
// A second little window wraps around the visible right-hand curve.
for (let z=17; z<=21; z++) {
let half=z===21 ? 0 : 1;
for (let y=22-half; y<=22+half; y++) {
set(34,y,z,"#342e37");
set(35,y,z,z===21 ? "#c6ad83" : "#f9bd61");
set(36,y,z,rand()<.4 ? "#fff1a1" : "#e9a956");
}
}
box(35,20,16,36,24,16,"#a5a596");
// Projecting balcony: thick floor, spaced balusters and a continuous rail.
for (let z=30; z<=31; z++)
for (let x=11; x<=39; x++)
for (let y=11; y<=39; y++) {
let d=Math.hypot(x-25,y-25);
if (d<=13 && d>=7.5)
set(x,y,z,z===31 ? "#aaa89b" : "#747a75");
}
for (let i=0; i<24; i++) {
let a=i*Math.PI/12, x=Math.round(25+12*Math.cos(a));
let y=Math.round(25+12*Math.sin(a));
box(x,y,32,x,y,34,i%3===0 ? "#aa9f88" : "#8b9287");
}
for (let x=11; x<=39; x++)
for (let y=11; y<=39; y++) {
let d=Math.hypot(x-25,y-25);
if (d>=11.5 && d<=13)
set(x,y,35,rand()<.23 ? "#c0b49a" : "#827f83");
}
// Glowing faceted crystal window in the top room.
for (let z=33; z<=37; z++) {
let half=(z===33 || z===37) ? 0 : z===34 || z===36 ? 1 : 2;
for (let x=26-half; x<=26+half; x++) {
for (let y=15; y<=18; y++) set(x,y,z,null);
set(x,16,z,x<26 ? "#4eddd8" : x>26 ? "#7b6cf5" : "#c4ffff");
set(x,15,z,x===26 ? "#e0ffff" : "#54cfe5");
}
}
for (let z=34; z<=36; z++) {
set(23,15,z,"#a9a299");
set(29,15,z,"#817889");
}
set(26,14,32,gold);
set(26,14,38,gold);
// Deep purple-blue tiled cone, with a wide overhanging eave.
for (let z=37; z<=43; z++) {
let t=(z-37)/7, r=10.9*Math.pow(1-t,.82);
for (let x=14; x<=38; x++)
for (let y=13; y<=37; y++) {
let d=Math.hypot(x-26,y-25);
if (d>r) continue;
let tile=(Math.floor((x+y*2)/3)+Math.floor(z/2))%4;
let col=["#292947","#373158","#48366b","#30395d"][tile];
if (d>r-1.5 && rand()<.16) col="#625184";
set(x,y,z,col);
}
}
for (let x=14; x<=38; x++)
for (let y=13; y<=37; y++) {
let d=Math.hypot(x-26,y-25);
if (d>=9.4 && d<=11.5)
set(x,y,37,rand()<.25 ? "#78608d" : "#363251");
}
// Curled roof finial and a bright little five-point star.
set(26,25,43,"#544074");
set(27,25,44,"#544074");
set(28,25,44,"#75628d");
set(29,24,44,"#fff0a0");
for (let [dx,dz] of [[-2,0],[-1,0],[1,0],[2,0],[0,-1],[0,1],
[-1,-1],[1,-1],[-1,1],[1,1]])
set(29+dx,24,dz+44,Math.abs(dx)+Math.abs(dz)>1 ? "#d9a949" : "#ffe17a");
set(29,23,44,"#fff9c4");
// Little moss tufts and storybook mushrooms on the lower stones.
for (let i=0; i<38; i++) {
let z=1+Math.floor(rand()*14), c=C(z), r=R(z);
let a=rand()*Math.PI*2;
let x=Math.round(c.x+r*Math.cos(a)), y=Math.round(c.y+r*Math.sin(a));
set(x,y,z,moss[Math.floor(rand()*moss.length)]);
if (rand()<.25) set(x,y,z+1,"#83a46a");
}
for (let [x,y] of [[13,19],[34,18],[14,29],[33,31]]) {
set(x,y,0,"#e8d6b7");
set(x,y,1,rand()<.5 ? "#cc6980" : "#ac76ad");
set(x,y,2,"#e4a4a4");
set(x,y-1,1,"#fff3d0");
}import { draw } from "./assets/voxel";
import { torreDeMago } from "./assets/torre-de-mago";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, torreDeMago, 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 torre-de-mago
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["torre-de-mago"] })
# Queda en client/assets/torre-de-mago.ts
# https://fogon.page/object/torre-de-mago