"""Render screenshots of key game states (headless) so we can inspect art. Usage: python shots.py [outdir] """ import os import sys os.environ.setdefault("SDL_VIDEODRIVER", "dummy") os.environ.setdefault("SDL_AUDIODRIVER", "dummy") import pygame # noqa: E402 from game import Game # noqa: E402 def save(g, name, out): g.render() path = os.path.join(out, name + ".png") pygame.image.save(g.canvas, path) # also save an upscaled preview big = pygame.transform.scale(g.canvas, (CV_W * 2, CV_H * 2)) pygame.image.save(big, os.path.join(out, name + "_2x.png")) print("saved", path) from physics import CV_W, CV_H # noqa: E402 def main(): out = sys.argv[1] if len(sys.argv) > 1 else "shots" os.makedirs(out, exist_ok=True) g = Game() # ---- title ---- for _ in range(50): g.update() save(g, "1_title", out) # ---- serve hint ---- g.state = "play" g.new_game() for _ in range(140): # past the ball banner g.update() save(g, "2_serve", out) # ---- mid play, staged action ---- t = g.table # force a live ball drifting toward the bumpers t.reset_ball_in_cannon() g.pending = "live" t.ball_live = True t.ball.x, t.ball.y = 295, 75 t.ball.vx, t.ball.vy = -2.2, 3.1 for _ in range(80): g.keys["fire"] = False g.update() save(g, "3_play", out) # manually trigger some juice: bumper hit + combo + fever g.combo = 4 g.combo_t = 150 g.fever = 60 * 12 g.add_msg("+500", 180, 150, (255, 214, 92)) for st in t.stars: st["lit"] = True b = t.bumpers[0] b["squash"] = 4 b["face_t"] = 0.0 g.particles.append(dict(x=180, y=150, life=14, kind="ring", color=(255, 255, 255))) g.bubble = ["CANDY FEVER!", 90, "star"] save(g, "4_fever", out) # ---- drain overlay ---- g.pending = "drain_pause" g.pending_t = 40 save(g, "5_drain", out) # ---- game over ---- g.pending = "over_banner" g.pending_t = 1 g.lives = 0 g.update() for _ in range(80): g.update() save(g, "6_gameover", out) pygame.quit() if __name__ == "__main__": main()