Generated gear parts (helmet, shoulder pieces, crown, cape, horns, plume) instead of drawn shapes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-08 00:11:47 +01:00
1 parent af330c09b7
commit 65ed76865d
16 files changed
+58 -16

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# Gear parts (high-res)
The parts laid over the detailed sprites as their gear (helmet, shoulder piece, crown, cape,
horn, plume; `GEAR_*` and `gen_gear` in `src/gfx.rs`). Generated on 2026-11-08 with
`fal-ai/nano-banana-pro` (`aspect_ratio: 3:2`, `resolution: 2K`, one image), the prompt in
`batch.py`: six pieces in light neutral grey on magenta, so the game tints them (bronze, steel,
gold; the cape red for creatures, blue for heroes).
Processing (inline python, see the session): magenta keyed out, every piece cropped to its
picture, the horn mirrored, turned into light grey (luminance x 1.25), scaled to its place in the
gear texture (the old rects times four: helmet 96x48, shoulder 48x36, crown 80x40, cape 112x160,
horn 28x40, plume 28x48) with hard alpha; copied to `assets/textures/gear/<part>.png`.
+12
View File
@@ -0,0 +1,12 @@
# The gear parts laid over the detailed sprites (src/gfx.rs GEAR_*), 2026-11-08: one sheet,
# light neutral grey so the game tints them (bronze, steel, gold; the cape red or blue).
PROMPT = ("A sheet of six separate equipment pieces for a dark-fantasy pixel-art game, arranged in a grid of 3 columns and 2 rows, each piece centred "
"in its own cell and filling most of it, all in the same style: hand-painted pixel art, crisp edges, a dark near-black outline, shading lit "
"from the upper left, and every piece in LIGHT NEUTRAL GREY tones only (no other colours), so it can be tinted later. The background is a "
"completely flat pure magenta (#FF00FF) everywhere - no frames, no grid lines, no text. The pieces, in reading order: "
"1. a round metal helmet seen from the front, a dome with a riveted rim, no face, no visor; "
"2. a single rounded shoulder plate (pauldron) seen from the front, with two rivets; "
"3. a crown with three pointed spikes and small round gems; "
"4. a long cape seen from behind, hanging down, wider at the hem, with folds; "
"5. a single curved horn pointing up, slightly bent to the right; "
"6. a feather plume, a tall bushy crest.")
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

