Simple PyGame extension for education.
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pygamejr-0.0.25.tar.gz.
File metadata
- Download URL: pygamejr-0.0.25.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17f0159087cf018e1302972050754e7b8d0cb1363854cccecb016841ef5ccb56
|
|
| MD5 |
a4a064f72b4006c3fb006585dea4c87c
|
|
| BLAKE2b-256 |
3305871db813f2c12b7a4509f01e796117521eb7082a216d251c22be514b3d6f
|
File details
Details for the file pygamejr-0.0.25-py3-none-any.whl.
File metadata
- Download URL: pygamejr-0.0.25-py3-none-any.whl
- Upload date:
- Size: 1.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3baef93d9873dfbf9b0b86b0e88301c97d66c632e468e391a18064e72179a0ae
|
|
| MD5 |
0ba85aef513b346b6041ee511999a0ab
|
|
| BLAKE2b-256 |
9f4df7a9e175b77624aff6a221030c0d53e1a8c96325750a8009e6a4387eaad0
|