from PIL import Image import sys from dataclasses import dataclass from generate import renderer from os import path visited = set() @dataclass class vec3: x: float y: float z: float @dataclass class Platform: scale: vec3 position: vec3 def parse_width(x, y, get_pixel): width = 0 while True: px = get_pixel(x, y) if px[0] != 0: width += 1 x += 1 else: break return width def parse_height(x, y, get_pixel): height = 0 while True: px = get_pixel(x, y) if px[0] != 0: height += 1 y += 1 else: break return height def round_to_one(n): if n == 0: return 1 else: return n def visit_pixels(x, y, width, height): for yi in range(round_to_one(height)): for xi in range(round_to_one(width)): xx = x + xi yy = y + yi location = (xx, yy) if location in visited: print(location) assert location not in visited visited.add(location) def parse_platform(x, y, get_pixel): width = parse_width(x, y, get_pixel) height = parse_height(x, y, get_pixel) visit_pixels(x, y, width, height) if width != 0 and height != 0: px = get_pixel(x, y) position = vec3( x + (width / 2), (px[0] - 128), y + (height / 2), ) scale = vec3( width, 1, height, ) return Platform( position=position, scale=scale, ) else: return None def find_platforms(im): width, height = im.size pixels = im.convert("RGB").getdata() def get_pixel(x, y): return pixels[y * width + x] platforms = [] for y in range(height): for x in range(width): if (x, y) not in visited: platform = parse_platform(x, y, get_pixel) if platform is not None: platforms.append(platform) return platforms def format_vec3(v): return ", ".join(( f"{n: 8.03f}" for n in [v.x, v.y, v.z] )) def generate_platform(platform): yield "{" yield f".position = vec3({format_vec3(platform.position)})," yield f".scale = vec3({format_vec3(platform.scale)})," yield "}," def generate_level(name, platforms): yield f"world::platform {name}_platforms[] = {{" for platform in platforms: yield from generate_platform(platform) yield "};" yield f"world::level {name}_level = {{" yield f".platforms = {name}_platforms," yield f".platforms_length = (sizeof ({name}_platforms)) / (sizeof (world::platform))," yield "};" def generate_file(name_platforms_list): yield '#include "demo/lizard/world.hpp"' yield "" yield f"namespace demo {{" yield "" for name, platforms in name_platforms_list: yield from generate_level(name, platforms) yield "" yield '}' def level_name(p): _, fn = path.split(p) name, _ = path.splitext(fn) return name def find_all_platforms(maps): for filename in maps: with Image.open(filename) as im: name = level_name(filename) platforms = find_platforms(im) yield (name, platforms) maps = sys.argv[1:] render, out = renderer() render(generate_file(find_all_platforms(maps))) sys.stdout.write(out.getvalue())