+34 -16
View File
@@ -1934,18 +1934,19 @@ fn gear_anchor(g: &Cell) -> GearAnchor {
}
// the gear's parts in their texture (grey, tinted by the metal or cloth colour at draw time):
// (x, y, w, h) in texels of GEAR_TEX
pub const GEAR_TEX: u32 = 96;
pub const GEAR_HELMET: (u32, u32, u32, u32) = (0, 0, 24, 12);
pub const GEAR_PAULDRON: (u32, u32, u32, u32) = (24, 0, 12, 9);
pub const GEAR_CROWN: (u32, u32, u32, u32) = (36, 0, 20, 10);
pub const GEAR_CAPE: (u32, u32, u32, u32) = (0, 14, 28, 40);
pub const GEAR_HORN: (u32, u32, u32, u32) = (28, 14, 7, 10);
pub const GEAR_PLUME: (u32, u32, u32, u32) = (36, 14, 7, 12);
// (x, y, w, h) in texels of GEAR_TEX; helmet, shoulder piece, crown, cape, horn and plume are
// generated pictures (art/generated/gear/), drawn over the simple shapes of gen_gear
pub const GEAR_TEX: u32 = 384;
pub const GEAR_HELMET: (u32, u32, u32, u32) = (0, 0, 96, 48);
pub const GEAR_PAULDRON: (u32, u32, u32, u32) = (96, 0, 48, 36);
pub const GEAR_CROWN: (u32, u32, u32, u32) = (144, 0, 80, 40);
pub const GEAR_CAPE: (u32, u32, u32, u32) = (0, 56, 112, 160);
pub const GEAR_HORN: (u32, u32, u32, u32) = (112, 56, 28, 40);
pub const GEAR_PLUME: (u32, u32, u32, u32) = (144, 56, 28, 48);
// the holidays' headwear (in its own colours, not tinted): a Christmas hat, a carved pumpkin, bunny ears
pub const GEAR_SANTA: (u32, u32, u32, u32) = (44, 14, 20, 20);
pub const GEAR_PUMPKIN: (u32, u32, u32, u32) = (66, 14, 22, 20);
pub const GEAR_EARS: (u32, u32, u32, u32) = (44, 36, 18, 18);
pub const GEAR_SANTA: (u32, u32, u32, u32) = (176, 56, 80, 80);
pub const GEAR_PUMPKIN: (u32, u32, u32, u32) = (264, 56, 88, 80);
pub const GEAR_EARS: (u32, u32, u32, u32) = (176, 144, 72, 72);
// where the gear of a 10x10 sprite goes (its cell, standing; per kind and view), for the
// holidays' headwear in the pixel-art style
@@ -2868,6 +2869,23 @@ fn gen_gear() -> Image {
shape(GEAR_HORN, &|x, y| (x - (1.0 - y) * 0.4 - 0.3).abs() < 0.16 + 0.3 * y, &|x, y| 0.95 - y * 0.25 - x * 0.1);
// plume: a feather bush
shape(GEAR_PLUME, &|x, y| (x - 0.5).powi(2) * 3.2 + (y - 0.5).powi(2) * 1.1 <= 0.26 + 0.04 * (y * 14.0).sin(), &|_x, y| 0.95 - y * 0.3);
// the generated parts (grey, sized to their places)
for (rect, png) in [
(GEAR_HELMET, include_bytes!("../assets/textures/gear/helmet.png") as &[u8]),
(GEAR_PAULDRON, include_bytes!("../assets/textures/gear/pauldron.png")),
(GEAR_CROWN, include_bytes!("../assets/textures/gear/crown.png")),
(GEAR_CAPE, include_bytes!("../assets/textures/gear/cape.png")),
(GEAR_HORN, include_bytes!("../assets/textures/gear/horn.png")),
(GEAR_PLUME, include_bytes!("../assets/textures/gear/plume.png")),
] {
let src = Image::from_file_with_format(png, Some(ImageFormat::Png)).expect("gear part");
for y in 0..rect.3 {
for x in 0..rect.2 {
let p = if x < src.width as u32 && y < src.height as u32 { src.get_pixel(x, y) } else { Color::new(0.0, 0.0, 0.0, 0.0) };
img.set_pixel(rect.0 + x, rect.1 + y, p);
}
}
}
// the holidays' headwear, coloured: a shape, outlined, its colour per texel
let mut cshape = |(ox, oy, w, h): (u32, u32, u32, u32), inside: &dyn Fn(f32, f32) -> bool, paint: &dyn Fn(f32, f32) -> Color| {
for y in 0..h {
@@ -3660,12 +3678,12 @@ mod sprite_tests {
}
out.export_png("/tmp/imp-cells.png");
let gear = gen_gear();
let mut g = Image::gen_image_color((GEAR_TEX * 4) as u16, (GEAR_TEX * 4) as u16, Color::new(0.35, 0.33, 0.38, 1.0));
for y in 0..GEAR_TEX * 4 {
for x in 0..GEAR_TEX * 4 {
let p = gear.get_pixel(x / 4, y / 4);
let mut g = Image::gen_image_color(GEAR_TEX as u16, GEAR_TEX as u16, Color::new(0.35, 0.33, 0.38, 1.0));
for y in 0..GEAR_TEX {
for x in 0..GEAR_TEX {
let p = gear.get_pixel(x, y);
if p.a > 0.5 {
g.set_pixel(x, GEAR_TEX * 4 - 1 - y, p);
g.set_pixel(x, GEAR_TEX - 1 - y, p);
}
}
}