← Monstruos y enemigosObjeto 3Dfogon/babosa
Babosa
Arrastrá para girarlo// «Babosa» · gpt-6-sol (medium)
// A big cartoon slug, horizontal and low on the ground: a long soft body in sickly yellow-green with a lighter belly and dark spots, a slimy trail behind, and at the front (-y) two long eye stalks with glowing orange eyes and a wide grumpy mouth.
// A slick trail stays on the floor while the slug bobs above it.
for (let y = 30; y <= 47; y++) {
const width = y < 39 ? 9 + (y - 30) * 0.55 : 14 - (y - 39) * 0.95;
for (let x = 9; x <= 39; x++) {
const wobble = Math.sin(y * 0.75) * 1.5;
if (Math.abs(x - 24 - wobble) > width || rand() < 0.09) continue;
set(x, y, 0, rand() < 0.28 ? "#69b486" : "#4b9475");
if (rand() < 0.12) set(x, y, 1, "#9bd9a0");
}
}
for (let i = 0; i < 45; i++) {
const x = 12 + Math.floor(rand() * 25);
const y = 39 + Math.floor(rand() * 9);
if (!get(x, y, 0)) set(x, y, 0, "#7ac99a");
}
part("body", [24, 24, 1]);
// Overlapping rounded volumes make a broad head, plump back, and tapered tail.
const lobes = [
[24, 25, 9, 16, 18, 10],
[24, 14, 10, 13, 10, 9],
[24, 36, 6, 11, 10, 6]
];
for (let x = 7; x <= 41; x++) {
for (let y = 3; y <= 45; y++) {
for (let z = 0; z <= 20; z++) {
let inside = false;
for (const [cx, cy, cz, rx, ry, rz] of lobes) {
const d = ((x - cx) / rx) ** 2 +
((y - cy) / ry) ** 2 +
((z - cz) / rz) ** 2;
if (d <= 1) { inside = true; break; }
}
if (!inside) continue;
let color;
const side = Math.abs(x - 24);
if (z <= 2) color = "#536d29";
else if (z <= 5 && (side > 9 || y < 11)) color = "#cfda77";
else if (z >= 14) color = "#b1cc43";
else if (side > 12 || z < 7) color = "#789630";
else color = "#99b936";
if (rand() < 0.055 && z > 4) color = "#a9c447";
set(x, y, z, color);
}
}
}
// Broad, readable patches on the back, following its actual surface.
for (const [sx, sy, radius] of [
[17, 19, 2], [29, 20, 2], [23, 25, 3],
[32, 29, 2], [16, 32, 2], [25, 35, 2]
]) {
for (let x = sx - radius; x <= sx + radius; x++) {
for (let y = sy - radius; y <= sy + radius; y++) {
if ((x - sx) ** 2 + (y - sy) ** 2 > radius ** 2) continue;
for (let z = 20; z >= 7; z--) {
if (get(x, y, z)) {
set(x, y, z, rand() < 0.2 ? "#637e2b" : "#718b2b");
break;
}
}
}
}
}
// Smaller spots run down both flanks.
for (const [sy, sz, radius] of [
[16, 12, 2], [22, 9, 2], [28, 13, 2],
[34, 8, 2], [39, 6, 1]
]) {
for (const side of [-1, 1]) {
for (let y = sy - radius; y <= sy + radius; y++) {
for (let z = sz - radius; z <= sz + radius; z++) {
if ((y - sy) ** 2 + (z - sz) ** 2 > radius ** 2) continue;
for (let x = side < 0 ? 7 : 41;
side < 0 ? x <= 24 : x >= 24;
x -= side) {
if (get(x, y, z)) {
set(x, y, z, "#566f28");
break;
}
}
}
}
}
}
// Find the visible front surface so the expression follows the round face.
function front(x, z) {
for (let y = 2; y <= 16; y++) if (get(x, y, z)) return y;
return -1;
}
// Wide, downturned grumpy mouth and a pale lower lip.
for (let x = 15; x <= 33; x++) {
const t = 1 - Math.abs(x - 24) / 9;
const upper = 8 + Math.round(2 * t);
const lower = 7 + Math.round(t);
for (let z = lower; z <= upper; z++) {
const y = front(x, z);
if (y >= 0) set(x, y - 1, z, "#344522");
}
const lipY = front(x, lower - 1);
if (lipY >= 0) set(x, lipY - 1, lower - 1, "#e0df87");
}
for (const x of [19, 29]) {
const z = 8;
const y = front(x, z);
if (y >= 0) set(x, y - 2, z, "#f1e9a5");
}
for (const x of [21, 27]) {
const y = front(x, 13);
if (y >= 0) set(x, y - 1, 13, "#5b7429");
}
animate("body", { type: "bob", axis: "z", speed: 1.5, amplitude: 0.7 });
// Both stalks sway together from their base at the front of the head.
part("eye stalks", [24, 10, 16]);
for (const side of [-1, 1]) {
const baseX = 24 + side * 7;
const eyeX = 24 + side * 9;
line(baseX, 10, 16, eyeX, 8, 27, 2, "#68882c");
line(baseX - side, 9, 18, eyeX - side, 7, 26, 1, "#b6cf50");
sphere(eyeX, 8, 28, 4, "#536e2b");
ellipsoid(eyeX, 5, 28, 3, 2, 3, "#e56820");
ellipsoid(eyeX, 3, 28, 2, 1, 2, "#ffb329");
set(eyeX, 2, 28, "#ffe26a");
set(eyeX, 1, 28, "#7a3522");
// Heavy slanted lids give the bright eyes their grumpy look.
line(eyeX - 3, 3, 31, eyeX + 3, 3, 30, 1, "#4d6729");
}
animate("eye stalks", {
type: "swing", axis: "x", speed: 2, amplitude: 0.25
});import { draw } from "./assets/voxel";
import { babosa } from "./assets/babosa";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, babosa, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: lo que mide en px su lado más largo
// angle: giro sobre el piso, en radianes
// t: segundos; si se mueve, se anima solo con eso# En una terminal, en la carpeta del juego
fogon assets add babosa
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["babosa"] })
# Queda en client/assets/babosa.ts
# https://fogon.page/object/babosa