← Piratas y marObjeto 3Dfogon/marinero
Marinero pirata
Arrastrá para girarlo// «Marinero pirata» · gpt-6-sol (medium)
// A young cartoon pirate deckhand facing -y: blue and white striped shirt, a blue bandana, bare forearms, brown short pants, bare feet, holding a wooden mop.
// Young pirate deckhand, facing -y.
const skin = "#f2ad72";
const skinLight = "#ffc58b";
const skinShade = "#d98555";
const blue = "#1879bd";
const blueLight = "#36a2dd";
const blueDark = "#145788";
const white = "#fff4dc";
const whiteShade = "#e4dfcf";
const brown = "#805039";
const brownLight = "#a66a43";
const brownDark = "#59382d";
const wood = "#a66a3f";
const woodLight = "#c58a52";
// Legs are separate walking parts, including their shorts and bare feet.
function leg(name, x, speed) {
part(name, [x + 2, 24, 17]);
box(x, 21, 13, x + 4, 27, 17, brown);
box(x, 20, 13, x + 4, 21, 16, brownLight);
box(x, 20, 12, x + 4, 27, 12, brownDark);
box(x + 1, 22, 5, x + 3, 26, 11, skin);
box(x + 1, 20, 3, x + 3, 26, 5, skinShade);
// Broad toes point toward the viewer.
box(x, 17, 0, x + 4, 26, 2, skin);
box(x, 17, 2, x + 4, 21, 3, skinLight);
for (let i = 0; i < 3; i++) {
set(x + i + 1, 16, 0, skinLight);
set(x + i + 1, 16, 1, skinLight);
}
animate(name, { type: "swing", axis: "x", speed, amplitude: 0.3 });
}
leg("leftLeg", 18, 5);
leg("rightLeg", 26, -5);
part("body", [24, 24, 20]);
// Rounded, solid striped shirt.
for (let z = 19; z <= 29; z++) {
for (let y = 19; y <= 29; y++) {
for (let x = 17; x <= 31; x++) {
const dx = (x - 24) / (z >= 26 ? 7.7 : 7.1);
const dy = (y - 24) / 5.8;
if (dx * dx + dy * dy > 1.05) continue;
const stripe = Math.floor((z - 19) / 2) % 2 === 0;
let c = stripe ? blue : white;
if (y >= 28 || x === 17 || x === 31) c = stripe ? blueDark : whiteShade;
else if (y <= 20 && stripe && rand() < 0.17) c = blueLight;
set(x, y, z, c);
}
}
}
// Belt and little brass buckle.
box(19, 19, 18, 29, 28, 19, brownDark);
box(22, 18, 18, 26, 19, 20, "#e9af39");
box(23, 17, 19, 25, 18, 19, "#ffdc6b");
set(24, 17, 19, brownDark);
// Neck and cheerful oversized face.
box(22, 21, 29, 26, 26, 32, skinShade);
box(22, 19, 29, 26, 22, 31, skin);
ellipsoid(24, 23, 35, 6, 5, 5, skin);
ellipsoid(24, 18, 34, 4, 2, 3, skinLight);
box(17, 21, 33, 18, 25, 35, skinShade);
box(30, 21, 33, 31, 25, 35, skinLight);
box(23, 16, 32, 25, 18, 34, skinLight);
// Eyes, brows, freckles and a curved smile on the front.
for (const x of [21, 27]) {
box(x, 17, 35, x + 1, 18, 36, white);
set(x, 16, 35, "#243b43");
set(x + 1, 17, 37, brownDark);
}
for (const x of [19, 20, 28, 29]) set(x, 18, 32, skinShade);
set(21, 17, 31, brownDark);
box(22, 16, 30, 26, 17, 30, brownDark);
set(27, 17, 31, brownDark);
box(23, 15, 30, 25, 15, 30, white);
// Blue bandana wrapped over the hair, with a knot and two trailing tails.
ellipsoid(24, 23, 39, 6, 5, 2, blue);
box(19, 18, 37, 29, 19, 38, blue);
box(20, 17, 38, 28, 18, 38, blueLight);
for (let x = 20; x <= 28; x++) {
if (x % 3 === 0) set(x, 17, 38, blueDark);
}
sphere(31, 27, 38, 2, blueLight);
line(32, 28, 37, 36, 32, 35, 1, blue);
line(32, 28, 37, 34, 31, 33, 1, blueDark);
box(23, 18, 40, 27, 21, 40, blueLight);
// A wooden mop planted beside him.
box(37, 19, 4, 38, 20, 35, wood);
box(37, 19, 7, 37, 19, 34, woodLight);
for (const z of [9, 17, 25, 32]) {
box(37, 18, z, 38, 20, z, brownDark);
}
box(36, 18, 3, 39, 21, 5, brownDark);
box(36, 18, 4, 39, 21, 4, "#dbac62");
// Chunky cream mop fibers spread across the floor.
ellipsoid(38, 20, 2, 5, 4, 2, whiteShade);
for (let x = 34; x <= 42; x += 2) {
for (let y = 17; y <= 23; y += 2) {
const c = rand() < 0.35 ? "#c9c8ad" : white;
line(x, y, 3, x + (x < 38 ? -1 : 1), y, 0, 0, c);
}
}
box(36, 18, 3, 39, 21, 4, white);
box(36, 18, 5, 39, 21, 5, "#d6bb87");
// Sleeves and arms swing opposite their corresponding legs.
function arm(name, side, speed) {
const left = side === "left";
const shoulderX = left ? 17 : 31;
part(name, [shoulderX, 24, 27]);
const x0 = left ? 13 : 32;
const x1 = left ? 18 : 36;
box(x0, 21, 25, x1, 27, 28, blue);
box(x0, 20, 27, x1, 22, 28, blueLight);
box(x0, 20, 24, x1, 26, 24, white);
box(x0, 21, 23, x1, 26, 23, blueDark);
if (left) {
box(13, 21, 16, 16, 25, 22, skin);
box(13, 20, 16, 15, 21, 21, skinLight);
ellipsoid(14, 23, 14, 2, 2, 2, skin);
box(13, 19, 13, 15, 21, 14, skinLight);
} else {
box(33, 21, 17, 36, 25, 22, skin);
box(35, 19, 15, 37, 23, 18, skinLight);
// Fingers curl around the mop handle.
box(36, 18, 15, 39, 19, 16, skin);
box(38, 18, 14, 39, 20, 15, skinShade);
}
animate(name, { type: "swing", axis: "x", speed, amplitude: 0.25 });
}
arm("leftArm", "left", -5);
arm("rightArm", "right", 5);import { draw } from "./assets/voxel";
import { marinero } from "./assets/marinero";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, marinero, 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 marinero
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["marinero"] })
# Queda en client/assets/marinero.ts
# https://fogon.page/object/marinero