← Pirates and sea3D assetfogon/coral
Coral
Drag to turn it// «Coral» · gpt-6-sol (medium)
// A colorful coral cluster: pink branching coral, an orange brain coral dome, purple fan coral and a few yellow tube corals on a sandy base.
// Sunlit sand, broad enough to anchor the whole reef.
for (let z = 0; z <= 3; z++) {
const rx = 21 - z * 0.9, ry = 19 - z * 0.9;
for (let x = 2; x <= 46; x++) for (let y = 3; y <= 45; y++) {
if (((x - 24) / rx) ** 2 + ((y - 24) / ry) ** 2 <= 1) {
const n = rand();
set(x, y, z, z === 3
? (n < 0.15 ? "#f8dfa0" : n < 0.29 ? "#d9ae70" : "#edca89")
: (n < 0.12 ? "#c99d65" : "#dfb77b"));
}
}
}
// The sea fan is its own gently swaying piece, rooted behind the corals.
part("fan", [25, 34, 5]);
line(25, 34, 4, 25, 34, 14, 2, "#7540a4");
line(25, 33, 9, 25, 33, 17, 1, "#b871dd");
const fanTips = [
[12, 28], [15, 33], [19, 36], [25, 37],
[31, 36], [36, 33], [39, 27]
];
for (const [x, z] of fanTips) {
line(25, 34, 12, x, 34, z, 1, "#8e4ab9");
line(25, 33, 13, x, 33, z, 0, "#cf84e9");
}
for (let z = 17; z <= 34; z += 3) {
const w = Math.min(13, Math.floor((z - 10) * 0.68));
for (let x = 25 - w; x <= 25 + w; x++) {
if (z <= 37 - 0.052 * (x - 25) ** 2) {
set(x, 34, z, "#a557ca");
if (x % 4 === 0) set(x, 33, z, "#d17bea");
}
}
}
for (let z = 19; z <= 31; z += 3) {
for (let x = 16; x <= 34; x += 4) {
if (Math.abs(x - 25) < (z - 10) * 0.68 &&
z + 3 <= 37 - 0.052 * (x - 25) ** 2) {
line(x, 34, z, x + (x < 25 ? -2 : 2), 34, z + 3, 0, "#b76bd9");
}
}
}
for (let x = 12; x <= 39; x++) {
const z = Math.round(37 - 0.052 * (x - 25) ** 2);
if (z >= 27) set(x, 34, z, "#d083ea");
}
animate("fan", { type: "swing", axis: "y", speed: 1.5, amplitude: 0.15 });
part("body");
// Chunky pink branching coral on the left.
const branches = [
[[14, 21, 4], [15, 21, 14], 3],
[[15, 21, 13], [13, 21, 23], 2],
[[13, 21, 22], [11, 20, 32], 2],
[[13, 21, 22], [17, 20, 30], 2],
[[15, 21, 15], [20, 19, 21], 2],
[[20, 19, 21], [21, 18, 30], 2],
[[20, 19, 21], [24, 20, 27], 1],
[[15, 21, 12], [9, 19, 19], 2],
[[9, 19, 19], [7, 18, 27], 2],
[[9, 19, 19], [11, 17, 25], 1],
[[13, 21, 23], [9, 23, 29], 1],
[[17, 20, 30], [17, 19, 35], 1],
[[17, 20, 30], [20, 21, 34], 1],
[[21, 18, 30], [24, 17, 34], 1]
];
for (const [a, b, r] of branches) {
line(...a, ...b, r, "#e96b9f");
sphere(...b, r + 0.45, "#f48ab3");
if (r >= 2) {
line(a[0], a[1] - 1, a[2] + 1,
b[0], b[1] - 1, b[2], 0, "#ffadc8");
}
}
for (const [x, y, z] of [[11,20,32],[17,19,35],[20,21,34],[24,17,34],
[7,18,27],[21,18,30]]) {
sphere(x, y, z, 1.3, "#ffb0c8");
}
// Orange brain coral: a solid rounded dome with winding raised folds.
cylinder(33, 24, 4, 8, 5, "#c65a2c");
ellipsoid(33, 24, 9, 10, 8, 12, "#ed8237");
ellipsoid(33, 23, 10, 9, 7, 10, "#fa9c43");
for (let y = 17; y <= 29; y += 3) {
for (let x = 25; x <= 41; x++) {
const yy = y + Math.round(Math.sin(x * 0.85 + y) * 0.8);
const q = ((x - 33) / 10) ** 2 + ((yy - 24) / 8) ** 2;
if (q < 0.91) {
const z = Math.round(9 + 12 * Math.sqrt(1 - q));
set(x, yy, z + 1, "#c9652d");
if (q < 0.83) set(x, yy + 1, z + 1, "#ffc066");
}
}
}
// Furrows curl down its viewer-facing side.
for (let x0 = 27; x0 <= 39; x0 += 3) {
for (let z = 9; z <= 17; z++) {
const x = x0 + Math.round(Math.sin(z * 0.68 + x0) * 0.7);
const q = ((x - 33) / 10) ** 2 + ((z - 9) / 12) ** 2;
if (q < 0.92) {
const y = Math.round(24 - 8 * Math.sqrt(1 - q));
set(x, y - 1, z, "#bd5c2b");
set(x + 1, y - 1, z, "#ffb552");
}
}
}
// Yellow trumpet-shaped tube corals, their dark openings visible from above.
function tube(x, y, height, radius) {
for (let z = 4; z < height - 2; z++) {
const bendX = Math.round(Math.sin(z * 0.32 + x) * 0.7);
cylinder(x + bendX, y, z, radius - 1, 1,
z % 4 === 0 ? "#d69224" : "#f2b832");
set(x + bendX, y - radius + 1, z, "#ffdb59");
}
const bx = x + Math.round(Math.sin((height - 3) * 0.32 + x) * 0.7);
cylinder(bx, y, height - 3, radius + 0.3, 2, "#f3b52a");
for (let dx = -radius - 1; dx <= radius + 1; dx++)
for (let dy = -radius - 1; dy <= radius + 1; dy++) {
const d = Math.hypot(dx, dy);
if (d <= radius + 0.6) {
set(bx + dx, y + dy, height - 1,
d < radius - 0.25 ? "#9a5926" : "#ffdc51");
if (d >= radius - 0.55 && d <= radius + 0.6)
set(bx + dx, y + dy, height, "#ffe36c");
}
}
}
tube(25, 12, 17, 3);
tube(30, 10, 13, 2);
tube(40, 17, 13, 2);
tube(8, 29, 12, 2);
// Shells, golden sand flecks and a few turquoise bits of sea glass.
for (const [x, y, z, c] of [
[18, 11, 4, "#fff1c2"], [19, 11, 4, "#fff1c2"],
[36, 12, 4, "#74d6cb"], [37, 12, 4, "#a0e6d5"],
[5, 24, 2, "#ffdf84"], [6, 25, 3, "#fff0ae"],
[30, 39, 2, "#82d9ce"], [31, 39, 2, "#a3e8d8"],
[42, 29, 2, "#fff0bd"], [41, 30, 3, "#ffdc84"]
]) set(x, y, z, c);import { draw } from "./assets/voxel";
import { coral } from "./assets/coral";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, coral, 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 coral
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["coral"] })
# It lands in client/assets/coral.ts
# https://fogon.page/object/coral