152 lines
3.3 KiB
Python
152 lines
3.3 KiB
Python
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)
|
|
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())
|