Files
ascreamfromthedark-gb/scripts/generate_level.py
T
enne2 36e52d4d1a Implement run mechanic and level progression with top-left HUD indicator
Run (B + direction):
- player_logic.c: while holding B + direction with stamina >= 10, each tile
  takes 8 frames instead of 16 (move_progress += 2, LERP >>4 unchanged) and
  costs 10 stamina per tile. DAS_REPEAT_RUN=2 chains tiles fluidly.
- Falls back silently to normal walk when stamina < 10.

Level progression:
- New global 'level' (starts at 1). title->game resets to 1; reaching the
  hatch (victory/Going Deeper) + START increments before engine_init (new
  maze); defeat + START resets to 1.
- Top-left HUD 'L<n>' via 3 sprites (OAM 23-25) from new level.png asset
  (glyphs L, 0-9), generated by scripts/generate_level.py and converted
  with png2asset -keep_duplicate_tiles for predictable tile ordering.
- VRAM base aligned to an EVEN index (8x16 hardware ignores tile LSB) and
  placed after the stamina load claim to avoid the shared BG tile block.
- update_level_display() called every frame; hides during game over/title.

Docs: README, doc/gameplay.md and the technical report updated.
2026-06-24 11:56:19 +02:00

149 lines
3.0 KiB
Python

from PIL import Image
# Standard Game Boy palette (same as generate_assets.py)
# 0: White/transparent-for-sprites, 1: Light Gray, 2: Dark Gray, 3: Black
PALETTE = [
224, 248, 207, # 0
134, 192, 108, # 1
48, 104, 80, # 2
7, 24, 33 # 3
] + [0] * (256 * 3 - 12)
# 5x7 font, '1' = light pixel (on), drawn with light gray (1) on transparent (0).
GLYPHS = {
' ': [
"00000",
"00000",
"00000",
"00000",
"00000",
"00000",
"00000",
],
'L': [
"10000",
"10000",
"10000",
"10000",
"10000",
"10000",
"11111",
],
'0': [
"01110",
"10001",
"10011",
"10101",
"11001",
"10001",
"01110",
],
'1': [
"00100",
"01100",
"00100",
"00100",
"00100",
"00100",
"01110",
],
'2': [
"01110",
"10001",
"00001",
"00010",
"00100",
"01000",
"11111",
],
'3': [
"11110",
"00001",
"00001",
"01110",
"00001",
"00001",
"11110",
],
'4': [
"00010",
"00110",
"01010",
"10010",
"11111",
"00010",
"00010",
],
'5': [
"11111",
"10000",
"11110",
"00001",
"00001",
"10001",
"01110",
],
'6': [
"00110",
"01000",
"10000",
"11110",
"10001",
"10001",
"01110",
],
'7': [
"11111",
"00001",
"00010",
"00100",
"01000",
"10000",
"10000",
],
'8': [
"01110",
"10001",
"10001",
"01110",
"10001",
"10001",
"01110",
],
'9': [
"01110",
"10001",
"10001",
"01111",
"00001",
"00010",
"01100",
],
}
# Glyph order in the sprite sheet (top -> bottom). 11 glyphs, each 8x16 = 2 tiles.
# Index i (0-based) occupies tiles (2i, 2i+1) in level_tiles thanks to -keep_duplicate_tiles.
# 0: 'L', 1..10: '0'..'9'. (No blank glyph: hidden digits are moved offscreen instead.)
ORDER = ['L', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
def main():
# 8x16 per glyph, stacked vertically -> 8 wide x (16*11)=176 tall
img = Image.new("P", (8, 176), 0) # transparent background
img.putpalette(PALETTE)
for gi, name in enumerate(ORDER):
glyph = GLYPHS[name]
y_base = gi * 16
# Place the 5x7 glyph in the top rows (0..6), columns 1..5.
for row in range(7):
line = glyph[row]
for col in range(5):
if line[col] == '1':
img.putpixel((1 + col, y_base + row), 1) # light gray
# Rows 7..15 stay transparent (0)
img.save("level.png")
print("Generated level.png (11 glyphs: L, 0-9)")
if __name__ == "__main__":
main()