pygamejr
A simple PyGame extension library for educational game development.
Table of Contents
- Overview
- Installation
- Quick Start
- Architecture
- API Reference — pygamejr
- API Reference — codomir
- Examples
- Project Structure
Overview
pygamejr is a thin wrapper around pygame-ce designed for teaching programming to beginners.
It provides two installable packages:
| Package | Description |
|---|---|
pygamejr |
Core engine: sprites, scenes, game loop |
codomir |
Quest/map layer: tile-based character movement on .tmx maps |
Installation
# Clone the repository
git clone https://github.com/benefitkids/pygamejr.git
cd pygamejr
# Install in editable mode
pip install -e .
Dependencies (installed automatically):
pygame-ce— community edition of pygamepytmx— loader for Tiled.tmxmap files
Quick Start
Minimal example
import pygamejr
bee = pygamejr.ImageSprite(pygamejr.resources.image.bee)
pygamejr.wait_quit()
Quest game (codomir)
from codomir import player, wait_quit
player.move_forward()
player.turn_right()
player.move_forward()
wait_quit()
Run the demos
python demo/1simple.py
python demo/scene.py
python demo/codomir/loop/map1.py
Architecture
pygamejr/
├── pygamejr/ # core engine
│ ├── base.py # pygame init, screen, game loop, scene switching
│ ├── scene.py # Scene — named sprite group container
│ ├── tilemap.py # TileMap — pytmx wrapper
│ ├── sprite/ # sprite classes
│ │ ├── base.py # BaseSprite
│ │ ├── image.py # ImageSprite
│ │ ├── text.py # TextSprite
│ │ ├── circle.py # CircleSprite
│ │ ├── rect.py # RectSprite
│ │ └── subtitles.py # SubtitlesSprite
│ └── resources/ # bundled images and path resolver
└── codomir/ # quest/map layer
├── quest.py # QuestScene, Player, Direction
├── maps/ # .tmx map path constants
└── resources/ # codomir-specific assets
Two-scene system
Every running game has two simultaneous scenes:
- Global scene — always rendered on top; holds HUD elements that survive level transitions.
Sprites added before the first
set_scene()call go here automatically. - Current scene — the active gameplay scene; switched with
set_scene(). Sprites added afterset_scene()go here automatically.
Import-time side effects
Importing pygamejr calls pygame.init() and creates the window immediately.
Importing codomir additionally loads the default map, builds the scene, and creates the player singleton.
API Reference — pygamejr
Game Loop
every_frame(frame_count=0, draw_sprites_rect=False)
Generator that drives the main game loop at 60 fps.
Yields dt (delta time in seconds) each frame.
Processes all pygame events and renders sprites automatically.
for dt in pygamejr.every_frame():
sprite.rect.x += 100 * dt # frame-rate-independent movement
| Parameter | Default | Description |
|---|---|---|
frame_count |
0 |
Stop after N frames (0 = infinite) |
draw_sprites_rect |
False |
Draw collision rectangles for debugging |
wait_quit()
Blocks until the user closes the window.
next_frame()
Renders exactly one frame (used internally by codomir for tile animations).
is_quit() -> bool
Returns True if a quit event has been received.
Scene Management
set_scene(scene: Scene)
Sets the active scene. Calls scene.init_scene() and clears sprite auto-registration target.
get_current_scene() -> Scene | None
Returns the current (gameplay) scene.
get_global_scene() -> Scene
Returns the global (HUD) scene, creating it on first call.
Scene
Container for named sprite groups.
scene = pygamejr.Scene()
| Method | Description |
|---|---|
add(sprite) |
Add sprite to the "default" layer |
remove(sprite) |
Remove sprite from the "default" layer |
add_sprite_list(name, group) |
Register a named LayeredUpdates group |
get_sprite_list(name) -> LayeredUpdates |
Retrieve a named group |
update(dt) |
Update all groups |
draw(draw_rect=False) |
Draw all groups; draw_rect=True shows rects |
init_scene() |
Called when scene becomes active (override this) |
Scene.from_tilemap(tilemap) |
Class method — build scene from a TileMap |
Sprites
All sprites auto-register to the current (or global) scene on creation.
Pass scene= to override registration.
BaseSprite
pygamejr.sprite.BaseSprite(sprite_angle=0, is_visible=True, scene=None)
| Property/Method | Description |
|---|---|
rect |
pygame.Rect — position and size |
is_visible |
Show/hide sprite |
move_forward(distance=1.0) |
Move in direction of sprite_angle |
rotate(angle) |
Rotate by angle degrees |
ImageSprite
pygamejr.ImageSprite(filename=None, image=None, crop_alpha=True,
sprite_angle=0, scene=None)
Loads an image from a file path or pygame.Surface.
Automatically crops transparent borders and creates a pixel-perfect mask for collision.
bee = pygamejr.ImageSprite(pygamejr.resources.image.bee)
bee.rect.center = (400, 300)
| Parameter | Description |
|---|---|
filename |
Path to image file |
image |
pygame.Surface to use directly |
crop_alpha |
Crop transparent border (default True) |
| Method | Description |
|---|---|
rotate(angle) |
Rotate image and update collision mask |
turn_left(angle=1) |
Rotate counter-clockwise |
turn_right(angle=1) |
Rotate clockwise |
TextSprite
pygamejr.TextSprite(text='', size=32, color=(255, 255, 255),
font_name=None, sprite_angle=0, scene=None)
Renders text as a sprite. Changing the .text property re-renders automatically.
label = pygamejr.TextSprite("Score: 0", size=24, color=(255, 255, 0))
label.text = "Score: 10" # updates automatically
CircleSprite
pygamejr.CircleSprite(color="red", radius=50, sprite_angle=0, scene=None)
RectSprite
pygamejr.RectSprite(color="red", width=50, height=50,
x=0, y=0, sprite_angle=0, scene=None)
SubtitlesSprite
Scrolling text overlay — cycles through a list of strings every 3 seconds, then hides.
pygamejr.sprite.SubtitlesSprite(
text_list=["Hello!", "Welcome to the game."],
size=28, color=(255, 255, 255)
)
Resources
pygamejr.resources.image
Module of named constants for built-in images.
pygamejr.resources.image.bee
pygamejr.resources.image.coin_gold
pygamejr.resources.image.player_ship1_orange
pygamejr.resources.image.meteor_grey_big1
Categories:
| Category | Examples |
|---|---|
| Creatures | bee, fly, frog, ladybug, mouse, worm_green |
| Enemies | slime_blue, slime_green, saw, fish_swim1 |
| Items | coin_gold, gem_blue, key_gold, star_gold |
| Space shooter | player_ship1_orange, laser_blue01, meteor_grey_big1 |
| UI | flag_green1, ladder_mid, lives |
TileMap
tilemap = pygamejr.TileMap("path/to/map.tmx")
sprites = tilemap.get_layer_sprites("Ground")
| Method | Description |
|---|---|
get_layer_sprites(layer_name) |
Returns list[ImageSprite] for named tile layer |
tmxdata |
Raw pytmx data object |
API Reference — codomir
Player
The player singleton is created automatically on import codomir.
from codomir import player, wait_quit
| Method | Description |
|---|---|
player.move_forward() |
Move one tile (64 px) in the current direction with animation |
player.turn_left() |
Turn 90° counter-clockwise |
player.turn_right() |
Turn 90° clockwise |
The player detects:
- Walls — blocks movement, plays shake animation
- Win tile — plays win animation and stops
set_map(map_path) / init(map_path)
Load a new .tmx map and reposition the player at the spawn tile.
from codomir import set_map, maps
set_map(maps.linear.map2)
Maps
from codomir import maps
maps.linear.map1 # linear map 1
maps.linear.map2 # linear map 2
# ...
maps.loop.map_loop1 # loop map 1
maps.pirates.linear.map1
Map collections:
| Module | Description |
|---|---|
maps.linear |
Straight-path maps (map1 – map6) |
maps.loop |
Loop maps (map_loop1 – map_loop6) |
maps.nested_loops |
Nested loop maps |
maps.pirates.linear |
Pirate-themed maps |
Examples
Simple animation
import pygamejr
bee = pygamejr.ImageSprite(pygamejr.resources.image.bee)
bee.rect.center = (400, 300)
for dt in pygamejr.every_frame():
bee.move_forward(150 * dt)
Multi-scene game with HUD
import pygamejr
import pygame
# --- Global scene (HUD, always visible) ---
score_label = pygamejr.TextSprite("Score: 0", size=24)
score_label.rect.topleft = (10, 10)
# --- Level 1 ---
level1 = pygamejr.Scene()
pygamejr.set_scene(level1)
enemy = pygamejr.ImageSprite(pygamejr.resources.image.bee)
enemy.rect.center = (400, 300)
score = 0
for dt in pygamejr.every_frame():
enemy.move_forward(100 * dt)
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
score += 1
score_label.text = f"Score: {score}"
Quest game with custom map
from codomir import player, wait_quit, set_map, maps
set_map(maps.linear.map3)
player.move_forward()
player.move_forward()
player.turn_right()
player.move_forward()
wait_quit()
Tile-based world from .tmx file
import pygamejr
tilemap = pygamejr.TileMap("levels/world.tmx")
scene = pygamejr.Scene.from_tilemap(tilemap)
pygamejr.set_scene(scene)
pygamejr.wait_quit()
Project Structure
pygamejr/
├── src/
│ ├── pygamejr/
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── scene.py
│ │ ├── tilemap.py
│ │ ├── sprite/
│ │ │ ├── base.py
│ │ │ ├── image.py
│ │ │ ├── text.py
│ │ │ ├── circle.py
│ │ │ ├── rect.py
│ │ │ └── subtitles.py
│ │ ├── resources/
│ │ │ ├── image.py
│ │ │ └── resolve_path.py
│ │ └── utils/
│ │ └── screen_size.py
│ └── codomir/
│ ├── __init__.py
│ ├── quest.py
│ ├── maps/
│ │ ├── linear.py
│ │ ├── loop.py
│ │ ├── nested_loops.py
│ │ └── pirates/
│ └── resources/
├── demo/
│ ├── 1simple.py
│ ├── scene.py
│ ├── space_invaders/
│ └── codomir/
├── pyproject.toml
└── README.md
Window Configuration
Control window size with environment variables before importing pygamejr:
PYGAMEJR_WINDOW_WIDTH=1024 PYGAMEJR_WINDOW_HEIGHT=768 python my_game.py
License
MIT © Alexander Mironov
Metadata
Release files for pygamejr 0.0.26
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pygamejr-0.0.26.tar.gz | 1.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pygamejr-0.0.26-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.8 MB
Release files / pygamejr-0.0.26.tar.gz
| Download URL | pygamejr-0.0.26.tar.gz |
|---|---|
| Size | 1.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a5b608d08a478e5c3d6d67f808d4274e5b8292eb9412bf74bd0dd87064556b62
|
|
BLAKE2b-256 checksum How to use checksums |
3b10c01a613f60c9727495dbba9294c23d99a969fc3ef448af861c7caeb0ca3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / pygamejr-0.0.26-py3-none-any.whl
| Download URL | pygamejr-0.0.26-py3-none-any.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8c2388ea500557633f104a825f937a0cbf38a7b837072c92b3bd82bab73377f7
|
|
BLAKE2b-256 checksum How to use checksums |
27e4b73cf1be817e9c65adfa730a0f21ef04ef15c962d64ed412feae0ff80ec7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|