← Animals3D assetfogon/tortuga
Tortuga
Drag to turn it// «Tortuga» · gpt-6-sol (medium)
// A cartoon land tortoise, horizontal along y, head at the front (-y): a high domed shell in dark green with lighter green hexagon plates outlined in brown, a wide flat shell rim, a wrinkly olive head with black dot eyes and a little smile poking out the front, four stubby olive legs at the corners and a tiny tail.
// Chunky body beneath the shell.
ellipsoid(24, 25, 12, 13, 15, 8, "#6f8b3e");
ellipsoid(24, 24, 15, 11, 13, 5, "#819d49");
// Tiny pointed tail.
line(24, 39, 11, 24, 45, 9, 2, "#718d3f");
set(24, 46, 9, "#819d49");
// Wide, flat shell rim.
for (let x = 4; x <= 44; x++) {
for (let y = 6; y <= 44; y++) {
const d = ((x - 24) / 20) ** 2 + ((y - 25) / 19) ** 2;
if (d > 1) continue;
for (let z = 12; z <= 15; z++) {
let color = z === 12 ? "#35472a" : "#496332";
if (d > 0.87) color = z === 15 ? "#765936" : "#59452d";
else if (d > 0.72) color = z === 15 ? "#658440" : "#405c31";
else if (z === 15) color = "#527439";
set(x, y, z, color);
}
}
}
// Domed shell with a tessellation of brown-outlined green hexagonal plates.
function plateAt(x, y) {
let first = Infinity, second = Infinity, chosen = 0;
for (let row = -2; row <= 5; row++) {
const cy = 12 + row * 7.8;
for (let col = -3; col <= 4; col++) {
const cx = 10 + col * 9 + (Math.abs(row) % 2) * 4.5;
const d = Math.hypot(x - cx, y - cy);
if (d < first) {
second = first;
first = d;
chosen = row * 17 + col;
} else if (d < second) {
second = d;
}
}
}
return { edge: second - first < 1.15, chosen };
}
for (let x = 7; x <= 41; x++) {
for (let y = 8; y <= 42; y++) {
const d = ((x - 24) / 17) ** 2 + ((y - 25) / 16) ** 2;
if (d > 1) continue;
const top = Math.round(15 + 17 * Math.sqrt(1 - d));
const plate = plateAt(x, y);
const shade = ["#649844", "#72a34a", "#79a950", "#60913e"][
Math.abs(plate.chosen * 7 + 19) % 4
];
for (let z = 16; z <= top; z++) {
let color = z < top - 2 ? "#35552e" : shade;
if (z < 20 && z < top - 1) color = "#405e30";
if (z >= top - 2 && plate.edge) color = "#705535";
if (z === top && !plate.edge && rand() < 0.065)
color = "#87b35a";
set(x, y, z, color);
}
}
}
// Each foot is a separate walking part.
function leg(name, x, y, speed) {
part(name, [x, y, 11]);
ellipsoid(x, y, 5, 5, 5, 6, "#728e40");
ellipsoid(x, y - 2, 2, 5, 5, 2, "#829e49");
// Broad toes and three little pale nails.
for (const dx of [-3, 0, 3]) {
ellipsoid(x + dx, y - 4, 2, 2, 2, 2, "#8da950");
set(x + dx, y - 5, 1, "#c1b77a");
set(x + dx, y - 5, 2, "#c8bf83");
}
// A couple of simple skin folds.
line(x - 3, y, 8, x - 1, y + 1, 8, 0, "#5c7737");
animate(name, { type: "swing", axis: "x", speed, amplitude: 0.2 });
}
leg("front-left", 12, 13, 3);
leg("front-right", 36, 13, -3);
leg("rear-left", 12, 36, -3);
leg("rear-right", 36, 36, 3);
// Big friendly head, attached at the neck.
part("head", [24, 14, 16]);
ellipsoid(24, 13, 15, 7, 6, 5, "#708d3d");
ellipsoid(24, 9, 16, 8, 7, 7, "#819e47");
ellipsoid(24, 7, 13, 6, 4, 3, "#90a950");
// Cheeks and a few short wrinkles.
ellipsoid(18, 7, 14, 2, 2, 2, "#8eaa4e");
ellipsoid(30, 7, 14, 2, 2, 2, "#8eaa4e");
line(17, 10, 17, 18, 12, 16, 0, "#607c38");
line(31, 10, 17, 30, 12, 16, 0, "#607c38");
line(18, 10, 13, 19, 12, 12, 0, "#647f38");
line(30, 10, 13, 29, 12, 12, 0, "#647f38");
// Black dot eyes with white glints.
for (const x of [20, 28]) {
ellipsoid(x, 4, 19, 1.5, 1, 1.5, "#1d261b");
set(x, 3, 20, "#ffffff");
}
// Tiny nostrils and a curved smile on the front of the muzzle.
set(22, 3, 15, "#526b36");
set(26, 3, 15, "#526b36");
set(21, 4, 12, "#455b30");
set(22, 3, 11, "#455b30");
line(23, 3, 11, 25, 3, 11, 0, "#455b30");
set(26, 3, 11, "#455b30");
set(27, 4, 12, "#455b30");
animate("head", { type: "bob", axis: "x", speed: 2, amplitude: 0.15 });
part("body", [24, 25, 12]);import { draw } from "./assets/voxel";
import { tortuga } from "./assets/tortuga";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, tortuga, 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 tortuga
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["tortuga"] })
# It lands in client/assets/tortuga.ts
# https://fogon.page/object/tortuga