2 changed files with 165 additions and 35 deletions
@ -0,0 +1,120 @@
|
||||
import os |
||||
from PIL import Image |
||||
import numpy as np |
||||
|
||||
img_path = '/home/enne2/.gemini/antigravity/brain/69a2b2a9-088f-47ee-9f3c-9ba7ac332992/test_mockup_clean.png' |
||||
img = Image.open(img_path).convert('RGB') |
||||
img = img.resize((160, 144), Image.Resampling.LANCZOS) |
||||
gray = img.convert('L') |
||||
arr = np.array(gray) |
||||
|
||||
quantized = np.zeros_like(arr, dtype=np.uint8) |
||||
quantized[arr >= 192] = 0 |
||||
quantized[(arr >= 128) & (arr < 192)] = 1 |
||||
quantized[(arr >= 64) & (arr < 128)] = 2 |
||||
quantized[arr < 64] = 3 |
||||
|
||||
is_wall = np.zeros((18, 20), dtype=bool) |
||||
for y in range(18): |
||||
for x in range(20): |
||||
tile = quantized[y*8:(y+1)*8, x*8:(x+1)*8] |
||||
if np.sum(tile > 0) > 32: |
||||
is_wall[y, x] = True |
||||
|
||||
for y in range(18): |
||||
is_wall[y, 0] = False |
||||
is_wall[y, 19] = False |
||||
for x in range(20): |
||||
is_wall[0, x] = False |
||||
is_wall[16, x] = False |
||||
is_wall[17, x] = False |
||||
|
||||
mockup_extracted = {} |
||||
|
||||
# We'll extract 6 floor tiles to give variety! |
||||
floors = [] |
||||
for y in range(2, 15): |
||||
for x in range(2, 18): |
||||
if not is_wall[y, x]: |
||||
floors.append(quantized[y*8:(y+1)*8, x*8:(x+1)*8]) |
||||
if len(floors) == 6: |
||||
break |
||||
if len(floors) == 6: break |
||||
|
||||
# If we couldn't find 6, just pad |
||||
while len(floors) < 6: |
||||
floors.append(np.zeros((8, 8), dtype=np.uint8)) |
||||
|
||||
for y in range(1, 16): |
||||
for x in range(1, 19): |
||||
if is_wall[y, x]: |
||||
n = is_wall[y-1, x] |
||||
s = is_wall[y+1, x] |
||||
e = is_wall[y, x+1] |
||||
w = is_wall[y, x-1] |
||||
mask = (8 if n else 0) | (4 if e else 0) | (2 if s else 0) | (1 if w else 0) |
||||
if mask not in mockup_extracted: |
||||
mockup_extracted[mask] = quantized[y*8:(y+1)*8, x*8:(x+1)*8] |
||||
|
||||
# Ensure all 16 masks exist |
||||
# If a mask is missing, try to synthesize it by rotating/flipping or just defaulting to mask 15 |
||||
base_wall = mockup_extracted.get(15, np.full((8,8), 2, dtype=np.uint8)) |
||||
|
||||
def patch_mask(mask): |
||||
if mask in mockup_extracted: |
||||
return mockup_extracted[mask] |
||||
|
||||
# Very simple synthesis using the base wall 15, and floor tiles to cut the edges |
||||
t = np.copy(base_wall) |
||||
f = floors[0] |
||||
n = (mask & 8) != 0 |
||||
e = (mask & 4) != 0 |
||||
s = (mask & 2) != 0 |
||||
w = (mask & 1) != 0 |
||||
if not n: |
||||
t[0,:] = f[0,:] |
||||
t[1,:] = 1 # highlight |
||||
if not s: |
||||
t[6,:] = 3 |
||||
t[7,:] = f[7,:] |
||||
if not w: |
||||
t[:,0] = f[:,0] |
||||
t[:,1] = 2 |
||||
if not e: |
||||
t[:,7] = f[:,7] |
||||
t[:,6] = 2 |
||||
return t |
||||
|
||||
walls = [] |
||||
for mask in range(16): |
||||
walls.append(patch_mask(mask)) |
||||
|
||||
def to_gb_format(tile_np): |
||||
bytes_arr = [] |
||||
for r in range(8): |
||||
lo = hi = 0 |
||||
for c in range(8): |
||||
val = int(tile_np[r, c]) |
||||
if val & 1: lo |= (1 << (7 - c)) |
||||
if val & 2: hi |= (1 << (7 - c)) |
||||
bytes_arr.append(lo) |
||||
bytes_arr.append(hi) |
||||
return bytes_arr |
||||
|
||||
with open('src/tiles.c', 'w') as f: |
||||
f.write('#include "tiles.h"\n\n') |
||||
f.write(f'const unsigned char TileData[{(6+16)*16}] = {{\n') |
||||
|
||||
for i, fl in enumerate(floors): |
||||
f.write(f' // Floor variant {i}\n') |
||||
b = to_gb_format(fl) |
||||
f.write(' ' + ', '.join(f"0x{val:02X}" for val in b) + ',\n') |
||||
|
||||
for i, w in enumerate(walls): |
||||
f.write(f' // Wall {i}\n') |
||||
b = to_gb_format(w) |
||||
f.write(' ' + ', '.join(f"0x{val:02X}" for val in b) + ',\n') |
||||
|
||||
f.write('};\n') |
||||
|
||||
print("tiles.c generated directly from mockup!") |
||||
@ -1,38 +1,48 @@
|
||||
#include "tiles.h" |
||||
|
||||
const unsigned char TileData[272] = { |
||||
// Tile 0 (Mask Floor)
|
||||
0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, |
||||
// Tile 1 (Mask 0)
|
||||
0x00, 0x00, 0x1E, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x3E, 0x3E, 0x1E, 0x1E, |
||||
// Tile 2 (Mask 1)
|
||||
0x00, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, |
||||
// Tile 3 (Mask 2)
|
||||
0x00, 0x00, 0x1E, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, |
||||
// Tile 4 (Mask 3)
|
||||
0x00, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, |
||||
// Tile 5 (Mask 4)
|
||||
0x00, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, |
||||
// Tile 6 (Mask 5)
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
||||
// Tile 7 (Mask 6)
|
||||
0x00, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, |
||||
// Tile 8 (Mask 7)
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, |
||||
// Tile 9 (Mask 8)
|
||||
0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x3E, 0x3E, 0x1E, 0x1E, |
||||
// Tile 10 (Mask 9)
|
||||
0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, |
||||
// Tile 11 (Mask 10)
|
||||
0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, |
||||
// Tile 12 (Mask 11)
|
||||
0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, |
||||
// Tile 13 (Mask 12)
|
||||
0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, |
||||
// Tile 14 (Mask 13)
|
||||
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
||||
// Tile 15 (Mask 14)
|
||||
0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, |
||||
// Tile 16 (Mask 15)
|
||||
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x10, 0xEF, 0x04, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, |
||||
const unsigned char TileData[352] = { |
||||
// Floor variant 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
// Floor variant 1
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
// Floor variant 2
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
// Floor variant 3
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
// Floor variant 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
// Floor variant 5
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
||||
// Wall 0
|
||||
0x7E, 0x7E, 0x7C, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x7E, 0x7C, 0x7C, 0x00, 0x00, |
||||
// Wall 1
|
||||
0x00, 0x02, 0xFC, 0x02, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0xFC, 0xFE, 0x00, 0x02, |
||||
// Wall 2
|
||||
0x00, 0x42, 0x3C, 0x42, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, |
||||
// Wall 3
|
||||
0x00, 0x02, 0xFC, 0x02, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, |
||||
// Wall 4
|
||||
0x00, 0x40, 0x3F, 0x40, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x3F, 0x7F, 0x00, 0x40, |
||||
// Wall 5
|
||||
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, |
||||
// Wall 6
|
||||
0x00, 0x40, 0x3F, 0x40, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, |
||||
// Wall 7
|
||||
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, |
||||
// Wall 8
|
||||
0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x3C, 0x7E, 0x00, 0x42, |
||||
// Wall 9
|
||||
0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0xFC, 0xFE, 0x00, 0x02, |
||||
// Wall 10
|
||||
0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, |
||||
// Wall 11
|
||||
0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, |
||||
// Wall 12
|
||||
0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x3F, 0x7F, 0x00, 0x40, |
||||
// Wall 13
|
||||
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, |
||||
// Wall 14
|
||||
0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, |
||||
// Wall 15
|
||||
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, |
||||
}; |
||||
|
||||
Loading…
Reference in new issue