🖼️ Section 06: Build the Game Shell and Rendering Loop
Section Summary
In this section, students create the first full Game class in game.py. They set up the Pygame window, clock, timer event, game objects, and rendering pipeline.
By the end of this section, students will have a working game shell that can open a window, draw the board/snake/food/UI, and follow the standard game loop structure.
✅ Checklist
- [ ] Create
game.py. - [ ] Add imports, type aliases, and the
Gameclass constants. - [ ] Implement
__init__with Pygame startup and timer setup. - [ ] Implement
reset()to create snake/food and initialize score/state. - [ ] Implement the loop methods:
run(),update(),handle_events(). - [ ] Add placeholder
step_snake()for next section logic. - [ ] Implement rendering helpers: grid, snake, food, UI, and overlay.
- [ ] Run
s06_test.pyto validate shell behavior.
Core Concepts
1. The Game Loop Pattern
Most Pygame projects follow this loop: 1. Handle events 2. Update game state 3. Draw the frame 4. Limit frame rate
This section builds that loop in run() so future gameplay logic has a stable structure.
2. Game as the Orchestrator Class
Game is the high-level coordinator. It owns the Pygame systems (screen, clock, font), game entities (snake, food), and state (playing, paused, gameover).
This is good OOP architecture: each object has a focused role, and Game manages collaboration between them.
3. Decoupling Render Speed from Snake Speed
self.clock.tick(S.FPS)controls how often frames are drawn.pg.time.set_timer(...)creates a custom event atS.SNAKE_TPS.
This separation means visuals can stay smooth while movement speed remains intentionally controlled.
4. State-Driven Behavior
The class uses string states:
- STATE_PLAYING
- STATE_PAUSED
- STATE_GAMEOVER
Even before full gameplay logic is added, state constants prepare clear, readable flow control.
5. Layered Rendering
draw() calls smaller methods in order:
- background
- grid
- food
- snake
- UI
- optional overlay
Breaking drawing into helper methods keeps code organized and easier to debug.
6. Placeholders as Intentional Scaffolding
update() and step_snake() are placeholders right now. This is intentional scaffolding: structure first, then behavior in the next section.
Code Students Will Type (game.py)
Type this code by hand so you understand how the game shell is assembled.
Detailed Code Review & Key Concepts
Initialization (__init__)
- Starts Pygame systems and creates display, clock, and font.
- Creates
snake_tick_eventtimer based onS.SNAKE_TPS. - Calls
reset()to build gameplay objects cleanly.
Lifecycle Methods
run()controls the loop order and frame limit.reset()centers a new snake, creates food from free cells, and restores score/state.update()is intentionally empty scaffolding for now.
Event Handling
handle_events()currently only handlesQUIT._quit_game()closes Pygame cleanly and exits.
This keeps shutdown behavior consistent and centralized.
Rendering Pipeline
draw()composes the frame using helper methods._draw_grid()paints cell lines._draw_snake()colors head/body differently._draw_food()draws a rounded pellet inset inside its tile._draw_ui()renders score text._draw_overlay()darkens screen and displays pause/gameover message.
This layered approach makes rendering readable and easy to expand.
Test File (s06_test.py)
Use this test file to check that the game shell initializes and renders correctly.
This test file validates the shell in practical slices:
- test_game_init_sets_core_objects() checks startup values and object creation.
- test_reset_restores_defaults() verifies reset state and centered snake start.
- test_draw_runs_in_playing_and_overlay_states() confirms draw path works across states.
- test_quit_event_triggers_system_exit() verifies quit events close the game flow properly.
Passing these tests means the game framework is ready for Section 07 gameplay logic.

