diff -ruN a/main.py b/main.py --- a/main.py 1969-12-31 21:00:00.000000000 -0300 +++ b/main.py 2026-11-04 23:47:43.099707009 -0300 @@ -0,0 +1,6 @@ +import pygame +import asyncio + +from src import main + +asyncio.run(main.main()) diff -ruN a/run_game.py b/run_game.py --- a/run_game.py 2026-11-04 23:43:16.239476711 -0300 +++ b/run_game.py 1969-12-31 21:00:00.000000000 -0300 @@ -1,2 +0,0 @@ -from src import main - diff -ruN a/src/boss.py b/src/boss.py --- a/src/boss.py 2026-11-04 23:43:16.261854606 -0300 +++ b/src/boss.py 2026-11-04 23:47:42.789063580 -0300 @@ -1,8 +1,8 @@ from random import * from math import * -from thing import * -from ship import * -import state, settings, sound +from .thing import * +from .ship import * +from . import state, settings, sound class Boss(Ship): hp0 = 50 diff -ruN a/src/camera.py b/src/camera.py --- a/src/camera.py 2026-11-04 23:43:16.262998722 -0300 +++ b/src/camera.py 2026-11-04 23:47:42.800993729 -0300 @@ -1,7 +1,7 @@ -from __future__ import division + from pygame import * from math import * -import settings, img, state +from . import settings, img, state pscale = 30 @@ -34,7 +34,7 @@ try: imgname, x, y, z, theta, ascale, obj = layer except: - print layer + print(layer) raise if imgname == "shroud": return drawshroud() diff -ruN a/src/effect.py b/src/effect.py --- a/src/effect.py 2026-11-04 23:43:16.264987038 -0300 +++ b/src/effect.py 2026-11-04 23:47:42.823925286 -0300 @@ -1,7 +1,7 @@ from random import * from math import * -from thing import * -import state +from .thing import * +from . import state tau = 2 * pi class Particles(Thing): diff -ruN a/src/img.py b/src/img.py --- a/src/img.py 2026-11-04 23:43:16.262660058 -0300 +++ b/src/img.py 2026-11-04 23:47:43.099956465 -0300 @@ -1,10 +1,13 @@ -from __future__ import division + from pygame import * from random import * from math import * import glob -import settings +from . import settings + +def cmp(a, b): + return (a > b) - (a < b) cache = {} fonts = {} @@ -105,7 +108,7 @@ img = Surface((120, 120)).convert_alpha() img.fill((0, 255, 0)) elif imgname.startswith("rgb"): - cs = map(int, imgname[3:].split(",")) + cs = list(map(int, imgname[3:].split(","))) img = Surface((40, 40)).convert_alpha() img.fill(cs) elif imgname.startswith("hp:"): diff -ruN a/src/main.py b/src/main.py --- a/src/main.py 2026-11-04 23:43:16.264281044 -0300 +++ b/src/main.py 2026-11-04 23:47:43.099300388 -0300 @@ -1,57 +1,45 @@ -from __future__ import division +import asyncio +import time as pytime from pygame import * -import datetime -import settings, play, scene, img, state +from . import settings, play, scene, img, state -if settings.reset: - state.reset() - -clock = time.Clock() - -mixer.pre_init(22050, -16, 2, 0) -flags = FULLSCREEN if settings.fullscreen else 0 -display.set_mode(settings.size, flags) -display.set_caption(settings.gamename + " | Loading...") -mouse.set_visible(not settings.fullscreen) -img.preload() -init() -display.set_caption(settings.gamename) - -scene.scenes.append(play.Scene()) - -accum = 0 - -nframe, nslow, toldslow = 0, 0, False - -while scene.scenes: - s = scene.scenes[-1] - dt0 = clock.tick(settings.fps) - kpressed = key.get_pressed() - kdowns = [] - for e in event.get(): - if e.type == QUIT: - del scene.scenes[:] - if e.type == KEYDOWN: - kdowns.append(e.key) - if settings.DEBUG and K_F12 in kdowns: - fname = datetime.datetime.now().strftime("screenshots/screenshot-%Y%m%d%H%M%S.png") - image.save(display.get_surface(), fname) - accum += min(0.001 * dt0, 0.1) * (5 if settings.DEBUG and kpressed[K_TAB] else 1) - dt = 1 / settings.fps - while accum > dt: - s.think(dt, kpressed, kdowns) - accum -= dt +async def main(): + if settings.reset: + state.reset() + + mixer.pre_init(22050, -16, 2, 0) + display.set_mode(settings.size) + display.set_caption(settings.gamename + " | Loading...") + await asyncio.sleep(0) + img.preload() + init() + display.set_caption(settings.gamename) + + scene.scenes.append(play.Scene()) + + accum = 0 + last = pytime.time() + + while True: + if not scene.scenes: + # the page has nowhere to quit to: start again from the saved stage + scene.scenes.append(play.Scene()) + s = scene.scenes[-1] + # frame limiter for the browser: the page needs control back every frame + await asyncio.sleep(max(0.0, 1.0 / settings.fps - (pytime.time() - last))) + now = pytime.time() + dt0 = (now - last) * 1000 + last = now + kpressed = key.get_pressed() kdowns = [] - s.draw() - if settings.DEBUG: - display.set_caption("%s %.1ffps" % (settings.gamename, clock.get_fps())) - if not settings.lowres and not toldslow: - nframe += 1 - nslow += clock.get_fps() < 15 - if nframe > 200 and nslow > 0.2 * nframe: - print "Note: game running slow. Consider the flag --lowres to disable some special effects." - toldslow = True - display.flip() -quit() - - + for e in event.get(): + if e.type == KEYDOWN: + kdowns.append(e.key) + accum += min(0.001 * dt0, 0.1) + dt = 1 / settings.fps + while accum > dt: + s.think(dt, kpressed, kdowns) + accum -= dt + kdowns = [] + s.draw() + display.flip() diff -ruN a/src/play.py b/src/play.py --- a/src/play.py 2026-11-04 23:43:16.262325561 -0300 +++ b/src/play.py 2026-11-04 23:47:42.880648934 -0300 @@ -1,7 +1,7 @@ from pygame import * from math import * from random import * -import scene, camera, state, img, settings +from . import scene, camera, state, img, settings class Scene(object): def __init__(self): diff -ruN a/src/settings.py b/src/settings.py --- a/src/settings.py 2026-11-04 23:43:16.263588925 -0300 +++ b/src/settings.py 2026-11-04 23:47:43.099485428 -0300 @@ -1,9 +1,10 @@ +import os import sys gamename = "The Eight Bit Passage" -savename = "save.pkl" +savename = "/saves/save.pkl" if os.path.isdir("/saves") else "save.pkl" # on the web the page keeps /saves in the browser DEBUG = "--DEBUG" in sys.argv -lowres = "--lowres" in sys.argv +lowres = True # the per-pixel image noise is too slow in the browser fullscreen = "--fullscreen" in sys.argv reset = "--reset" in sys.argv easy = "--easy" in sys.argv diff -ruN a/src/ship.py b/src/ship.py --- a/src/ship.py 2026-11-04 23:43:16.263930256 -0300 +++ b/src/ship.py 2026-11-04 23:47:43.100125297 -0300 @@ -1,9 +1,12 @@ -from __future__ import division + from random import * from math import * -from thing import * -from effect import * -import settings, state, sound +from .thing import * +from .effect import * +from . import settings, state, sound + +def cmp(a, b): + return (a > b) - (a < b) def piratelayers(level): if level == 1 or level == 2: diff -ruN a/src/sound.py b/src/sound.py --- a/src/sound.py 2026-11-04 23:43:16.260759824 -0300 +++ b/src/sound.py 2026-11-04 23:47:42.940645263 -0300 @@ -1,5 +1,5 @@ from pygame import * -import settings +from . import settings cache = {} def playsound(sname): diff -ruN a/src/state.py b/src/state.py --- a/src/state.py 2026-11-04 23:43:16.265457243 -0300 +++ b/src/state.py 2026-11-04 23:47:43.100470336 -0300 @@ -1,8 +1,13 @@ # The game state from random import * -import cPickle, os -import ship, thing, effect, settings, boss, img, sound, scene +import pickle, os +from . import ship, thing, effect, settings, boss, img, sound, scene + + +def _pydiv(a, b): + # Python 2 "/": integer division when both operands are ints + return a // b if isinstance(a, int) and isinstance(b, int) else a / b # Call at program start def init(): @@ -76,12 +81,12 @@ def save(): obj = stage, atboss - cPickle.dump(obj, open(settings.savename, "wb")) + pickle.dump(obj, open(settings.savename, "wb")) def load(): global stage, atboss try: - obj = cPickle.load(open(settings.savename, "rb")) + obj = pickle.load(open(settings.savename, "rb")) stage, atboss = obj except: stage, atboss = 1, False @@ -266,7 +271,7 @@ x, vx = choice([(5, 1.5), (-5, -1.5)]) vy = uniform(1, 1.5) t = (dy * (vylast - legvy) + ymax * legvy) / (legvy * (vylast - vy)) - if t < dy / legvy: + if t < _pydiv(dy, legvy): t = ymax / (legvy - vy) y = yc0 + dy + 10 sq.append(ship.MineShip((x - t * vx, y - t * vy, 0), (vx, vy), plevel)) @@ -278,7 +283,7 @@ x, vx = choice([(5, 1.5), (-5, -1.5)]) vy = uniform(1, 1.5) t = (dy * (vylast - legvy) + ymax * legvy) / (legvy * (vylast - vy)) - if t < dy / legvy: + if t < _pydiv(dy, legvy): t = ymax / (legvy - vy) y = yc0 + dy + 10 sq.append(ship.JumpShip((x - t * vx, y - t * vy, 0), (vx, vy), plevel)) @@ -297,7 +302,7 @@ x, vx = choice([(5, 1.5), (-5, -1.5)]) vy = uniform(1, 1.5) t = (dy * (vylast - legvy) + ymax * legvy) / (legvy * (vylast - vy)) - if t < dy / legvy: + if t < _pydiv(dy, legvy): t = ymax / (legvy - vy) y = yc0 + dy + 10 sq.append(ship.MineShip((x - t * vx, y - t * vy, 0), (vx, vy), plevel)) @@ -316,7 +321,7 @@ x, vx = choice([(5, 1.5), (-5, -1.5)]) vy = uniform(1, 1.5) t = (dy * (vylast - legvy) + ymax * legvy) / (legvy * (vylast - vy)) - if t < dy / legvy: + if t < _pydiv(dy, legvy): t = ymax / (legvy - vy) y = yc0 + dy + 10 sq.append(ship.MineShip((x - t * vx, y - t * vy, 0), (vx, vy), plevel)) diff -ruN a/src/thing.py b/src/thing.py --- a/src/thing.py 2026-11-04 23:43:16.264664416 -0300 +++ b/src/thing.py 2026-11-04 23:47:43.100299421 -0300 @@ -1,6 +1,11 @@ from math import * from random import * -import state, settings +from . import state, settings + + +def _pydiv(a, b): + # Python 2 "/": integer division when both operands are ints + return a // b if isinstance(a, int) and isinstance(b, int) else a / b class Thing(object): @@ -73,7 +78,7 @@ pass def getshadows(self): - if self.casts and self.z > self.h / 2: + if self.casts and self.z > _pydiv(self.h, 2): yield self.x, self.y, self.r class Rock(Thing): @@ -84,7 +89,7 @@ w0, h0 = self.w, self.h + 0.7 w1, h1 = w0 - 0.2, h0 - 0.2 w2, h2 = w0 - 0.4, h0 - 0.4 - self.r = self.w / 2 + self.r = _pydiv(self.w, 2) self.layers = [ ["rock%s,%s" % (w2, h2), 0.2], ["rock%s,%s" % (w1, h1), 0.1], @@ -98,7 +103,7 @@ for h in objs: if not h.alive: continue - if h.z > self.h/2: + if h.z > _pydiv(self.h, 2): continue dx, dy = h.x - self.x, h.y - self.y if dx ** 2 + dy ** 2 < (self.r + h.r) ** 2: @@ -151,7 +156,7 @@ def causedamage(self): self.alive = False - import effect + from . import effect state.effects.append(effect.Splode((self.x, self.y, self.z))) def hitany(self, objs): @@ -163,7 +168,8 @@ r = 0.1 h = 0.2 layers = [["cannonball", 0]] - def __init__(self, obj, (dx, dy, dvx, dvy)): + def __init__(self, obj, xxx_todo_changeme): + (dx, dy, dvx, dvy) = xxx_todo_changeme Thing.__init__(self, (obj.x + dx, obj.y + dy, obj.z + 0.2)) self.vy = state.vyc + self.vy0 + dvy self.vx = (obj.vx / obj.vy * self.vy if obj.vy else 0) + dvx