← Medieval3D assetfogon/reina
Reina
Drag to turn it// «Reina» · gpt-6-sol (medium)
// A chunky cartoon medieval queen: a long flowing deep red gown with gold trim and a white fur collar, a purple cape, a big round head with rosy cheeks, black dot eyes, long brown hair and a tall golden crown with red and blue gems, holding a small golden scepter.
// Chunky storybook queen, facing -y.
const red = ["#761d2c", "#852131", "#982c39", "#ac3b45"];
const purple = ["#45245e", "#552b72", "#693783"];
const gold = "#e9b94f", goldLight = "#f8d77a", goldDark = "#a96d29";
const fur = "#f4eee0", furShade = "#d7d0c5";
const skin = "#efb899", skinLight = "#f8c9a9";
const hair = "#573321", hairLight = "#75452a";
// Cape: a broad, slightly swept-back purple sheet with a bright edge.
for (let z = 1; z <= 28; z++) {
const width = 16 - z * 0.32;
const back = Math.round(39 - z * 0.26);
const front = back - 3;
for (let x = Math.ceil(24 - width); x <= Math.floor(24 + width); x++) {
const t = Math.abs(x - 24) / width;
const edgeBack = back - Math.round(3 * t * t);
for (let y = front; y <= edgeBack; y++) {
const edge = Math.abs(x - 24) > width - 1.5;
set(x, y, z, edge ? "#86529a" :
purple[rand() < 0.13 ? 2 : (z < 8 ? 0 : 1)]);
}
}
}
// Heavy embroidered cape hem.
for (let x = 9; x <= 39; x++) {
for (let y = 35; y <= 38; y++) {
if (get(x, y, 2)) set(x, y, 2, "#9c689e");
}
}
// Full, solid bell-shaped red skirt.
for (let z = 0; z <= 23; z++) {
const rx = 15.5 - z * 0.38;
const ry = 11.5 - z * 0.23;
for (let x = Math.ceil(24 - rx); x <= Math.floor(24 + rx); x++) {
for (let y = Math.ceil(24 - ry); y <= Math.floor(24 + ry); y++) {
const d = ((x - 24) / rx) ** 2 + ((y - 24) / ry) ** 2;
if (d > 1) continue;
const shade = z < 5 ? 0 : z > 17 ? 2 : 1;
set(x, y, z, red[Math.min(3, shade + (rand() < 0.055 ? 1 : 0))]);
}
}
}
// Gold hem and two long, curved embroidered seams on the visible front.
for (let z = 1; z <= 21; z++) {
const rx = 15.5 - z * 0.38, ry = 11.5 - z * 0.23;
for (let x = Math.ceil(24 - rx); x <= Math.floor(24 + rx); x++) {
const f = Math.sqrt(Math.max(0, 1 - ((x - 24) / rx) ** 2));
const yf = Math.ceil(24 - ry * f);
if (z === 1 || z === 2) {
for (let y = yf; y <= yf + 1; y++) set(x, y, z, z === 2 ? gold : goldDark);
}
if (Math.abs(x - (17 + z * 0.17)) < 0.55 ||
Math.abs(x - (31 - z * 0.17)) < 0.55) {
set(x, yf - 1, z, goldDark);
if (z % 4 !== 0) set(x, yf - 1, z + 1, gold);
}
}
}
// Blue-and-gold heraldic lozenge on the front of the gown.
for (let z = 8; z <= 19; z++) {
const half = Math.max(0, 5 - Math.abs(z - 13.5));
const ry = 11.5 - z * 0.23;
for (let x = Math.ceil(24 - half); x <= Math.floor(24 + half); x++) {
const rx = 15.5 - z * 0.38;
const yf = Math.ceil(24 - ry * Math.sqrt(1 - ((x - 24) / rx) ** 2));
const border = Math.abs(x - 24) > half - 1 || z === 8 || z === 19;
set(x, yf - 1, z, border ? gold : "#283f83");
}
}
box(23, 12, 12, 25, 13, 14, goldLight);
// Fitted bodice, waist belt, and white fur shoulder collar.
ellipsoid(24, 23, 25, 7.5, 6.5, 5, "#892332");
for (let x = 17; x <= 31; x++) {
for (let y = 18; y <= 28; y++) {
if (get(x, y, 22)) set(x, y, 22, goldDark);
if (get(x, y, 23) && y < 21) set(x, y, 23, gold);
}
}
box(22, 16, 23, 26, 18, 25, goldDark);
set(24, 15, 24, "#f9d87d");
ellipsoid(24, 22, 29, 9, 7, 2, furShade);
ellipsoid(24, 21, 30, 8, 6, 2, fur);
for (let x = 17; x <= 31; x += 3) {
ellipsoid(x, 16, 28, 1.5, 1.5, 1.5, x % 2 ? fur : furShade);
}
// The head, hair and crown bob together.
part("head", [24, 23, 30]);
ellipsoid(24, 23, 33, 7.5, 6.5, 7, hair);
ellipsoid(17, 24, 28, 2.5, 3.5, 7, hair);
ellipsoid(31, 24, 28, 2.5, 3.5, 7, hair);
for (let z = 24; z <= 32; z++) {
set(15, 22, z, z % 3 === 0 ? hairLight : hair);
set(33, 22, z, z % 3 === 0 ? hairLight : hair);
}
ellipsoid(24, 19, 33.5, 6, 4.5, 6, skin);
ellipsoid(24, 17, 35, 4, 2.5, 3, skinLight);
// Swept brown fringe framing the face.
box(19, 15, 38, 27, 17, 39, hair);
box(18, 17, 36, 19, 19, 38, hairLight);
box(29, 17, 36, 30, 19, 38, hairLight);
box(20, 14, 37, 23, 15, 38, hairLight);
// Black dot eyes, brows, cheeks, a little nose and smile.
box(20, 14, 34, 21, 15, 35, "#211b20");
box(27, 14, 34, 28, 15, 35, "#211b20");
set(21, 13, 35, "#fff1d8");
set(28, 13, 35, "#fff1d8");
box(20, 15, 36, 22, 15, 36, hair);
box(26, 15, 36, 28, 15, 36, hair);
ellipsoid(19, 16, 32, 1.7, 1, 1.2, "#df8582");
ellipsoid(29, 16, 32, 1.7, 1, 1.2, "#df8582");
set(24, 13, 32, "#e4a081");
box(23, 14, 30, 25, 14, 30, "#a94e58");
// Crown: thick circlet, raised points, inset royal gems.
for (let z = 39; z <= 41; z++) {
for (let x = 17; x <= 31; x++) {
for (let y = 15; y <= 27; y++) {
const d = ((x - 24) / 7) ** 2 + ((y - 21) / 6) ** 2;
if (d <= 1 && d >= 0.52) set(x, y, z, z === 40 ? goldLight : gold);
}
}
}
box(18, 15, 42, 20, 17, 44, gold);
box(23, 15, 42, 25, 17, 45, goldLight);
box(28, 15, 42, 30, 17, 44, gold);
set(19, 16, 45, goldLight);
set(29, 16, 45, goldLight);
box(20, 14, 40, 21, 15, 41, "#3566ae");
box(23, 14, 40, 25, 15, 41, "#b52938");
box(27, 14, 40, 28, 15, 41, "#3566ae");
set(24, 13, 41, "#ed6570");
animate("head", {type:"bob", axis:"z", speed:2, amplitude:0.3});
// Separate gently swinging sleeves and hands.
part("leftArm", [16, 22, 28]);
ellipsoid(14, 21, 25, 3.5, 3.5, 4.5, "#902738");
ellipsoid(12, 19, 21, 3, 3, 4, "#7a2031");
box(10, 16, 18, 14, 21, 19, gold);
ellipsoid(12, 18, 17, 2.3, 2.3, 2.5, skin);
set(11, 16, 17, skinLight);
animate("leftArm", {type:"swing", axis:"x", speed:2, amplitude:0.2});
part("rightArm", [32, 22, 28]);
ellipsoid(34, 21, 25, 3.5, 3.5, 4.5, "#902738");
ellipsoid(36, 19, 21, 3, 3, 4, "#7a2031");
box(34, 16, 18, 38, 21, 19, gold);
ellipsoid(36, 17, 17, 2.3, 2.3, 2.5, skin);
set(36, 15, 17, skinLight);
// Golden scepter gripped in the right hand.
box(37, 14, 15, 38, 15, 32, goldDark);
box(37, 13, 20, 38, 14, 30, gold);
box(35, 13, 32, 40, 15, 33, gold);
ellipsoid(37.5, 14, 35, 3, 2.5, 3, goldLight);
set(37, 11, 35, "#b52c40");
set(38, 11, 35, "#b52c40");
set(37, 14, 38, goldLight);
animate("rightArm", {type:"swing", axis:"x", speed:-2, amplitude:0.2});
part("body");import { draw } from "./assets/voxel";
import { reina } from "./assets/reina";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, reina, 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 reina
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["reina"] })
# It lands in client/assets/reina.ts
# https://fogon.page/object/reina