Claimed floors reworked: roughly hewn castle flagstones worn smooth, no visible tile grid
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No files matched your search
@@ -1,53 +1,58 @@
|
||||
# The masters' claimed floors (high-res)
|
||||
|
||||
Generated on 2026-11-07 with fal.ai: `fal-ai/nano-banana-pro`, `aspect_ratio: 3:2`,
|
||||
`resolution: 2K`, one image per master. Each sheet has six slabs in a 3x2 grid on magenta; five
|
||||
are used (`HD_FLOORS` in `src/gfx.rs`, with weights so plain slabs come more often).
|
||||
`resolution: 2K`, one image per master. Each sheet has six tiles in a 3x2 grid on magenta; tiles
|
||||
1-5 are used (plain, engraving, cracks, chipped, broken; `HD_FLOORS` in `src/gfx.rs`, weighted
|
||||
4:1:3:2:1 so plain tiles come most often).
|
||||
|
||||
The first version (`v1/`) had regular slabs with thick grout frames and looked too even; this
|
||||
one asks for roughly hewn castle flagstones worn smooth by many feet.
|
||||
|
||||
Prompt template (`{floor}` per master):
|
||||
|
||||
```text
|
||||
A texture sheet of six square floor tiles for a dark-fantasy dungeon strategy game, arranged in a grid of 3 columns and 2 rows, the tiles separated by thin flat pure magenta (#FF00FF) gaps, magenta also around the outside. Every tile is seen straight from above (orthographic top-down, no perspective), flat even lighting, no shadows, and fills its square completely. Every tile is one square floor slab made of a few fitted flagstones, with a dark grout line along all four edges, so the tiles fit together in any arrangement. All six tiles use the same stone, colours and style: {floor} The six tiles differ: tile 1 intact and clean; tile 2 with a large carved engraving in the middle; tile 3 with fine hairline cracks; tile 4 with a chipped corner and a few missing stone splinters; tile 5 with a broken flagstone, cracked through, a piece sunk and loose rubble; tile 6 with small engravings and worn edges. Style: hand-painted pixel art, chunky clear shapes, crisp edges, readable at small size. No text, no labels, no numbers.
|
||||
A texture sheet of six square floor tiles for a dark-fantasy dungeon strategy game, arranged in a grid of 3 columns and 2 rows, the tiles separated by thin flat pure magenta (#FF00FF) gaps, magenta also around the outside. Every tile is seen straight from above (orthographic top-down, no perspective), flat even lighting, no shadows, and fills its square completely. Every tile is a piece of the floor of an old medieval castle dungeon: irregular, roughly hewn flagstones of clearly different sizes and shapes (some large, some small, uneven outlines, slightly rounded chipped edges), laid with uneven mortar joints of varying width - not a regular grid. Centuries of feet have worn the stones smooth and polished: soft sheen on the walked-on surfaces, rounded worn edges, shallow dips. Along the four edges of every tile runs a mortar joint as thin and irregular as the ones inside, so the tiles fit together in any arrangement without a visible grid. All six tiles use the same stone, colours and style: {floor} The six tiles differ: tile 1 plain worn stones; tile 2 with a carved engraving on one large stone, worn half smooth; tile 3 with hairline cracks; tile 4 with a chipped stone corner and missing splinters; tile 5 with a broken flagstone, cracked through, a piece sunk and loose rubble; tile 6 with a few small worn engravings. Style: hand-painted pixel art, crisp edges, muted natural stone colours, readable at small size. No text, no labels, no numbers.
|
||||
```
|
||||
|
||||
## player
|
||||
|
||||
```text
|
||||
polished flagstones of medium crimson-red stone with a purple tint (clearly brighter than black), the engravings are glowing-edged demonic runes, horned skulls and pentagram-like sigils of an evil dungeon master.
|
||||
dark red-brown stone with a crimson-purple tint (medium brightness, not black); the engravings are worn demonic runes and horned skulls of an evil dungeon master, the grooves faintly glowing red.
|
||||
```
|
||||
|
||||
## mossgrim
|
||||
|
||||
```text
|
||||
damp mossy green-grey flagstones; the engravings show mushrooms, spores and coiling mould tendrils, green fungus and moss grow out of the grout lines and cracks, a mouldy cellar master's floor.
|
||||
grey-green stone, damp; moss and small fungi grow in the mortar joints and cracks; the engravings are worn mushrooms and coiling mould tendrils.
|
||||
```
|
||||
|
||||
## nightwell
|
||||
|
||||
```text
|
||||
elegant deep-blue marble flagstones with fine silver veins, the engravings are refined lilies, crescent moons and elegant curling filigree inlaid with silver, the floor of a cold, cultivated and vain lady of the night.
|
||||
cold blue-grey slate and marble stones with faint silver veins; the engravings are worn lilies and crescent moons with remnants of silver inlay.
|
||||
```
|
||||
|
||||
## saffrax
|
||||
|
||||
```text
|
||||
warm ochre-yellow sandstone flagstones with brass inlays, the engravings are alchemical sigils, suns and sulphur symbols, a few scorch marks, the floor of a greedy alchemist master of sulphur and gold.
|
||||
warm ochre-brown sandstone with a few brass studs; the engravings are worn alchemical sigils and suns, a few sooty scorch marks and yellow sulphur stains.
|
||||
```
|
||||
|
||||
## Processing
|
||||
|
||||
`tools/make_floor_tiles.py` crops the slabs, fills magenta inside them (chipped corners, holes)
|
||||
with a dark void, brightens if asked, scales and reduces the colours:
|
||||
`tools/make_floor_tiles.py` crops the tiles, fills magenta inside them (chipped corners, holes)
|
||||
with a dark void, cuts a thin edge off (the joints and frames the model drew around every tile),
|
||||
evens out the light (no vignette, all tiles equally bright, so the grid does not show), scales
|
||||
and reduces the colours:
|
||||
|
||||
```bash
|
||||
T=tools/make_floor_tiles.py
|
||||
python3 $T player-raw.png player --grid 2x3 --pick 1,2,3,5,6 --size 128 --bright 1.45 # and --size 64
|
||||
python3 $T mossgrim-raw.png mossgrim --grid 2x3 --pick 1,2,3,4,5 --size 128
|
||||
python3 $T nightwell-raw.png nightwell --grid 2x3 --pick 1,2,3,4,5 --size 128 --bright 1.15
|
||||
python3 $T saffrax-raw.png saffrax --grid 2x3 --pick 1,2,3,4,5 --size 128 --bright 0.82
|
||||
python3 $T player-raw.png player --grid 2x3 --pick 1,2,3,4,5 --size 128 --bright 1.1 --inset 0.03 --flatten
|
||||
python3 $T mossgrim-raw.png mossgrim --grid 2x3 --pick 1,2,3,4,5 --size 128 --inset 0.03 --flatten
|
||||
python3 $T nightwell-raw.png nightwell --grid 2x3 --pick 1,2,3,4,5 --size 128 --inset 0.045 --flatten
|
||||
python3 $T saffrax-raw.png saffrax --grid 2x3 --pick 1,2,3,4,5 --size 128 --inset 0.03 --flatten
|
||||
# the same with --size 64
|
||||
```
|
||||
|
||||
The player's sheet came out too dark (brightened by 1.45); its fourth slab repeats the big skull
|
||||
with a chipped corner and is left out. Saffrax' sandstone was too glaring (darkened by 0.82).
|
||||
`<name>-64.png` / `<name>-128.png` are copied to `assets/textures/floor-<name>.png` /
|
||||
`floor-<name>-128.png`; `<name>-128-preview.png` shows a floor laid out at random.
|
||||
|
Before Width: | Height: | Size: 277 KiB After Width: | Height: | Size: 368 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 4.1 MiB After Width: | Height: | Size: 4.5 MiB |
|
Before Width: | Height: | Size: 397 KiB After Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 4.4 MiB After Width: | Height: | Size: 4.3 MiB |
|
Before Width: | Height: | Size: 327 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 4.2 MiB After Width: | Height: | Size: 4.4 MiB |
|
Before Width: | Height: | Size: 326 KiB After Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 4.3 MiB After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 4.1 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 4.3 MiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
@@ -350,21 +350,22 @@ const HD_TILES: [(u32, u32, &[u8], &[u8]); 9] = [
|
||||
(T_DIAMOND, 2, include_bytes!("../assets/textures/diamond.png"), include_bytes!("../assets/textures/diamond-128.png")),
|
||||
];
|
||||
|
||||
// The masters' claimed floors in the high-res style: five single slabs each (with a grout line
|
||||
// along the edges, so they fit in any order), in the master's colour with engravings of their
|
||||
// own and some of them cracked, chipped or broken. They go into cells of their own (from
|
||||
// The masters' claimed floors in the high-res style: five single tiles each of roughly hewn,
|
||||
// worn-smooth castle flagstones (cut so they fit in any order), in the master's colour with
|
||||
// engravings of their own and some of them cracked, chipped or broken. They go into cells of their own (from
|
||||
// T_HDFLOOR on, five per master); a tile picks one by its position, weighted (plain slabs more
|
||||
// often than the big engravings and the broken ones).
|
||||
// (the claimed floor's cells, the first own cell, 64x64 slabs side by side, 128x128 ones, weights)
|
||||
pub const T_HDFLOOR: u32 = 224;
|
||||
const HD_FLOORS: [(u32, u32, &[u8], &[u8], [u32; 5]); 4] = [
|
||||
// the player: crimson stone, demonic runes and horned skulls (plain, big engraving, cracks, broken, small engravings)
|
||||
(T_CLAIM, T_HDFLOOR, include_bytes!("../assets/textures/floor-player.png"), include_bytes!("../assets/textures/floor-player-128.png"), [4, 1, 3, 1, 2]),
|
||||
// Mossgrim: mossy green slabs, mushrooms and mould (plain, big engraving, cracks, chipped, broken)
|
||||
// every floor: plain, engraving, cracks, chipped, broken
|
||||
// the player: red-brown stone, demonic runes and horned skulls
|
||||
(T_CLAIM, T_HDFLOOR, include_bytes!("../assets/textures/floor-player.png"), include_bytes!("../assets/textures/floor-player-128.png"), [4, 1, 3, 2, 1]),
|
||||
// Mossgrim: damp grey-green stone, moss in the joints, mushrooms and mould
|
||||
(T_RIVAL1, T_HDFLOOR + 5, include_bytes!("../assets/textures/floor-mossgrim.png"), include_bytes!("../assets/textures/floor-mossgrim-128.png"), [4, 1, 3, 2, 1]),
|
||||
// Lady Nightwell: blue marble, silver lilies and moons
|
||||
// Lady Nightwell: blue-grey slate and marble, lilies and moons
|
||||
(T_RIVAL2, T_HDFLOOR + 10, include_bytes!("../assets/textures/floor-nightwell.png"), include_bytes!("../assets/textures/floor-nightwell-128.png"), [4, 1, 3, 2, 1]),
|
||||
// Saffrax: ochre sandstone, brass and alchemical sigils
|
||||
// Saffrax: ochre sandstone, brass studs, alchemical sigils and suns
|
||||
(T_RIVAL3, T_HDFLOOR + 15, include_bytes!("../assets/textures/floor-saffrax.png"), include_bytes!("../assets/textures/floor-saffrax-128.png"), [4, 1, 3, 2, 1]),
|
||||
];
|
||||
|
||||
|
||||
@@ -6,10 +6,13 @@ palette shared by all tiles of the sheet.
|
||||
|
||||
Usage:
|
||||
make_floor_tiles.py raw.png out_prefix --grid 2x3 --pick 1,2,3,5,6 [--size 128]
|
||||
[--colors 48] [--bright 1.0]
|
||||
[--colors 48] [--bright 1.0] [--inset 0.0] [--flatten]
|
||||
|
||||
--pick which cells to keep, numbered row by row from 1
|
||||
--bright factor on the colours (above 1: lighter)
|
||||
--inset cut this share off every side (a frame or edge joint the model drew around the tile)
|
||||
--flatten even out the light: no vignette towards the edges, all tiles equally bright, so
|
||||
the grid of tiles does not show on the floor
|
||||
|
||||
Writes out_prefix-<size>.png: the picked tiles side by side, and out_prefix-<size>-preview.png
|
||||
(a 6x4 floor of them laid out at random, scaled up 2x). Needs Pillow.
|
||||
@@ -17,7 +20,7 @@ Writes out_prefix-<size>.png: the picked tiles side by side, and out_prefix-<siz
|
||||
import argparse
|
||||
import random
|
||||
|
||||
from PIL import Image, ImageEnhance
|
||||
from PIL import Image, ImageEnhance, ImageFilter, ImageStat
|
||||
|
||||
VOID = (22, 14, 18)
|
||||
|
||||
@@ -36,6 +39,8 @@ def main():
|
||||
ap.add_argument("--size", type=int, default=128)
|
||||
ap.add_argument("--colors", type=int, default=48)
|
||||
ap.add_argument("--bright", type=float, default=1.0)
|
||||
ap.add_argument("--inset", type=float, default=0.0)
|
||||
ap.add_argument("--flatten", action="store_true")
|
||||
a = ap.parse_args()
|
||||
rows, cols = (int(v) for v in a.grid.split("x"))
|
||||
pick = [int(v) - 1 for v in a.pick.split(",")]
|
||||
@@ -56,9 +61,24 @@ def main():
|
||||
for x in range(tile.width):
|
||||
if magenta(tp[x, y]):
|
||||
tp[x, y] = VOID
|
||||
if a.bright != 1.0:
|
||||
tile = ImageEnhance.Brightness(tile).enhance(a.bright)
|
||||
tiles.append(tile.resize((a.size, a.size), Image.LANCZOS))
|
||||
if a.inset > 0:
|
||||
d = int(tile.width * a.inset)
|
||||
tile = tile.crop((d, d, tile.width - d, tile.height - d))
|
||||
tiles.append(tile)
|
||||
if a.flatten:
|
||||
# divide by the large-scale brightness: every tile gets the same, even brightness (the
|
||||
# sheet's mean), so neither a vignette nor a lighter or darker tile shows the grid
|
||||
blurs = [t.convert("L").filter(ImageFilter.GaussianBlur(t.width / 5)) for t in tiles]
|
||||
mean = sum(ImageStat.Stat(b).mean[0] for b in blurs) / len(blurs)
|
||||
for t, blur in zip(tiles, blurs):
|
||||
bp, tp = blur.load(), t.load()
|
||||
for y in range(t.height):
|
||||
for x in range(t.width):
|
||||
f = mean / max(bp[x, y], 1)
|
||||
tp[x, y] = tuple(min(255, int(c * f)) for c in tp[x, y])
|
||||
if a.bright != 1.0:
|
||||
tiles = [ImageEnhance.Brightness(t).enhance(a.bright) for t in tiles]
|
||||
tiles = [t.resize((a.size, a.size), Image.LANCZOS) for t in tiles]
|
||||
|
||||
strip = Image.new("RGB", (a.size * len(tiles), a.size))
|
||||
for k, t in enumerate(tiles):
|
||||
|
||||