← Ancient and prehistory3D assetfogon/carro-egipcio
Carro egipcio
Drag to turn it// «Carro egipcio» · gpt-6-sol (medium)
// An Egyptian war chariot: a light open cart of gold and wood with a curved front panel decorated with blue patterns, two big six-spoke wooden wheels on the sides, and a long pole sticking out forward (-y) with a yoke. No horse.
const wood = "#9b572b";
const woodLight = "#c47b38";
const woodDark = "#713d25";
const gold = "#e5ad39";
const goldLight = "#ffd66b";
const goldDark = "#ae7627";
const lapis = "#244c9b";
const blue = "#3778bd";
const turquoise = "#42c9c1";
const frontY = x => {
const t = Math.abs(x - 24) / 8;
return 16 + Math.round(4 * t * t);
};
// Axle, visible between the wheels.
box(10, 26, 10, 38, 28, 12, woodDark);
box(15, 26, 12, 33, 27, 13, goldDark);
// Shaped wooden floor: its front edge follows the curved shield.
for (let x = 16; x <= 32; x++) {
for (let y = frontY(x); y <= 36; y++) {
for (let z = 7; z <= 9; z++) {
set(x, y, z, z === 9 ? woodLight : wood);
}
if (y > 21 && y < 35 && y % 4 === 0) set(x, y, 9, "#d08a42");
}
}
for (let x = 16; x <= 32; x++) {
set(x, 36, 8, goldDark);
set(x, 36, 9, gold);
}
box(16, 35, 7, 32, 36, 7, woodDark);
// Curved, solid front shield, higher at its swept-back ends.
for (let x = 16; x <= 32; x++) {
const y = frontY(x);
const rise = Math.round(4 * Math.pow(Math.abs(x - 24) / 8, 2));
const top = 19 + rise;
for (let z = 10; z <= top; z++) {
const c = z <= 11 ? goldDark : z === top ? goldLight : gold;
set(x, y, z, c);
set(x, y + 1, z, z < 12 ? woodDark : goldDark);
}
// Bright rim and a bold lapis stripe on the viewer-facing surface.
set(x, y - 1, top, goldLight);
set(x, y - 1, 11, goldLight);
for (let z = 13; z <= 14; z++) set(x, y - 1, z, lapis);
if (x % 3 === 0) set(x, y - 1, 14, turquoise);
}
// Turquoise lotus-and-sun ornament above the blue stripe.
for (let dx = -6; dx <= 6; dx++) {
const x = 24 + dx, y = frontY(x) - 1;
if (Math.abs(dx) <= 2) set(x, y, 16, turquoise);
if (Math.abs(dx) === 3 || Math.abs(dx) === 4) set(x, y, 15, turquoise);
if (Math.abs(dx) <= 1) set(x, y, 17, blue);
}
set(24, frontY(24) - 1, 18, goldLight);
for (const x of [18, 30]) {
const y = frontY(x) - 1;
set(x, y, 17, lapis);
set(x, y, 18, turquoise);
}
// Open sides: low wooden guards with gilded top rails and rear posts.
for (const x of [16, 32]) {
box(x, 22, 10, x, 35, 12, wood);
box(x, 22, 13, x, 35, 13, goldDark);
box(x, 23, 16, x, 35, 16, goldLight);
for (const y of [24, 29, 34]) {
box(x, y, 13, x, y, 16, gold);
set(x, y, 15, turquoise);
}
box(x, 35, 10, x, 36, 18, goldDark);
box(x, 35, 18, x, 36, 19, goldLight);
set(x, 34, 19, lapis);
}
// Long central pole and broad, slightly swept yoke.
box(23, 3, 8, 25, 19, 9, wood);
box(24, 3, 10, 24, 18, 10, goldDark);
box(23, 1, 8, 25, 3, 9, gold);
box(24, 1, 9, 24, 2, 10, goldLight);
box(13, 4, 8, 35, 6, 9, woodLight);
box(13, 4, 10, 35, 5, 10, gold);
for (const x of [13, 14, 34, 35]) {
box(x, 4, 8, x, 7, 11, gold);
set(x, 4, 11, goldLight);
}
for (const x of [17, 20, 28, 31]) {
box(x, 4, 10, x, 5, 10, lapis);
set(x, 4, 11, turquoise);
}
// Each wheel is a separate spinning part. Their planes are perpendicular
// to the axle, so rotation around x rolls them forward.
function makeWheel(name, cx) {
const cy = 27, cz = 11;
part(name, [cx, cy, cz]);
for (let x = cx - 2; x <= cx + 1; x++) {
for (let y = cy - 11; y <= cy + 11; y++) {
for (let z = 0; z <= 22; z++) {
const r = Math.hypot(y - cy, z - cz);
if (r >= 8.9 && r <= 11.1) {
const outerFace = x === cx - 2 || x === cx + 1;
set(x, y, z, outerFace ? woodLight : wood);
if (outerFace && r > 10.25) set(x, y, z, gold);
if (outerFace && r < 9.5) set(x, y, z, goldDark);
}
}
}
}
// Six thick spokes, with gilded tips.
for (let i = 0; i < 6; i++) {
const a = i * Math.PI / 3;
const dy = Math.cos(a), dz = Math.sin(a);
line(cx, cy, cz, cx, cy + 9 * dy, cz + 9 * dz, 1, woodLight);
line(cx - 1, cy + 7.5 * dy, cz + 7.5 * dz,
cx - 1, cy + 9 * dy, cz + 9 * dz, 0, gold);
}
cylinder(cx - 2, cy, cz, 2, 4, goldDark, "x");
cylinder(cx - 2, cy, cz, 1, 1, goldLight, "x");
cylinder(cx + 1, cy, cz, 1, 1, goldLight, "x");
// Rivets spaced around the outside face.
const outside = cx < 24 ? cx - 2 : cx + 1;
for (let i = 0; i < 12; i++) {
const a = i * Math.PI / 6;
set(outside, cy + 10 * Math.cos(a), cz + 10 * Math.sin(a), goldLight);
}
animate(name, { type: "spin", axis: "x", speed: 3 });
}
makeWheel("left wheel", 10);
makeWheel("right wheel", 39);
part("body");import { draw } from "./assets/voxel";
import { carroEgipcio } from "./assets/carro-egipcio";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, carroEgipcio, 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 carro-egipcio
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["carro-egipcio"] })
# It lands in client/assets/carro-egipcio.ts
# https://fogon.page/object/carro-egipcio