← Asian3D assetfogon/bol-de-ramen
Bol de ramen
Drag to turn it// «Bol de ramen» · gpt-6-sol (medium)
// A big bowl of ramen, chunky and appetizing: a deep red and black bowl with a white pattern on the rim, golden broth on top with wavy yellow noodles, a halved soft egg with orange yolk, two pink and white narutomaki slices, green onions, a square of nori sticking up and a pair of chopsticks resting on the rim.
const cx = 24, cy = 24;
const red = "#a92329", darkRed = "#761920";
const black = "#191b1b", gold = "#dbab49";
const white = "#f4e8d3";
function ring(radius, z, color, width = 0.6) {
for (let a = 0; a < Math.PI * 2; a += 0.025) {
for (let r = radius - width / 2; r <= radius + width / 2; r += 0.4) {
set(cx + Math.cos(a) * r, cy + Math.sin(a) * r, z, color);
}
}
}
// Heavy foot and gently flaring, solid lacquered bowl.
for (let z = 0; z <= 22; z++) {
const outer = z < 3 ? 11.5 : Math.min(20, 11.5 + (z - 2) * 0.46);
for (let x = 3; x <= 45; x++) {
for (let y = 3; y <= 45; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r > outer) continue;
let color;
if (z <= 3) color = r > outer - 1.4 ? black : "#30302a";
else if (z <= 17) {
color = r > outer - 2.5
? (rand() < 0.11 ? darkRed : red)
: "#6d3c22";
} else if (z <= 20) {
color = r > outer - 2.8
? (rand() < 0.16 ? "#34302b" : black)
: "#b76d27";
} else {
if (r < 17.3) continue;
color = z === 22 ? darkRed : red;
}
set(x, y, z, color);
}
}
}
ring(12.9, 4, gold);
ring(18.1, 16, "#d49b3b");
ring(19.5, 19, gold);
ring(19.6, 21, "#e4ae4b");
ring(19.4, 22, gold);
// White geometric motifs around the black upper band and across the lip.
for (let a = 0; a < Math.PI * 2; a += 0.012) {
const motif = ((a / (Math.PI * 2) * 24) % 1 + 1) % 1;
const d = Math.min(motif, 1 - motif);
if (d < 0.13) {
const r = 19.65;
set(cx + Math.cos(a) * r, cy + Math.sin(a) * r, 20, white);
if (d < 0.055) {
set(cx + Math.cos(a) * r, cy + Math.sin(a) * r, 19, white);
set(cx + Math.cos(a) * 18.5, cy + Math.sin(a) * 18.5, 22, white);
}
}
}
// Golden broth, with small pools of oil and warm surface variation.
for (let x = 7; x <= 41; x++) {
for (let y = 7; y <= 41; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r > 17.1) continue;
const fleck = rand();
set(x, y, 20,
fleck < 0.12 ? "#edb84d" :
fleck < 0.25 ? "#b9782b" : "#d99538");
if (r < 16.4 && rand() < 0.27)
set(x, y, 21, rand() < 0.5 ? "#eca94a" : "#c88330");
}
}
// A nest of thick, undulating yellow noodles.
for (let strand = 0; strand < 12; strand++) {
const baseY = 11.5 + strand * 2.25;
let previous = null;
for (let x = 10; x <= 38; x += 1.2) {
const y = baseY + Math.sin(x * 0.57 + strand * 1.7) * 2.3;
if (Math.hypot(x - cx, y - cy) > 16.2) {
previous = null;
continue;
}
const z = 21.5 + Math.sin(x * 0.39 + strand) * 0.65;
if (previous)
line(previous[0], previous[1], previous[2], x, y, z,
0.7, strand % 3 === 0 ? "#ffe181" : "#f5c655");
previous = [x, y, z];
}
}
// Upright sheet of dark, lightly mottled nori at the back.
for (let x = 18; x <= 29; x++) {
for (let z = 21; z <= 35; z++) {
if (z === 35 && (x === 18 || x === 29)) continue;
for (let y = 30; y <= 31; y++) {
set(x, y, z, rand() < 0.19 ? "#29452e" : "#172b25");
}
if (rand() < 0.28) set(x, 29, z, "#3c6040");
}
}
box(18, 30, 21, 29, 31, 21, "#344d30");
// Halved soft egg: plump white, shiny orange yolk facing upward.
ellipsoid(15, 17, 22, 5.1, 4.2, 2.6, "#ede6d2");
ellipsoid(15, 17, 24, 4.5, 3.5, 1.3, "#fff5dc");
ellipsoid(15, 16, 25, 2.7, 2.5, 1.2, "#ec8b24");
ellipsoid(14.7, 15.7, 26, 1.5, 1.3, 0.5, "#ffbd47");
// Two thick narutomaki slices, edged and spiraled in cherry pink.
function naruto(x, y, z) {
cylinder(x, y, z, 3.7, 2, "#f5e9dd");
for (let a = 0; a < Math.PI * 2; a += 0.07)
set(x + 3.45 * Math.cos(a), y + 3.45 * Math.sin(a), z + 2, "#e88d9d");
for (let t = 0; t < Math.PI * 3.3; t += 0.12) {
const r = 0.35 + t * 0.18;
set(x + r * Math.cos(t), y + r * Math.sin(t), z + 2, "#e77c97");
}
}
naruto(31, 16, 22);
naruto(36, 24, 21);
// Chopped jade-green scallions, scattered in small clusters.
const scallions = [
[12, 26], [15, 29], [18, 27], [12, 32], [16, 34],
[26, 12], [24, 16], [27, 23], [32, 28], [36, 29],
[22, 36], [10, 22], [28, 35]
];
for (const [x, y] of scallions) {
cylinder(x, y, 21, 1.5, 2, "#4e933e");
set(x, y, 23, "#b8ca70");
if (rand() < 0.65) set(x + 1, y, 23, "#75af55");
}
// Parallel lacquered chopsticks resting diagonally across opposite rim edges.
line(7, 11, 24, 40, 35, 24, 0, "#713726");
line(9, 9, 25, 42, 33, 25, 0, "#8b4930");
line(7, 11, 24, 14, 16, 24, 0, "#bc7440");
line(9, 9, 25, 16, 14, 25, 0, "#cf8750");
for (const [x, y, z] of [[11, 14, 24], [13, 12, 25]]) {
set(x, y, z, gold);
set(x + 1, y + 1, z, gold);
}import { draw } from "./assets/voxel";
import { bolDeRamen } from "./assets/bol-de-ramen";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, bolDeRamen, 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 bol-de-ramen
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["bol-de-ramen"] })
# It lands in client/assets/bol-de-ramen.ts
# https://fogon.page/object/bol-de-ramen