Add configuration option for ghost reset distance. Improve documentation.

This commit is contained in:
2025-12-20 17:12:58 -05:00
parent faf3f239d8
commit 7a3705d342
25 changed files with 132 additions and 28 deletions

View File

@@ -1,17 +1,24 @@
#!/usr/bin/env python
# Generate maze.txt geometry by tracing the outline of a binary maze image.
# The script expects the maze PNG to be white-on-black and writes walls/floor
# segments in the format ghostland.cpp consumes at runtime.
import matplotlib.image as mpimage
# TODO: parameterize this path via CLI flags or config.
img = mpimage.imread("/home/cowley/Pictures/maze.png")
rows = len(img)
cols = len(img[0])
def isfilled(val):
# Pixels brighter than ~20% are treated as walls.
return all(x > 0.2 for x in val)
def getval(img, x, y):
# Bounds-check helpers so we can safely probe virtual border pixels.
if y < 0 or y >= len(img):
return False
if x < 0 or x >= len(img[y]):
@@ -20,6 +27,8 @@ def getval(img, x, y):
segments = []
# Sweep the image in four directions to emit axis-aligned wall segments.
# Horizontal sweep detecting transitions from empty -> filled above (top edges).
for iy in range(-1, rows + 1):
seg_start = None
for ix in range(-1, cols + 1):
@@ -34,6 +43,7 @@ for iy in range(-1, rows + 1):
segments.append((seg_start, (cols - 0.5, iy - 0.5), (0.0, 0.0, 1.0)))
# Horizontal sweep detecting transitions from empty -> filled below (bottom edges).
for iy in range(-1, rows + 1):
seg_start = None
for ix in range(-1, cols + 1):
@@ -47,6 +57,7 @@ for iy in range(-1, rows + 1):
if seg_start is not None:
segments.append((seg_start, (cols - 0.5, iy + 0.5), (0.0, 0.0, -1.0)))
# Vertical sweep detecting transitions from empty -> filled on the left.
for ix in range(-1, cols + 1):
seg_start = None
for iy in range(-1, rows + 1):
@@ -60,6 +71,7 @@ for ix in range(-1, cols + 1):
if seg_start is not None:
segments.append((seg_start, (ix - 0.5, rows - 0.5), (-1.0, 0.0, 0.0)))
# Vertical sweep detecting transitions from empty -> filled on the right.
for ix in range(-1, cols + 1):
seg_start = None
for iy in range(-1, rows + 1):
@@ -73,10 +85,12 @@ for ix in range(-1, cols + 1):
if seg_start is not None:
segments.append((seg_start, (ix + 0.5, rows - 0.5), (1.0, 0.0, 0.0)))
print(segments[:10])
print(segments[:10]) # Quick sanity check; remove or redirect for batch runs.
# Serialize into the legacy maze.txt format ghostland.cpp expects.
res = {}
res["players"] = []
# Hard-coded spawn until a better level editor exists.
player = {
"y": 2.5,
"x": 845.0,
@@ -86,6 +100,7 @@ player = {
res["players"].append(player)
res["surfaces"] = []
for segment in segments:
# Build quads with outward normals stored as the fifth element.
p1 = {"x": segment[0][0], "z": -segment[0][1], "y": 0.0}
p2 = {
"x": segment[1][0],
@@ -110,10 +125,12 @@ xmax = 0.0
zmin = 0.0
zmax = 0.0
# Write the flattened surfaces followed by a floor bounding box so the game can detect footsteps.
with open("maze.txt", "w") as f:
f.write(f"{player['x']} {player['y']} {player['z']} {player['yaw']}\n")
f.write(f"{len(res['surfaces'])}\n")
for segment in res["surfaces"]:
# Track extrema to write a single floor plane at the end.
for point in segment[:4]:
if point["x"] < xmin:
xmin = point["x"]