← Medieval3D assetfogon/ariete
Ariete
Drag to turn it// «Ariete» · gpt-6-sol (medium)
// A medieval battering ram: a big wooden frame on four solid wooden wheels, with a sloped plank roof covered in hides, and under it a huge log ram hanging from two chains, its front end capped with a black iron head shaped like a ram's head pointing forward (-y).
const wood = "#513320";
const woodDark = "#382318";
const woodLight = "#785036";
const iron = "#25282a";
const ironLight = "#4c5355";
const gold = "#c59a4c";
// Four solid wheels with iron tires and wooden hubs.
for (const wy of [14, 35]) {
for (const side of ["left", "right"]) {
const x0 = side === "left" ? 5 : 39;
const face = side === "left" ? 5 : 42;
cylinder(x0, wy, 6, 6, 4, woodDark, "x");
cylinder(x0, wy, 6, 4, 4, wood, "x");
for (let a = 0; a < 360; a += 3) {
const t = a * Math.PI / 180;
const yy = Math.round(wy + 5.5 * Math.cos(t));
const zz = Math.round(6 + 5.5 * Math.sin(t));
for (let x = x0; x <= x0 + 3; x++) {
set(x, yy, zz, a % 24 < 8 ? ironLight : iron);
}
}
for (let a = 0; a < 360; a += 45) {
const t = a * Math.PI / 180;
line(face, wy, 6,
face, wy + 4 * Math.cos(t), 6 + 4 * Math.sin(t),
0, woodLight);
}
cylinder(face, wy, 6, 2, 1, ironLight, "x");
set(face, wy, 6, gold);
}
}
// Heavy chassis and wheel axles.
for (const yy of [14, 35]) {
box(9, yy - 1, 5, 38, yy + 1, 7, woodDark);
box(10, yy, 7, 37, yy, 8, woodLight);
}
for (const xx of [12, 36]) {
box(xx - 2, 10, 8, xx + 2, 39, 10, woodDark);
box(xx - 1, 11, 10, xx + 1, 38, 11, woodLight);
}
// Posts, side rails, and diagonal braces.
for (const xx of [12, 36]) {
for (const yy of [12, 37]) {
box(xx - 2, yy - 2, 8, xx + 2, yy + 2, 30, woodDark);
box(xx - 1, yy - 2, 11, xx, yy - 2, 29, woodLight);
for (const z of [10, 25]) {
box(xx - 2, yy - 2, z, xx + 2, yy + 2, z + 1, iron);
}
set(xx, yy - 2, 26, gold);
}
box(xx - 1, 12, 24, xx + 1, 37, 26, wood);
box(xx - 1, 12, 24, xx - 1, 37, 24, woodLight);
line(xx, 15, 10, xx, 23, 23, 1, wood);
line(xx, 34, 10, xx, 27, 23, 1, wood);
}
for (const yy of [11, 38]) {
box(12, yy, 27, 36, yy + 1, 29, woodDark);
line(12, yy, 30, 24, yy, 38, 1, wood);
line(24, yy, 38, 36, yy, 30, 1, wood);
}
// Ridge and rafters.
box(23, 9, 36, 25, 40, 38, woodDark);
for (const yy of [11, 20, 29, 38]) {
line(10, yy, 30, 24, yy, 38, 1, wood);
line(24, yy, 38, 38, yy, 30, 1, wood);
}
// Sloping roof of stitched, irregular hides.
const hides = ["#756750", "#8a775b", "#a08b69", "#695c4b"];
for (let x = 9; x <= 39; x++) {
const z = 39 - Math.floor(Math.abs(x - 24) * 0.53);
for (let y = 9; y <= 40; y++) {
const patch = (
Math.floor((y - 9) / 7) * 3 +
Math.floor(Math.abs(x - 24) / 7)
) % hides.length;
const color = rand() < 0.09
? hides[(patch + 1) % hides.length]
: hides[patch];
set(x, y, z - 1, woodDark);
set(x, y, z, color);
if (y % 7 === 1) set(x, y, z, "#4c4035");
}
}
box(23, 8, 39, 25, 41, 39, woodDark);
for (const x of [9, 39]) {
for (let y = 10; y <= 40; y += 3) {
set(x, y, 31, gold);
}
}
for (let x = 10; x <= 38; x += 3) {
const z = 39 - Math.floor(Math.abs(x - 24) * 0.53);
set(x, 9, z, "#c6ac80");
set(x, 10, z, iron);
}
// Small heraldic banners on the open sides.
for (const x of [10, 38]) {
const banner = x === 10 ? "#852f36" : "#304d83";
box(x, 20, 20, x, 27, 26, banner);
for (let y = 20; y <= 27; y++) {
set(x, y, 26, gold);
if (y % 2 === 0) set(x, y, 20, gold);
}
box(x, 23, 22, x, 24, 24, gold);
set(x, 23, 23, banner);
}
// Chains and log move together beneath the roof.
part("ram", [24, 24, 30]);
animate("ram", {
type: "swing",
axis: "x",
speed: 2,
amplitude: 0.35
});
for (const yy of [15, 34]) {
for (const xx of [20, 28]) {
set(xx, yy, 30, ironLight);
for (let z = 21; z <= 29; z++) {
set(xx, yy, z, z % 2 ? ironLight : iron);
if (z % 3 === 0) {
set(xx + (xx < 24 ? 1 : -1), yy, z, iron);
}
}
set(xx, yy, 20, gold);
}
}
// Solid wooden ram with grain and iron bindings.
cylinder(24, 9, 17, 4, 31, woodDark, "y");
cylinder(24, 10, 17, 3, 29, wood, "y");
for (let y = 13; y <= 37; y++) {
for (const x of [22, 25, 27]) {
if (rand() < 0.72) set(x, y, 20, woodLight);
}
}
for (const y of [13, 19, 32, 37]) {
cylinder(24, y, 17, 5, 2, iron, "y");
for (const x of [20, 24, 28]) {
set(x, y, 21, ironLight);
}
set(24, y, 22, gold);
}
cylinder(24, 39, 17, 3, 1, "#9b7147", "y");
set(24, 39, 17, woodDark);
for (const [x, z] of [[22, 16], [26, 16], [24, 19]]) {
set(x, 39, z, woodDark);
}
// Forward-facing forged ram's head: muzzle, brow, ears, and curled horns.
cylinder(24, 8, 17, 5, 5, iron, "y");
box(20, 5, 17, 28, 10, 22, iron);
box(21, 4, 15, 27, 8, 19, iron);
box(22, 3, 15, 26, 6, 18, ironLight);
box(20, 5, 21, 28, 7, 23, "#363c3e");
box(18, 8, 20, 20, 11, 22, iron);
box(28, 8, 20, 30, 11, 22, iron);
for (const s of [-1, 1]) {
line(24 + s * 4, 9, 22, 24 + s * 8, 10, 25, 2, iron);
line(24 + s * 8, 10, 25, 24 + s * 10, 7, 24, 1, ironLight);
line(24 + s * 10, 7, 24, 24 + s * 8, 5, 21, 1, iron);
set(24 + s * 7, 8, 26, ironLight);
}
for (const x of [21, 27]) {
set(x, 4, 20, gold);
set(x, 3, 16, iron);
}
set(24, 3, 18, gold);
set(24, 5, 22, ironLight);import { draw } from "./assets/voxel";
import { ariete } from "./assets/ariete";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, ariete, 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 ariete
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["ariete"] })
# It lands in client/assets/ariete.ts
# https://fogon.page/object/ariete