← Ancient and prehistory3D assetfogon/clay-pots
Vasijas de barro
Drag to turn it// «Vasijas de barro» · propio
// Three terracotta clay pots of different sizes standing together: round bellies, narrow necks and flared lips, the biggest with a darker painted band.
// Three terracotta pots of different sizes: round bellies, narrow necks and flared lips; the biggest has a painted
// band, the middle one two little handles.
const clay = ["#8f4628", "#a35432", "#b5623c", "#c8744a", "#d98a5c", "#e6a076"];
const inside = "#5e2c18";
const band = "#5c2817";
const paint = "#ecd3a8";
const clampi = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
// The shape: radius at each height, for a pot one unit tall.
const SHAPE = [[0, 0.19], [0.06, 0.26], [0.3, 0.37], [0.5, 0.395], [0.68, 0.33], [0.8, 0.2], [0.88, 0.15], [0.94, 0.17], [1, 0.215]];
function radiusAt(t) {
for (let i = 0; i < SHAPE.length - 1; i++) {
const [t0, r0] = SHAPE[i], [t1, r1] = SHAPE[i + 1];
if (t >= t0 && t <= t1) {
const k = (t - t0) / (t1 - t0);
const s = k * k * (3 - 2 * k);
return r0 + (r1 - r0) * s;
}
}
return SHAPE[SHAPE.length - 1][1];
}
function pot(cx, cy, tall, opts = {}) {
for (let z = 0; z < tall; z++) {
const t = z / (tall - 1);
const r = radiusAt(t) * tall;
const above = radiusAt(Math.min(1, t + 0.06)) * tall;
for (let x = Math.floor(cx - r - 1); x <= Math.ceil(cx + r + 1); x++)
for (let y = Math.floor(cy - r - 1); y <= Math.ceil(cy + r + 1); y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > r) continue;
if (z > 1 && d < r - 1.8) continue; // hollow
if (d < r - 0.95 && z > 1) {
set(x, y, z, inside);
continue;
}
// Lighter where it faces up and towards the light (front left).
let tone = 2 + (above < r - 0.25 ? 1 : above > r + 0.25 ? -1 : 0);
const side = ((cx - x) + (cy - y)) / (r * 1.6);
tone += side > 0.45 ? 1 : side < -0.45 ? -1 : 0;
if (t > 0.93) tone++;
if (rand() < 0.1) tone--;
let c = clay[clampi(tone, 0, 5)];
if (opts.band && t > 0.4 && t < 0.6) {
const a = Math.round((Math.atan2(y - cy, x - cx) + Math.PI) * r * 0.55);
const zig = (a + Math.abs(((z - Math.round(tall * 0.4)) % 6) - 3)) % 6 === 0;
const edge = t < 0.425 || t > 0.575;
c = edge ? paint : zig ? paint : band;
}
if (opts.stripes && (z === Math.round(tall * 0.62) || z === Math.round(tall * 0.7))) c = band;
set(x, y, z, c);
}
}
if (opts.handles) {
// Two ears from the shoulder to the neck.
const z0 = Math.round(tall * 0.66), z1 = Math.round(tall * 0.9);
for (const s of [-1, 1]) {
const r0 = radiusAt(0.66) * tall, r1 = radiusAt(0.9) * tall;
const out = Math.max(r0, r1) + 2.2;
line(cx + s * (r0 - 0.5), cy, z0, cx + s * out, cy, (z0 + z1) / 2, 0.6, clay[3]);
line(cx + s * out, cy, (z0 + z1) / 2, cx + s * (r1 - 0.5), cy, z1, 0.6, clay[4]);
}
}
}
pot(15, 31, 36, { band: true });
pot(37, 23, 25, { handles: true });
pot(17, 8, 18, { stripes: true });import { draw } from "./assets/voxel";
import { clayPots } from "./assets/clay-pots";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, clayPots, 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 clay-pots
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["clay-pots"] })
# It lands in client/assets/clay-pots.ts
# https://fogon.gg/object/clay-pots