← Piratas y marObjeto 3Dfogon/sirena
Sirena
Arrastrá para girarlo// «Sirena» · gpt-6-sol (medium)
// A cartoon mermaid sitting on a small round grey rock: long wavy red hair, a purple shell top, a long turquoise fish tail with lighter scales curling over the rock edge and a big fan fin at the end, friendly face facing -y.
// Rock: a low, rounded perch with a sunlit top.
ellipsoid(24, 25, 4, 15, 12, 5, "#72777b");
ellipsoid(24, 25, 7, 13, 10, 2, "#999c99");
forEach((x, y, z, color) => {
if ((color === "#72777b" || color === "#999c99") && !get(x, y, z + 1)) {
if (rand() < 0.12) set(x, y, z, z > 6 ? "#b5b5aa" : "#858b8a");
}
});
line(12, 24, 5, 15, 22, 4, 0, "#555f63");
line(33, 32, 5, 36, 30, 3, 0, "#555f63");
// Long red hair behind her shoulders and head.
ellipsoid(24, 24, 32, 8, 7, 9, "#a82e25");
ellipsoid(16, 24, 22, 3, 4, 12, "#b93628");
ellipsoid(32, 24, 23, 3, 4, 11, "#a82e25");
sphere(16, 23, 12, 3, "#c8442c");
sphere(32, 25, 14, 3, "#b93628");
line(15, 21, 29, 15, 22, 17, 1, "#e35a35");
line(33, 22, 31, 33, 23, 19, 1, "#cf442b");
sphere(17, 22, 16, 2, "#e35a35");
sphere(31, 23, 18, 2, "#cf442b");
// Curling turquoise tail, flowing forward and over the rock's edge.
ellipsoid(24, 23, 12, 7, 6, 4, "#008f9b");
ellipsoid(24, 20, 12, 6, 5, 4, "#09adb0");
line(24, 20, 11, 26, 14, 9, 4, "#09adb0");
line(26, 14, 9, 31, 11, 8, 3, "#008f9b");
line(30, 11, 8, 35, 12, 8, 2, "#09adb0");
line(24, 17, 14, 27, 13, 11, 1, "#45d2c9");
line(28, 11, 10, 33, 10, 9, 1, "#45d2c9");
// Bright, overlapping scale marks on the visible front of the tail.
for (const [x, y, z] of [
[20, 17, 12], [23, 15, 12], [26, 16, 13],
[21, 16, 10], [24, 14, 10], [27, 12, 10],
[29, 9, 8], [32, 9, 8], [25, 17, 15]
]) {
set(x, y, z, "#9aebd5");
set(x + 1, y, z - 1, "#59d5c7");
}
// Waist, bare torso, neck, and arms resting beside her.
ellipsoid(24, 23, 18, 5, 4, 7, "#efa879");
ellipsoid(24, 22, 26, 2, 2, 3, "#f5b98a");
line(19, 22, 24, 16, 19, 18, 2, "#e99c70");
line(16, 19, 18, 15, 18, 13, 2, "#f5b98a");
line(29, 22, 24, 32, 19, 18, 2, "#e99c70");
line(32, 19, 18, 33, 18, 13, 2, "#f5b98a");
sphere(15, 17, 12, 2, "#f5b98a");
sphere(33, 17, 12, 2, "#f5b98a");
// Two chunky purple scallop shells.
for (const x of [21, 27]) {
ellipsoid(x, 18, 22, 4, 2, 3, "#713690");
ellipsoid(x, 16, 23, 3, 1, 2, "#b367cf");
line(x - 2, 15, 21, x - 1, 15, 24, 0, "#dc91e4");
line(x + 1, 15, 21, x + 1, 15, 24, 0, "#dc91e4");
set(x, 15, 24, "#edb1ec");
}
line(18, 18, 20, 30, 18, 20, 0, "#5a287d");
// Friendly face looking toward -y.
ellipsoid(24, 21, 32, 7, 6, 7, "#f5b98a");
ellipsoid(24, 17, 29, 5, 2, 3, "#ffd0a0");
for (const x of [21, 27]) {
box(x - 1, 15, 32, x + 1, 15, 34, "#fff9e9");
box(x, 14, 32, x, 14, 33, "#283344");
set(x, 13, 33, "#ffffff");
line(x - 1, 14, 35, x + 1, 14, 35, 0, "#963f31");
}
set(24, 14, 30, "#e89572");
set(20, 15, 29, "#ef8e82");
set(28, 15, 29, "#ef8e82");
line(22, 14, 27, 24, 14, 26, 0, "#a64d51");
line(24, 14, 26, 26, 14, 27, 0, "#a64d51");
// Swept fringe and wavy locks frame the face without hiding it.
ellipsoid(24, 21, 39, 8, 6, 2, "#c9412c");
line(18, 17, 38, 22, 15, 37, 2, "#df5331");
line(23, 15, 38, 28, 16, 36, 2, "#b93628");
line(18, 17, 36, 17, 17, 25, 2, "#c9412c");
line(30, 17, 36, 31, 18, 25, 2, "#b93628");
sphere(17, 18, 24, 2, "#e35a35");
sphere(31, 19, 23, 2, "#cf442b");
line(19, 16, 37, 21, 15, 37, 0, "#f37743");
line(17, 17, 31, 17, 17, 27, 0, "#f37743");
// The broad fan fin pivots at the end of the tail, just over the rock edge.
part("tailFin", [34, 12, 8]);
for (let x = 34; x <= 44; x++) {
const d = x - 34;
const bottom = Math.ceil(8 - d * 0.68);
const top = Math.floor(8 + d * 0.92);
for (let z = bottom; z <= top; z++) {
// A notch separates its two rounded lobes.
if (x >= 42 && z >= 7 && z <= 10) continue;
for (let y = 10; y <= 12; y++) {
set(x, y, z, y === 10 ? "#39c9c0" : "#008f9b");
}
}
}
for (const [x, z] of [[42, 15], [44, 3], [41, 5]]) {
line(35, 9, 8, x, 9, z, 0, "#a4edce");
}
line(36, 9, 9, 42, 9, 16, 0, "#a4edce");
line(36, 9, 7, 43, 9, 2, 0, "#a4edce");
animate("tailFin", { type: "swing", axis: "z", speed: 2, amplitude: 0.3 });import { draw } from "./assets/voxel";
import { sirena } from "./assets/sirena";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, sirena, 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 sirena
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["sirena"] })
# Queda en client/assets/sirena.ts
# https://fogon.page/object/sirena