Implement a hacky PoC

It does not do much, but if you are adventurous, it gives a "could work
one day" vibes :-P
master
LEdoian 6 months ago
parent 892140c313
commit ada68944ca

@ -1 +1,7 @@
__version__ = '0.0.1a1' __version__ = '0.0.1a1'
import abc
import pygame
class Renderer(abc.ABC):
@abc.abstractmethod
def render(self, item: str, w: int, h: int) -> pygame.Surface: ...

@ -1,5 +1,99 @@
import pygame as pg
import pygame.freetype as pgft
from triditko.renderers import DrawItemNameRenderer
from triditko.utils import align
import json
import importlib
def get_base_surface(screen_size, categories) -> (pg.Surface, (int, int)):
"""Returns a surface template with legend, suitable as a basis for rendering the rest.
Very barebones, will need to be remade for advanced features."""
w, h = screen_size
result = pg.Surface((w, h))
result.fill((0,0,0))
label_height = h//5
label_width = w//len(categories)
label_pos_y = label_height*4
renderer = DrawItemNameRenderer()
# NOTE: I wanted them to have a border, but too lazy.
for i, cat in enumerate(categories):
label = renderer.render(cat, label_width, label_height)
result.blit(label, (i*label_width, label_pos_y))
return result, (w, label_pos_y)
def main(): def main():
print('hi') # Inspired by quickstart at <https://www.pygame.org/docs/>
pg.init()
initial_screen_size = (800, 600)
screen = pg.display.set_mode(
initial_screen_size, # size
pg.RESIZABLE, # flags; TODO: pg.OPENGL?
)
clock = pg.time.Clock()
font = pgft.Font(None)
#TODO: use argparse and reasonable stuff
categories = ['good', 'bad', 'ugly']
bindings = {
pg.K_1: 'good',
pg.K_2: 'bad',
pg.K_3: 'ugly',
}
escape_char = pg.K_ESCAPE
items = [f'item_{i}' for i in range(20)]
renderer = 'triditko.renderers:DrawItemNameRenderer'
outputfile = '/dev/stdout'
result = {k: [] for k in categories}
# dafuq boilerplate?
renderer_module, renderer_path = renderer.split(':')
renderer_module = importlib.import_module(renderer_module)
for sgmt in renderer_path.split('.'):
renderer_module = getattr(renderer_module, sgmt)
renderer = renderer_module() # FIXME: not a module anymore.
# TODO: draw first or at least create an event to do so?
base_surface, (item_w, item_h) = get_base_surface(initial_screen_size, categories)
current_item = 0
running = True
pressed = False
while running:
# event loop, yada yada
for event in pg.event.get():
if event.type == pg.QUIT:
running = False # The while is too outer :-/
elif event.type == pg.KEYDOWN and not pressed:
# We need to do our own press handling
pressed = True
if event.key == escape_char:
running = False
elif event.key in bindings:
cat = bindings[event.key]
result[cat].append(items[current_item])
current_item += 1
# FIXME: too hacky error handling!
running = current_item < len(items)
elif pressed and event.type == pg.KEYUP:
# FIXME: does not work for multiple presses!
pressed = False
# FIXME: hacky
if not running: continue
# It is unnecessary (bad, even) to redraw the item every tick, but good for PoC
item_sfc = base_surface.copy()
item_rendered = renderer.render(items[current_item], item_w, item_h)
pos = align((item_w, item_h), item_rendered, 'cc')
item_sfc.blit(item_rendered, pos)
screen.blit(item_sfc, (0,0))
pg.display.flip()
clock.tick(60)
with open(outputfile, 'wt') as f:
json.dump(result, f)
pg.quit()
if __name__ == '__main__': main() if __name__ == '__main__': main()

@ -0,0 +1,14 @@
from triditko import Renderer
from triditko.utils import align
import pygame as pg
import pygame.freetype as pgft
class DrawItemNameRenderer(Renderer):
def render(self, item, w, h):
result = pg.Surface((w, h))
font = pgft.Font(None, size=25)
rendered, _brect = font.render(item, fgcolor=(255,255,255)) #white.
pos = align(result, rendered)
result.blit(rendered, pos)
return result

@ -0,0 +1,37 @@
import pygame as pg
def _get_dimen(obj) -> (int, int):
"""Gets width, height from various representations.
Permitted representations:
- pg.Surface
- (w, h) tuple
- tbd
"""
if isinstance(obj, pg.Surface):
return obj.get_size()
if isinstance(obj, tuple):
assert isinstance(obj[0], int)
assert isinstance(obj[1], int)
return obj[0], obj[1]
raise NotImplementedError(f"bad input {obj} for {__name__}._get_dimen")
def align(bottom, top, alignment='cc'):
"""Returns the position for top surface so that it is aligned to the bottom one in the specified way.
alignment is t/c/b × l/c/r.""" # Go figure what that means lol.
# Somehow this is not part of pygame?
valign, halign = alignment
bw, bh = _get_dimen(bottom)
tw, th = _get_dimen(top)
x = {
'l': 0,
'r': bw - tw,
'c': (bw//2) - (tw//2),
}[halign]
y = {
't': 0,
'b': bh - th,
'c': (bh//2) - (th//2),
}[valign]
return x, y
Loading…
Cancel
Save