← Farm3D assetfogon/espantapajaros
Espantapájaros
Drag to turn it// «Espantapájaros» · gpt-6-sol (medium)
// A classic scarecrow on a vertical wooden pole stuck in the ground: a burlap sack head with stitched black X eyes and a stitched smile, a floppy pointed brown straw hat, a faded patched blue-and-red checkered shirt with straw sticking out of the cuffs and collar, arms stretched straight out to the sides along a horizontal crossbar, ragged brown trousers with straw at the hems hanging from the pole, and a small black crow perched on one arm.
const wood = "#9b6036", woodLight = "#bb7b46", woodDark = "#734425";
const straw = ["#f8d65e", "#e9b83f", "#ffdf79"];
const blue = "#527fa9", blueLight = "#7198b6", blueDark = "#365b80";
const red = "#bf534d", redLight = "#da7061";
// A little patch of sunny ground around the post.
ellipsoid(24, 24, 0, 11, 8, 1, "#69b94d");
for (let i = 0; i < 95; i++) {
const x = 15 + Math.floor(rand() * 19);
const y = 17 + Math.floor(rand() * 15);
if (get(x, y, 0)) set(x, y, 1, rand() < 0.5 ? "#88cd56" : "#55a743");
}
// Vertical stake and its visible horizontal crossbar.
box(23, 23, 0, 25, 25, 34, wood);
box(23, 23, 0, 23, 23, 32, woodLight);
box(25, 25, 1, 25, 25, 32, woodDark);
box(5, 23, 26, 43, 25, 27, wood);
box(5, 23, 27, 43, 23, 27, woodLight);
// Loose straw below the trouser legs.
for (const cx of [20, 28]) {
for (let i = 0; i < 12; i++) {
const x = cx - 2 + Math.floor(rand() * 5);
const y = 21 + Math.floor(rand() * 6);
line(x, y, 8, x + Math.floor(rand() * 3) - 1, y, 5 + Math.floor(rand() * 3),
0, straw[i % 3]);
}
}
// Baggy, torn trousers.
box(18, 21, 16, 30, 28, 21, "#806347");
box(18, 20, 10, 22, 28, 18, "#927252");
box(26, 20, 10, 30, 28, 18, "#927252");
box(18, 20, 10, 18, 20, 17, "#b18a5d");
box(26, 20, 10, 26, 20, 17, "#b18a5d");
box(19, 20, 8, 22, 27, 11, "#806347");
box(26, 20, 8, 29, 27, 11, "#806347");
for (let x = 18; x <= 30; x++) {
if (x > 22 && x < 26) continue;
if (rand() < 0.7) box(x, 21, 8, x, 26, 8 + Math.floor(rand() * 3), "#927252");
}
// A conspicuous sewn trouser patch.
box(19, 19, 14, 21, 19, 17, "#ae8253");
for (let z = 14; z <= 17; z++) {
set(18, 19, z, "#dfc292");
set(22, 19, z, "#dfc292");
}
// Shirt torso, with broad shoulders and a readable checkered front.
box(18, 21, 20, 30, 28, 29, blue);
box(16, 22, 26, 32, 27, 29, blue);
box(18, 20, 21, 30, 20, 28, blueLight);
for (let x = 18; x <= 30; x++) {
for (let z = 21; z <= 29; z++) {
const check = (Math.floor((x - 18) / 3) + Math.floor((z - 21) / 3)) % 2;
set(x, 19, z, check ? red : blueLight);
}
}
for (let z = 21; z <= 29; z += 3) {
for (let x = 18; x <= 30; x++) set(x, 18, z, blueDark);
}
for (let x = 20; x <= 29; x += 3) {
for (let z = 21; z <= 29; z++) set(x, 18, z, redLight);
}
// Uneven front placket, button dots, and a patched pocket.
box(24, 17, 21, 24, 17, 28, "#e4c89a");
for (const z of [22, 25, 28]) set(24, 16, z, "#634534");
box(19, 17, 22, 22, 17, 25, "#dfaa62");
box(20, 16, 23, 21, 16, 24, "#e9bb77");
for (const x of [19, 22]) for (const z of [22, 25]) set(x, 16, z, "#f2d99a");
// Straw poking through the open collar.
for (let i = 0; i < 14; i++) {
const x = 20 + Math.floor(rand() * 9);
const y = 20 + Math.floor(rand() * 6);
line(x, y, 29, x + Math.floor(rand() * 3) - 1, y - 1, 32,
0, straw[i % 3]);
}
// Each sleeve and its cuff belong to a separate, gently swaying arm.
function arm(name, pivotX, fromX, toX, speed) {
part(name, [pivotX, 24, 27]);
const lo = Math.min(fromX, toX), hi = Math.max(fromX, toX);
box(lo, 21, 25, hi, 27, 29, blue);
box(lo, 20, 26, hi, 20, 28, blueLight);
for (let x = lo; x <= hi; x++) {
for (let z = 25; z <= 29; z++) {
const check = (Math.floor((x - lo) / 3) + Math.floor((z - 25) / 2)) % 2;
set(x, 19, z, check ? red : blueLight);
}
if ((x - lo) % 3 === 0) box(x, 18, 25, x, 18, 29, blueDark);
}
for (const z of [25, 28]) box(lo, 18, z, hi, 18, z, redLight);
const end = fromX < toX ? lo : hi;
const outward = fromX < toX ? -1 : 1;
box(end, 20, 24, end + outward, 27, 29, blueDark);
for (let i = 0; i < 15; i++) {
const y = 21 + Math.floor(rand() * 6);
const z = 25 + Math.floor(rand() * 4);
line(end + outward, y, z,
end + outward * (2 + Math.floor(rand() * 3)), y + Math.floor(rand() * 3) - 1,
z + Math.floor(rand() * 3) - 1, 0, straw[i % 3]);
}
animate(name, { type: "swing", axis: "y", speed, amplitude: 0.2 });
}
arm("leftArm", 17, 6, 17, 2);
arm("rightArm", 31, 31, 42, -2);
// A chunky crow riding the right sleeve, facing inward.
ellipsoid(38, 20, 33, 3, 2, 2, "#22252c");
ellipsoid(36, 20, 35, 2, 2, 2, "#171b22");
ellipsoid(39, 18, 33, 2, 1, 1, "#39404a");
line(40, 20, 33, 44, 21, 32, 1, "#171b22");
line(41, 20, 32, 45, 21, 31, 0, "#30343c");
box(33, 19, 34, 34, 20, 34, "#e5ac3c");
set(35, 17, 36, "#fff3d1");
set(35, 16, 36, "#12151b");
for (const x of [37, 39]) {
line(x, 20, 31, x, 20, 29, 0, "#deaa39");
line(x, 20, 29, x - 1, 19, 29, 0, "#deaa39");
}
part("body");
// The sack head tilts independently at the neck.
part("head", [24, 24, 31]);
ellipsoid(24, 24, 35, 6, 5, 5, "#c9a879");
box(20, 20, 33, 28, 28, 38, "#d8b98a");
box(21, 19, 33, 27, 19, 38, "#dec092");
box(20, 21, 32, 28, 27, 33, "#ad895f");
for (let i = 0; i < 35; i++) {
const x = 20 + Math.floor(rand() * 9);
const z = 33 + Math.floor(rand() * 6);
set(x, 19, z, rand() < 0.5 ? "#caa577" : "#e8ca9c");
}
// Restore a clean face plane for the large black stitched features.
for (const cx of [22, 26]) {
line(cx - 1, 18, 37, cx + 1, 18, 35, 0, "#272327");
line(cx - 1, 18, 35, cx + 1, 18, 37, 0, "#272327");
}
for (const [x, z] of [[20, 34], [21, 33], [22, 32], [23, 32],
[24, 32], [25, 32], [26, 33], [27, 34]]) {
set(x, 18, z, "#352a27");
}
for (const x of [21, 23, 25, 27]) set(x, 18, 32, "#514039");
// Side seam and tied burlap at the neck.
for (let z = 33; z <= 38; z += 2) set(29, 21, z, "#8d704f");
box(22, 21, 31, 26, 27, 32, "#aa855a");
box(22, 20, 31, 26, 20, 31, "#f4d368");
// Wide, floppy hat brim, with one corner drooping down.
ellipsoid(24, 24, 40, 9, 8, 1, "#79502f");
ellipsoid(24, 24, 41, 8, 7, 1, "#a16c39");
box(15, 21, 39, 19, 27, 40, "#a16c39");
box(14, 22, 38, 17, 26, 39, "#80512e");
box(29, 19, 39, 32, 27, 40, "#8c5a32");
box(21, 21, 41, 28, 27, 42, "#986333");
box(22, 22, 43, 28, 26, 43, "#ae7640");
box(24, 22, 44, 28, 25, 44, "#a16c39");
box(27, 23, 45, 29, 24, 45, "#8c5a32");
box(21, 20, 41, 28, 20, 41, "#e2bd61");
box(22, 20, 42, 27, 20, 42, "#e2bd61");
set(25, 19, 41, "#684329");
animate("head", { type: "swing", axis: "y", speed: 1.1, amplitude: 0.2 });
part("body");import { draw } from "./assets/voxel";
import { espantapajaros } from "./assets/espantapajaros";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, espantapajaros, 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 espantapajaros
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["espantapajaros"] })
# It lands in client/assets/espantapajaros.ts
# https://fogon.page/object/espantapajaros