juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

mkpieces.py (3543B)


      1 #!/usr/bin/env python3
      2 """Genera gfx/pieces.c: sprites de las piezas a partir de los glifos de ajedrez de
      3 DejaVu Sans. Cada pixel usa 2 bits: 0 transparente, 1 cuerpo, 2 contorno/detalle.
      4 Uso: python3 tools/mkpieces.py > gfx/pieces.c   (con --png ARCHIVO hace una muestra)"""
      5 import sys
      6 from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageChops
      7 
      8 FONT = '/usr/share/fonts/TTF/DejaVuSans.ttf'
      9 SIZES = [48, 32]
     10 ORDER = 'PNBRQK'
     11 FILLED = {'K': '♚', 'Q': '♛', 'R': '♜', 'B': '♝', 'N': '♞', 'P': '♟'}
     12 HOLLOW = {'K': '♔', 'Q': '♕', 'R': '♖', 'B': '♗', 'N': '♘', 'P': '♙'}
     13 
     14 def glyph(ch, size, box):
     15     f = ImageFont.truetype(FONT, box)
     16     im = Image.new('L', (size * 2, size * 2), 0)
     17     ImageDraw.Draw(im).text((size, size), ch, font=f, fill=255, anchor='mm')
     18     return im
     19 
     20 def sprite(p, size):
     21     box = int(size * 1.02)
     22     full = glyph(FILLED[p], size, box)
     23     hollow = glyph(HOLLOW[p], size, box)
     24     bb = full.getbbox()
     25     cx, cy = (bb[0] + bb[2]) // 2, (bb[1] + bb[3]) // 2
     26     off = (cx - size // 2, cy - size // 2 - (size // 24))
     27     crop = lambda im: im.crop((off[0], off[1], off[0] + size, off[1] + size))
     28     full, hollow = crop(full), crop(hollow)
     29     body = full.point(lambda v: 255 if v > 110 else 0)
     30     # cuerpo = silueta rellena: el glifo hueco relleno por dentro coincide con el lleno
     31     outer = body.filter(ImageFilter.MaxFilter(3))
     32     outline = ImageChops.subtract(outer, body)
     33     # detalle interior: las lineas del glifo hueco que caen dentro del cuerpo
     34     detail = hollow.point(lambda v: 255 if v > 140 else 0)
     35     inner = body.filter(ImageFilter.MinFilter(3))
     36     detail = ImageChops.multiply(detail, inner)
     37     px = []
     38     for y in range(size):
     39         for x in range(size):
     40             if outline.getpixel((x, y)) or detail.getpixel((x, y)): px.append(2)
     41             elif body.getpixel((x, y)): px.append(1)
     42             else: px.append(0)
     43     return px
     44 
     45 def main():
     46     if len(sys.argv) > 2 and sys.argv[1] == '--png':
     47         W = sum(SIZES) + 8
     48         im = Image.new('RGB', (len(ORDER) * 2 * (SIZES[0] + 4), W * 1), (120, 140, 90))
     49         x = 0
     50         for col, (b, o) in enumerate([((240, 240, 230), (20, 20, 20)), ((30, 30, 34), (200, 200, 200))]):
     51             for p in ORDER:
     52                 y = 0
     53                 for s in SIZES:
     54                     px = sprite(p, s)
     55                     for i, v in enumerate(px):
     56                         if v: im.putpixel((x + i % s, y + i // s), b if v == 1 else o)
     57                     y += s + 4
     58                 x += SIZES[0] + 4
     59         im.resize((im.width * 3, im.height * 3), Image.NEAREST).save(sys.argv[2])
     60         return
     61     print('/* pieces.c - sprites de las piezas, generado por tools/mkpieces.py (glifos de DejaVu Sans). No editar. */')
     62     print('#include "chess_gfx.h"\n')
     63     for s in SIZES:
     64         for p in ORDER:
     65             px = sprite(p, s)
     66             data = []
     67             for i in range(0, len(px), 4):
     68                 b = 0
     69                 for k in range(4):
     70                     b |= px[i + k] << (2 * k)
     71                 data.append(b)
     72             print('static const uint8_t P%d_%s[%d] = {' % (s, p, len(data)))
     73             for i in range(0, len(data), 24):
     74                 print('    ' + ', '.join('0x%02x' % v for v in data[i:i + 24]) + ',')
     75             print('};')
     76     print('\nconst PieceSet PIECES[%d] = {' % len(SIZES))
     77     for s in SIZES:
     78         print('    { %d, { 0, %s } },' % (s, ', '.join('P%d_%s' % (s, p) for p in ORDER)))
     79     print('};')
     80     print('const int NPIECESETS = %d;' % len(SIZES))
     81 
     82 main()