ajhahn.de
← the-way-out commits

Commit

the-way-out

v0.2.13

ajhahnde · May 2026 · 0eec54c9af8b58ad424c3e0ff59758e9d6b90396 · view on GitHub →

modified CHANGELOG.md
@@ -1,5 +1,21 @@
# CHANGELOG
## v0.2.13
A maintenance release. No gameplay, tools, or save-file format changes;
existing saves and custom levels load as-is.
### Fixes
- Update flow: on the packaged macOS `.app`, clicking **UPDATE** in the
main menu no longer leaves the old game window open next to the
freshly launched one. The post-update restart now hands off via
`/usr/bin/open -n` + `SystemExit(0)` (mirroring the existing
`/Applications` relocation path in `launcher.py`) instead of
`os.execv`'ing the bundle's bootloader — only the new instance
survives. Dev runs (`python main.py` / `python launcher.py`) still
restart via `os.execv` as before.
## v0.2.12
A level-editor polish release. No gameplay or save-file format
modified VERSION
@@ -1 +1 @@
v0.2.12
v0.2.13
modified main.py
@@ -1,4 +1,5 @@
import os
import subprocess
import sys
import threading
@@ -353,7 +354,25 @@ while running:
main_menu.draw(screen)
pygame.display.flip()
pygame.time.delay(900)
pygame.quit() # before execv
pygame.quit()
# On a PyInstaller --windowed macOS bundle, os.execv re-execs
# the bootloader from inside its Python child while the parent
# bootloader keeps its NSApplication alive — net result: two
# windows. `open -n` + SystemExit hands off cleanly via
# LaunchServices so only the new instance survives. Mirrors
# launcher._relocate_to_applications().
bundle = None
if getattr(sys, "frozen", False) and sys.platform == "darwin":
contents_macos = os.path.dirname(
os.path.realpath(sys.executable))
candidate = os.path.dirname(
os.path.dirname(contents_macos))
if (candidate.endswith(".app")
and os.path.isdir(candidate)):
bundle = candidate
if bundle is not None:
subprocess.Popen(["/usr/bin/open", "-n", bundle])
raise SystemExit(0)
if getattr(sys, "frozen", False):
os.execv(sys.executable, [sys.executable])
else: