Game Architecture
Scenes, Config & Clean Structure
A 200-line prototype and a 5,000-line real game need very different code organization. This module introduces scene/state management, centralized asset loading, config constants, logging and a project layout that scales.
Game States & Scene Management
A "scene" (or "state") is a self-contained screen — menu, gameplay, pause, game over — each handling its own events, updates and drawing. A SceneManager holds the current scene and swaps it out on request, so main.py never needs a giant if/elif chain.
class Scene:
def __init__(self, manager):
self.manager = manager
def handle_events(self, events): pass
def update(self, dt): pass
def draw(self, screen): pass
class SceneManager:
def __init__(self):
self.current = None
def go_to(self, scene):
self.current = scene
def handle_events(self, events):
self.current.handle_events(events)
def update(self, dt):
self.current.update(dt)
def draw(self, screen):
self.current.draw(screen)
class MenuScene(Scene):
def handle_events(self, events):
for e in events:
if e.type == pygame.KEYDOWN and e.key == pygame.K_RETURN:
self.manager.go_to(PlayScene(self.manager))
def draw(self, screen):
screen.fill((10, 14, 30))
# draw title + "Press Enter" prompt
Centralized Asset Loading
Rather than scattering pygame.image.load() calls across scene files, one module loads everything once at startup and every scene reads from the same shared dictionary — the exact pattern introduced in Module 4, now formalized project-wide.
class Assets:
images = {}
sounds = {}
@classmethod
def load_all(cls):
cls.images["player"] = pygame.image.load("assets/player.png").convert_alpha()
cls.images["enemy"] = pygame.image.load("assets/enemy.png").convert_alpha()
cls.sounds["jump"] = pygame.mixer.Sound("assets/jump.wav")
# ... every asset the game needs, loaded exactly once
Config Files & Constants
Magic numbers scattered through gameplay code (800, 1600, 0.7) become unreadable fast. A single config.py module holding named constants makes tuning game feel a one-line change instead of a hunt through every file.
SCREEN_WIDTH = 960
SCREEN_HEIGHT = 540
FPS = 60
GRAVITY = 1600
JUMP_FORCE = -650
PLAYER_SPEED = 300
WHITE = (255, 255, 255)
BG_COLOR = (5, 9, 26)
Logging, Debugging & Project Organization
logging module instead of scattered print() calls — it gives timestamps, severity levels (DEBUG/INFO/WARNING/ERROR), and can be silenced in a release build without deleting code.DEBUG = True flag in config.py, so debug visuals never ship in the final build.main.py, config.py, assets.py, scenes/, entities/, assets/images|sounds/ — separate code from content, and separate each concern into its own module.The Layered Architecture at a Glance
Stacking the pieces from this module top to bottom shows the dependency direction clearly: each layer only depends on the layers below it, never the other way around.