← Ancient and prehistory3D assetfogon/street-awning
Toldo de calle
Drag to turn it// «Toldo de calle» · propio
// A cloth awning hung across a street: four tall dark wooden poles holding a sagging blue and cream striped cloth, with ropes at the corners.
// A cloth awning hung across a street: four tall dark wooden poles on stone feet hold a sagging blue and cream
// striped cloth, with ropes at the corners.
const pole = ["#35251a", "#463222", "#57402c", "#684d36"];
const blue = ["#22566f", "#2f6f8f", "#3d84a6", "#52a0c2"];
const cream = ["#cbb68c", "#dcc9a0", "#ead9b6", "#f5e8cb"];
const stone = ["#a88250", "#b8925a", "#c9a56c"];
const rope = "#b89a68";
const clampi = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
const X0 = 5, X1 = 42, Y0 = 9, Y1 = 38, HIGH = 38;
// The cloth hangs lowest in the middle.
function clothZ(x, y) {
const u = (x - (X0 + X1) / 2) / ((X1 - X0) / 2), v = (y - (Y0 + Y1) / 2) / ((Y1 - Y0) / 2);
return HIGH - 8.5 * (1 - u * u) * (1 - v * v * 0.35) - 2.2 * (1 - v * v);
}
// The poles (2×2) on their feet, with a knob on top.
for (const px of [X0 - 1, X1])
for (const py of [Y0 - 1, Y1]) {
box(px - 1, py - 1, 0, px + 2, py + 2, 2, stone[1]);
box(px - 1, py - 1, 2, px + 2, py + 2, 2, stone[2]);
for (let z = 3; z <= HIGH + 2; z++) for (let i = 0; i < 2; i++) for (let j = 0; j < 2; j++) set(px + i, py + j, z, pole[clampi((i === 0 ? 2 : 1) + (j === 0 ? 1 : 0) - (z % 9 === 0 ? 1 : 0), 0, 3)]);
box(px, py, HIGH + 3, px + 1, py + 1, HIGH + 3, pole[3]);
box(px - 1, py - 1, HIGH - 1, px + 2, py + 2, HIGH - 1, rope);
}
// The cloth: stripes across the street, two layers (the under one in shade).
for (let x = X0; x <= X1; x++) {
const s = Math.floor((x - X0) / 4) % 2 === 0;
const tones = s ? blue : cream;
const fold = (x - X0) % 4 === 0 ? 1 : 0;
for (let y = Y0; y <= Y1; y++) {
const z = Math.round(clothZ(x, y));
const hem = y === Y0 || y === Y1 || x === X0 || x === X1;
set(x, y, z, tones[clampi(3 - fold - (hem ? 1 : 0) - (rand() < 0.1 ? 1 : 0), 0, 3)]);
set(x, y, z - 1, tones[clampi(1 - fold, 0, 3)]);
}
}
// A fringe along the two long edges.
for (let x = X0; x <= X1; x += 2)
for (const y of [Y0, Y1]) set(x, y, Math.round(clothZ(x, y)) - 2, cream[1]);
// Ropes: from each pole down and out to a peg.
for (const [px, py, sx, sy] of [[X0 - 1, Y0 - 1, -1, -1], [X1 + 1, Y0 - 1, 1, -1], [X0 - 1, Y1 + 1, -1, 1], [X1 + 1, Y1 + 1, 1, 1]]) {
line(px, py, HIGH - 1, px + sx * 3, py + sy * 6, 0, 0, rope);
box(px + sx * 3, py + sy * 6, 0, px + sx * 3, py + sy * 6, 1, pole[1]);
}import { draw } from "./assets/voxel";
import { streetAwning } from "./assets/street-awning";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, streetAwning, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: its longest side, in px
// angle: turn on the floor, in radians
// t: seconds; if it moves, that animates it# In a terminal, in the game's folder
fogon assets add street-awning
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["street-awning"] })
# It lands in client/assets/street-awning.ts
# https://fogon.gg/object/street-awning