← Monstruos y enemigosObjeto 3Dfogon/gusano-gigante
Gusano gigante
Arrastrá para girarlo// «Gusano gigante» · gpt-6-sol (medium)
// A giant cartoon sandworm bursting out of the ground: a thick segmented pinkish-brown body rising up in a curve from a pile of sand and rocks, ending in a round open mouth facing -y with rings of white teeth and a dark throat.
// Sand and scattered rocks stay still while the worm sways.
for (let z = 0; z <= 4; z++) {
for (let x = 4; x <= 44; x++) {
for (let y = 7; y <= 42; y++) {
const d = ((x - 24) / (20 - z * 1.4)) ** 2 +
((y - 25) / (17 - z * 1.3)) ** 2;
if (d < 1 && rand() > (z > 2 ? 0.24 : 0.04)) {
set(x, y, z, rand() < 0.15 ? "#f5d68a" :
z < 2 ? "#bd8e50" : "#dfb76d");
}
}
}
}
ellipsoid(16, 30, 3, 8, 7, 3, "#d6a65c");
ellipsoid(33, 27, 2, 8, 6, 2, "#e6bc70");
ellipsoid(26, 16, 2, 10, 5, 2, "#d5a45e");
const rocks = [
[9, 21, 2, 3, 2, 2], [38, 19, 2, 3, 3, 2],
[13, 36, 2, 3, 2, 2], [35, 36, 1, 2, 2, 1],
[7, 29, 1, 2, 2, 1], [30, 12, 1, 2, 2, 1]
];
for (const [x, y, z, rx, ry, rz] of rocks) {
ellipsoid(x, y, z, rx, ry, rz, "#82766b");
box(x - 1, y - 1, z + rz, x, y, z + rz, "#aaa091");
}
for (let i = 0; i < 105; i++) {
const x = 5 + Math.floor(rand() * 39);
const y = 9 + Math.floor(rand() * 33);
if (get(x, y, 2) && rand() > 0.35)
set(x, y, 3, rand() < 0.5 ? "#ffe09a" : "#ad804b");
}
// The entire raised worm turns at the point where it emerges.
part("worm", [24, 29, 5]);
animate("worm", { type: "swing", axis: "x", speed: 2, amplitude: 0.2 });
// Curving, chunky body. Dark bands define its segments.
for (let z = 4; z <= 32; z++) {
const h = z - 5;
const cy = 30 - 0.25 * h - 0.009 * h * h;
const rx = 8.3 + 0.5 * Math.sin(z * 0.18);
const ry = 7.4 + 0.4 * Math.sin(z * 0.21);
const band = ((z - 5) % 6 + 6) % 6;
for (let x = 14; x <= 34; x++) {
for (let y = Math.floor(cy - 9); y <= Math.ceil(cy + 9); y++) {
const d = ((x - 24) / rx) ** 2 + ((y - cy) / ry) ** 2;
if (d > 1) continue;
let color;
if (band === 0) color = "#754758";
else if (band === 1) color = "#995b67";
else if (y > cy + 2) color = "#995863";
else if (y < cy - 2 || band === 2) color = "#d9908b";
else color = "#bb7478";
if (d > 0.77 && y > cy) color = band === 0 ? "#643e50" : "#854c5c";
if (rand() < 0.045 && band !== 0) color = "#e7a39a";
set(x, y, z, color);
}
}
}
// Broad head with a darker underside.
for (let z = 24; z <= 42; z++) {
for (let x = 14; x <= 34; x++) {
for (let y = 8; y <= 25; y++) {
const d = ((x - 24) / 10) ** 2 +
((y - 17) / 9) ** 2 +
((z - 33) / 9) ** 2;
if (d > 1) continue;
let color = z < 30 ? "#965866" :
y < 16 || z > 37 ? "#dc9691" : "#be777b";
if (d > 0.78 && z < 32) color = "#79495a";
if (rand() < 0.035) color = "#e9aaa0";
set(x, y, z, color);
}
}
}
// Recess the round, forward-facing mouth.
for (let y = 7; y <= 14; y++) {
for (let x = 17; x <= 31; x++) {
for (let z = 26; z <= 40; z++) {
const r = Math.hypot(x - 24, z - 33);
if (r < 6.35) set(x, y, z, null);
}
}
}
// Dark throat at the back of the opening.
for (let x = 18; x <= 30; x++) {
for (let z = 27; z <= 39; z++) {
const r = Math.hypot(x - 24, z - 33);
if (r < 6.2) {
set(x, 14, z, r < 3.5 ? "#241d36" :
r < 5 ? "#39243e" : "#71384e");
}
}
}
// Thick pink outer lip and its shadowed inner gum.
for (let y = 8; y <= 11; y++) {
for (let x = 15; x <= 33; x++) {
for (let z = 24; z <= 42; z++) {
const r = Math.hypot(x - 24, z - 33);
if (r >= 6.25 && r <= 8.55) {
set(x, y, z, r < 6.95 ? "#713d50" :
z < 32 ? "#aa6070" : "#e7a19a");
}
}
}
}
for (let x = 16; x <= 32; x++) {
for (let z = 25; z <= 41; z++) {
const r = Math.hypot(x - 24, z - 33);
if (r >= 6.5 && r <= 7.8) set(x, 7, z, "#f0aaa0");
}
}
// Little triangular teeth point inward all around the mouth.
for (let i = 0; i < 16; i++) {
const a = (i + 0.5) * Math.PI * 2 / 16;
for (let t = 0; t <= 3; t++) {
const r = 6.55 - t * 0.62;
const halfWidth = t < 2 ? 0.72 : 0.26;
for (let w = -halfWidth; w <= halfWidth + 0.01; w += 0.65) {
const x = Math.round(24 + Math.cos(a) * r - Math.sin(a) * w);
const z = Math.round(33 + Math.sin(a) * r + Math.cos(a) * w);
set(x, 7, z, t === 3 ? "#fff8df" : "#fff3d4");
if (t < 2) set(x, 8, z, "#dfd6c7");
}
}
}
// Friendly glowing eyes, perched above either side of the mouth.
for (const x of [16, 32]) {
ellipsoid(x, 12, 39, 2, 2, 2, "#824d60");
ellipsoid(x, 10, 39, 1.5, 1, 1.5, "#ffc83e");
set(x, 9, 39, "#fff5a0");
set(x, 9, 40, "#fff9cf");
}import { draw } from "./assets/voxel";
import { gusanoGigante } from "./assets/gusano-gigante";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, gusanoGigante, 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 gusano-gigante
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["gusano-gigante"] })
# Queda en client/assets/gusano-gigante.ts
# https://fogon.page/object/gusano-gigante