An expanded Pong built with Python + Pygame. It supports SP/2P play, multiple maps (Classic, Ice Hockey, Dual/Coupled paddles, Gravity, Labyrinth), power‑ups and weapons (missiles, bombs, mines), bats, and a simple start menu. Includes a “dev vs play” workflow so you can keep a stable, playable copy while working on changes.
# 1) Create and activate a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
# 2) Install dependencies
pip install -r requirements.txt
# 3) Run
python -m pong # or: python -m pong --mode 2pIf you prefer a single command to set up and launch:
# Using the shell helper
bash run.sh # open menu
bash run.sh --mode 2p # start two‑player
# Or with Makefile (pass extra args via ARGS="...")
make run # open menu
make run ARGS="--mode 2p" # start two‑player- Menu:
1single‑player,2two‑player,Escquit - Gameplay:
- Left paddle:
W/A/S/D(full 2D on hockey/labyrinth) - Right paddle: arrows (in 2‑player)
- Boost: Left/Right Shift (or RT trigger on gamepad)
- Pause:
Space• Reset:R• Fullscreen:F• Quit:Esc
- Left paddle:
- Weapons (keyboard):
- Left:
Qmissile,Abomb,Zmine - Right (2P):
Pmissile,Lbomb,/mine
- Left:
- Gamepads (2P): first = Left, second = Right. Move with sticks. Face/shoulder buttons mapped analogously.
- Resolution defaults can be overridden with
--width/--height. - Heavy missiles (freeze shots, B on gamepad) freeze the enemy paddle briefly. Each player has a max of 10 freeze shots per match (configurable).
- Labyrinth map scales paddles to 1/3 size for corridor navigation.
python -m pong --mode 1p --fps 60 --width 1000 --height 600 --ai-speed 420 --win-score 11--mode:1p(default) or2p--fps: target frames per second (default 60)--width,--height: window size--ai-speed: maximum AI paddle speed in pixels/sec (default 420)--win-score: points needed to win the game (default 11)
This repo is set up to use two Git worktrees:
main(this repo/folder): development. You build and iterate here.play(a sibling folder): stable playable copy that you or others can launch while you keep coding.
Why: you can “cut” a playable build at any commit without disturbing your dev tree, and anyone can run the game from that copy while you continue making changes.
From the repo root:
# Create the play branch + worktree at ../pong-game-play
bash scripts/setup_play.shThis will create a new folder next to your repo (default: ../pong-game-play) checked out at branch play.
- Develop in this repo (branch
mainor feature branches). - Cut a new playable build when ready:
# Advance `play` to the latest commit
bash scripts/cut_play.sh # or: bash scripts/cut_play.sh <commit-or-tag>- Run the playable build (from anywhere):
bash scripts/run_play.sh # or: make playMakefile shortcuts:
make setup-play # same as scripts/setup_play.sh
make cut-play # REF=<ref> to pick a specific commit/tag
make play # run from the play worktreeNotes:
- Do not edit files directly in the
playworktree — treat it as read‑only runtime output of theplaybranch. scripts/cut_play.shsimply force‑movesplayto a ref and resets the worktree to match.
This repository includes a minimal CI that runs on pushes to main/play and on PRs to main:
- Installs Python and
pygame, performs a syntax check (compileall), and runs a headless smoke test (scripts/ci_smoke.py) using SDL’s dummy video/audio drivers. This verifies that the game at least initializes, updates, and draws a few frames in a consistent environment.
Badge at the top of this README reflects the current CI status.
Two common options for creating a GitHub repo and pushing your code:
# Install and login once (if not already)
gh auth login
# From the repo root, create a public repo named "pong-game" and push
gh repo create <your-user-or-org>/pong-game --public --source=. --remote=origin --push
# Push the play branch too
git push -u origin play-
Create a new Public repository on GitHub (no README/license) named
pong-game. -
Add the remote and push from your local repo:
git remote add origin https://github.com/<your-user-or-org>/pong-game.git
git push -u origin main
git push -u origin playNow your game is public and both main and play are available. Collaborators can clone and run make setup-play && make play to get a local playable copy.
Add a short description and topics to improve discoverability:
- GitHub UI → About → “Edit” → set Description and Topics (e.g.,
pygame,game,pong). - Or via CLI:
gh repo edit --description "Pygame Pong with maps, weapons, and dual worktree workflow" \
--add-topic pygame --add-topic game --add-topic pongProtecting main ensures that only reviewed and CI‑passing changes land in your default branch (the one most users browse and base work from). It’s optional, but useful if others will contribute.
Why protect main:
- Prevents accidental force‑pushes and direct commits that bypass review.
- Requires PRs to pass CI before merging, keeping
mainin a runnable state. - Encourages feature branches and cleaner history.
Recommended rules for main:
- Require pull request reviews (1 approval is usually enough for small projects).
- Require status checks to pass (enable the “CI” workflow as a required check).
- Disallow force pushes and deletions.
Suggested policy for play:
- Keep as a fast‑forward only branch updated by maintainers via
scripts/cut_play.shafter merges tomain. You can leave it unprotected, or protect it from direct pushes if multiple maintainers exist.
How to enable (GitHub UI):
- Settings → Branches → Branch protection rules → “Add rule”.
- Branch name pattern:
main. - Check “Require a pull request before merging” and “Require status checks to pass”.
- Select the “CI” check under required status checks, save.
CLI alternative (using gh):
# Require 1 review and passing checks on main (example using GitHub API)
gh api \
-X PUT \
-H "Accept: application/vnd.github+json" \
"/repos/${GITHUB_USER:-laroccamartin}/pong-game/branches/main/protection" \
-f required_status_checks.strict=true \
-f enforce_admins=true \
-F required_status_checks.contexts[]='CI' \
-F required_pull_request_reviews.required_approving_review_count=1 \
-F restrictions= Replace the owner/repo as needed. You’ll need sufficient repo permissions for the API call to succeed.
- Branch off
main(e.g.,feature/labyrinth-ai), open a PR, and after merge cut a new playable build viacut_play.sh. - Keep changes focused; update docs when behavior or setup changes.
- Consider enabling branch protection on
main(above) so CI enforces a basic health check before merges.
See LICENSE.