pygameP
Pygame Plus — A comprehensive game development framework for Pygame with 44 modules: GLSL shaders, physics, scene management, lighting, dialogue, AI behavior trees, inventory, quests, achievements, CLI tools, and more.
Installation
pip install pygameP
Dependencies are installed automatically:
pygame >= 2.0.0PyOpenGL >= 3.1.0(for shader support)
Features
| Module | Description |
|---|---|
| shaders | GLSL shader system + built-in effects (grayscale, blur, invert, brightness, pulse, wave) |
| performance | Object pool, spatial hash, FPS monitor, batch renderer |
| scene | .pgstage JSON scene files with multi-scene switching and script bindings |
| physics | Simple rigid-body physics (gravity, collision, raycasting) |
| input | Unified input for keyboard, mouse, gamepad, and multi-touch |
| camera | 2D camera with smooth follow, screen shake, zoom, and bounds |
| audio | Audio manager with BGM fade, SFX pooling, and volume control |
| audio_fx | Audio effects (reverb, echo, pitch shift) + 2D positional audio |
| animation | SpriteSheet, Animation, AnimationController |
| particles | Particle emitters, lifecycle, color gradients |
| tween | 22+ easing functions, delay, callbacks |
| sprites | SpriteGroup batch update/draw, collision detection |
| lighting | 2D lighting with raycasted shadows, shadow-bleed, soft edges, distance falloff |
| dialogue | Branching dialogue trees, typewriter effect, choices |
| behaviortree | AI behavior trees (Selector, Sequence, Action, Condition, decorators) |
| statemachine | Finite state machine for game states and AI |
| events | Publish/subscribe event bus |
| pathfinding | A* pathfinding with grid maps |
| tilemap | Orthographic + isometric tilemap rendering |
| inventory | Item system with stacking, equipment, serialization |
| quest | Quest tracking, objectives, prerequisites, rewards |
| achievement | Achievement unlock tracking, progress, notifications |
| gui | Button, Slider, TextInput, ProgressBar, Label |
| gui_widgets | Dropdown, Checkbox, RadioButton, Panel, ImageWidget |
| scrollview | ScrollView, TabPanel, Tooltip, ContextMenu |
| layout | VBox, HBox, GridLayout auto-arrangement |
| dialog | MessageBox, ConfirmDialog, InputDialog |
| theme | GUI theme system (dark/light/retro built-in) |
| sprite_atlas | Texture atlas packing + 9-slice/9-patch UI rendering |
| render_target | Off-screen rendering, post-processing (Bloom, Vignette, ColorGrade) |
| noise | Perlin noise, cave/maze/terrain generation |
| i18n | Multi-language support with string formatting |
| parallax | Multi-layer parallax scrolling backgrounds |
| async_utils | AsyncTimer, LoopRunner for non-blocking tasks |
| assets | Cached asset loader (images, sounds, fonts, JSON) |
| save | JSON save slots + config manager |
| debug | Debug overlay with FPS, hitboxes, custom stats |
| console | In-game debug console + screenshot capture |
| virtual_joystick | On-screen touch/mouse joystick |
| tiled | Tiled Map Editor (.tmx) importer |
| script_engine | Script bindings: file path or inline code (start/update/event hooks) |
| webview | Embed HTML content into Pygame (WebSurface) |
| video | Play MP4 videos in Pygame (VideoPlayer) |
| cli | CLI project management (new, run, build, pgstage, validate, merge, diff, etc.) |
Quick Start
1. GLSL Shader Effects
Load shaders from .glsl files or inline code strings. Apply to the entire screen or individual sprites.
from pygameP import Shader, ShaderEffect, BuiltInEffects
# Use built-in effects
grayscale = BuiltInEffects.grayscale()
blur = BuiltInEffects.blur(radius=3.0)
invert = BuiltInEffects.invert()
pulse = BuiltInEffects.pulse(speed=2.0)
wave = BuiltInEffects.wave(amplitude=0.05, frequency=10.0)
# Apply to the entire screen
grayscale.apply(screen)
# Apply to a single sprite
pulse.apply(my_sprite)
# Custom GLSL code
my_shader = Shader(fragment_source="""
#version 330 core
in vec2 v_texcoord;
out vec4 frag_color;
uniform sampler2D u_texture;
uniform float u_time;
void main() {
vec4 c = texture(u_texture, v_texcoord);
frag_color = vec4(c.r, c.g * abs(sin(u_time)), c.b, c.a);
}
""")
# Load from file
custom = Shader(
vertex_file="assets/shaders/default.vert",
fragment_file="assets/shaders/plasma.frag"
)
2. Performance Optimization
from pygameP import ObjectPool, SpatialHash, FPSMonitor, BatchRenderer
# Object pool — reduce allocation overhead for bullets/particles
bullet_pool = ObjectPool(lambda: Bullet(), initial_size=200)
bullet = bullet_pool.acquire() # grab from pool
# ... use it ...
bullet_pool.release(bullet) # return to pool
# Spatial hash — fast collision detection
spatial = SpatialHash(cell_size=64)
spatial.insert(enemy, enemy.rect)
nearby = spatial.query(player.rect) # only check nearby objects
# FPS monitor + adaptive quality
fps_monitor = FPSMonitor(target_fps=60)
while running:
dt = fps_monitor.tick()
if fps_monitor.should_reduce_quality():
reduce_particle_count()
# Batch rendering — merge draw calls
batch = BatchRenderer(screen)
for sprite in sprites:
batch.blit(sprite.image, sprite.rect.topleft)
batch.render() # execute all at once
3. Scene Management (.pgstage)
.pgstage is pygameP's custom scene file format, based on JSON.
Scene Editor:
.pgstagefiles are created and managed by pgstage Editor, a visual scene editor. The pygameP library only loads and runs scenes. Online Editor: https://tomlct2015.github.io/pygameP/editor/pgstage-editor
{
"name": "ExampleLevel",
"width": 1600,
"height": 1200,
"background_color": [20, 25, 40],
"camera_x": 0,
"camera_y": 0,
"properties": {
"music": "assets/music/level1.ogg",
"difficulty": "normal"
},
"entities": [
{
"type": "Player",
"x": 100,
"y": 800,
"layer": 5,
"hp": 100,
"tag": "player"
},
{
"type": "Enemy",
"x": 500,
"y": 800,
"layer": 4,
"hp": 50,
"ai": "patrol"
}
]
}
Usage in Python:
from pygameP import Scene, SceneManager, SceneEntity
# Load a scene from .pgstage file
scene = Scene.load("levels/level1.pgstage")
# Multi-scene management (with transition)
manager = SceneManager()
manager.load("menu", "scenes/menu.pgstage")
manager.load("game", "levels/level1.pgstage")
manager.switch_to("game", transition=0.5)
# Game loop
while running:
dt = clock.tick(60) / 1000.0
manager.update(dt)
manager.draw(screen)
4. Simple Physics Engine
from pygameP import RigidBody, PhysicsWorld, BoxCollider, CircleCollider
# Create physics world
world = PhysicsWorld(gravity=980.0)
# Dynamic rigid body (affected by gravity)
player = RigidBody(x=100, y=0, mass=1.0, collider=BoxCollider(32, 64))
player.restitution = 0.3 # bounciness
player.friction = 0.2 # friction
world.add_body(player)
# Static rigid body (ground, platforms)
ground = RigidBody(x=0, y=600, mass=0, collider=BoxCollider(800, 40))
world.add_body(ground)
# Apply force or impulse
player.apply_force(500, 0) # continuous force
player.apply_impulse(0, -300) # jump (instant)
# Update each frame
world.update(dt)
# Collision callback
def on_hit(body1, body2):
print("Collision!")
world.on_collision = on_hit
# Raycasting
hit = world.raycast((100, 300), (1, 0), max_distance=500)
if hit:
body, distance, point = hit
print(f"Hit {body} at distance {distance}")
5. Extended Input Devices
from pygameP import InputManager
input_mgr = InputManager()
# Map actions to multiple input sources
input_mgr.map_action("jump", "keyboard", pygame.K_SPACE)
input_mgr.map_action("jump", "gamepad", (0, 0)) # gamepad 0, button 0
input_mgr.map_action("shoot", "mouse", 1) # left mouse button
input_mgr.map_action("move_right", "gamepad", (0, "axis_0"))
# Game loop
while running:
events = pygame.event.get()
input_mgr.update(events)
if input_mgr.is_action_just_pressed("jump"):
player.jump()
if input_mgr.is_action_pressed("move_right"):
player.move_right()
# Analog input (gamepad stick)
move_x = input_mgr.get_action_value("move_right")
# Direct gamepad access
pad = input_mgr.get_gamepad(0)
if pad:
left_stick = pad.get_left_stick()
pad.rumble(0.5, 0.5, 100) # vibration
# Touch input
if input_mgr.touch.is_touching():
pos = input_mgr.touch.get_touch_position()
Supported input devices:
- Keyboard — key press/release/just-pressed
- Mouse — position, relative motion, scroll wheel, button state
- Gamepad — buttons, stick axes, D-pad, rumble/vibration
- Touch — multi-touch, touch start/end/move
6. Async Timer & Loop Runner
Non-blocking scheduled tasks for game loops.
from pygameP import AsyncTimer, LoopRunner
timer = AsyncTimer()
# Infinite loop — run callback every N seconds
timer.loop(0.1, update_ai)
# One-shot — run once after delay
timer.after(3.0, spawn_boss)
# Repeating — run every N seconds (stoppable)
task = timer.every(1.0, save_checkpoint)
task.stop() # cancel later
# Per-frame loop runner
runner = LoopRunner()
runner.add("physics", update_physics)
runner.add("ai", update_ai)
# In game loop:
timer.update(dt)
runner.update(dt)
7. Asset Manager
Global resource loader with automatic caching.
from pygameP import AssetManager
assets = AssetManager("assets")
# Load (cached after first load)
img = assets.image("sprites/player.png")
snd = assets.sound("sfx/jump.ogg")
fnt = assets.font("fonts/arial.ttf", 24)
data = assets.json("data/level1.json")
# Preload all at startup
assets.preload_images(["bg.png", "player.png", "enemy.png"])
assets.preload_sounds(["jump.ogg", "hit.ogg"])
# Background music
assets.music("music/theme.ogg", fade_ms=1000)
assets.stop_music(fade_ms=500)
# Stats
print(assets.stats()) # {'images': 3, 'sounds': 2, ...}
# Cleanup
assets.unload("sprites/player.png")
assets.clear() # clear all caches
8. Save System & Config
JSON-based save slots and game configuration.
from pygameP import SaveManager, Config
# Save game
save = SaveManager("saves")
save.save("slot1", {"level": 5, "hp": 100, "items": ["sword", "shield"]})
data = save.load("slot1")
save.exists("slot1") # True
save.list_slots() # ["slot1"]
save.delete("slot1")
# Config with defaults
cfg = Config("settings.json", defaults={
"volume": 0.8,
"resolution": [1280, 720],
"fullscreen": False,
})
vol = cfg.get("volume") # 0.8
cfg.set("volume", 0.5)
cfg["fullscreen"] = True # bracket access
cfg.save() # write to disk
cfg.reset() # reset to defaults
9. Camera System
2D camera with smooth follow, screen shake, zoom, and world bounds.
from pygameP import Camera
cam = Camera(1280, 720, world_width=3200, world_height=1800)
# Smooth follow player
cam.follow(player.x, player.y, speed=5.0, dead_zone=20)
# Instant snap to position
cam.look_at(500, 300)
# Screen shake on hit
cam.shake(intensity=8, duration=0.3)
# Zoom
cam.zoom_to(1.5, speed=3.0)
# In game loop:
cam.update(dt)
offset = cam.offset # (dx, dy) to subtract from entity positions
# Coordinate conversion
sx, sy = cam.world_to_screen(world_x, world_y)
wx, wy = cam.screen_to_world(mouse_x, mouse_y)
# Visibility check
if cam.visible(entity.x, entity.y, 32, 32):
entity.draw(screen)
10. Audio Manager
BGM fade, SFX pooling, and volume control.
from pygameP import AudioManager
audio = AudioManager(sfx_channels=16)
# Background music with fade
audio.play_bgm("music/theme.ogg", fade_ms=1000)
audio.set_bgm_volume(0.7)
audio.stop_bgm(fade_ms=500)
audio.pause_bgm()
audio.resume_bgm()
# Sound effects (auto-cached)
audio.play_sfx("sfx/jump.ogg")
audio.play_sfx("sfx/explosion.ogg", volume=0.5)
# Volume groups
audio.set_master_volume(0.8) # affects everything
audio.set_sfx_volume(0.6) # affects SFX only
# Preload
audio.preload_sfx(["jump.ogg", "hit.ogg", "coin.ogg"])
11. GUI Widgets
Button, Slider, TextInput, ProgressBar, Label.
from pygameP import Button, Slider, TextInput, ProgressBar, Label
btn = Button(100, 200, 200, 50, "Start Game", callback=start_game)
slider = Slider(100, 300, 200, min_val=0.0, max_val=1.0, value=0.8)
text = TextInput(100, 400, 200, 40, placeholder="Enter name...")
bar = ProgressBar(100, 500, 200, 20, value=0.75)
label = Label(100, 550, "Score: 0", font_size=24)
# In game loop:
for event in pygame.event.get():
btn.handle_event(event)
slider.handle_event(event)
text.handle_event(event)
text.update(dt) # cursor blink
btn.draw(screen)
slider.draw(screen)
text.draw(screen)
bar.draw(screen)
label.draw(screen)
# Access values
print(slider.value) # 0.0 to 1.0
print(text.text) # typed string
bar.value = 0.9 # auto-clamped to 0.0-1.0
12. Debug Overlay
Press F1 to toggle. Shows FPS, entity count, hitboxes, and custom stats.
from pygameP import DebugOverlay
dbg = DebugOverlay()
dbg.show_hitboxes = True
dbg.show_fps = True
dbg.show_entity_count = True
dbg.hotkey = pygame.K_F1 # configurable
# In game loop:
dbg.handle_event(event)
dbg.update(dt, entity_count=len(entities), score=score, ammo=ammo)
dbg.draw(screen, entities) # draws hitboxes + overlay
# Custom stats
dbg.set_stat("health", player.hp)
dbg.set_stat("mode", "survival")
13. Tiled Map Import
Load Tiled Map Editor (.tmx) files.
from pygameP import TiledLoader
loader = TiledLoader()
tilemap = loader.load("levels/level1.tmx")
# Access layers
for layer in tilemap.layers:
print(layer.name, layer.width, layer.height)
# Get tile at position
tile_id = tilemap.get_tile("Ground", x=5, y=3)
# Access objects
for obj in tilemap.objects:
print(obj.name, obj.type, obj.x, obj.y)
# Find objects by type
enemies = tilemap.get_object_layer("Enemies").get_objects_by_type("Enemy")
spawn = tilemap.get_object_layer("Spawns").get_object_by_name("PlayerStart")
# Tileset info
for ts in tilemap.tilesets:
print(ts.name, ts.first_gid, ts.image_source)
# Coordinate conversion
px, py = tilemap.tile_to_pixel(5, 3)
tx, ty = tilemap.pixel_to_pixel(mouse_x, mouse_y)
# Check visibility
if tilemap.visible(entity.rect):
entity.draw(screen)
API Reference
Shader
Shader(vertex_source, fragment_source, vertex_file, fragment_file)— create shadershader.use()/shader.stop()— enable/disableshader.set_uniform(name, value)— set uniform (float, int, vec2, vec3, vec4)shader.apply_to_surface(surface)— apply to entire screenshader.apply_to_sprite(sprite)— apply to single sprite
BuiltInEffects
grayscale()— grayscale filterblur(radius)— blur effectinvert()— color inversionbrightness(amount)— brightness adjustmentpulse(speed)— pulsing glowwave(amplitude, frequency)— wave distortion
ObjectPool
acquire()— get object from poolrelease(obj)— return objectrelease_all()— return all objectsresize(n)— adjust pool size
SpatialHash
insert(obj, rect)— insert objectquery(rect)— query objects in areaquery_nearby(obj, rect)— query nearby (excludes self)remove(obj)/clear()
Scene / SceneManager
Scene.load(path)— load.pgstagefileSceneManager.load(name, path)— load and register sceneSceneManager.switch_to(name, transition)— switch scenes
PhysicsWorld
add_body(body)/remove_body(body)update(dt)— step physics (handles gravity and collisions)raycast(start, direction, max_distance)— ray cast query
InputManager
update(events)— update all input devicesis_action_pressed(action)— is action held downis_action_just_pressed(action)— was action just pressed this frameget_action_value(action)— get analog value (-1 to 1)map_action(action, device, binding)— map action to input
AsyncTimer
loop(interval, callback)— run callback every N seconds (infinite)every(interval, callback)— alias for loop()after(delay, callback)— run once after delayupdate(dt)— advance all taskscancel_all()— cancel all tasks
LoopRunner
add(name, callback)— register per-frame callbackremove(name)— remove callbackupdate(dt)— call all callbacks with dt
AssetManager
image(path)— load/cache imagesound(path)— load/cache soundfont(path, size)— load/cache fontjson(path)— load/cache JSON datamusic(path, fade_ms)— play BGMpreload_images(paths)— bulk preloadstats()— cache statisticsclear()— clear all caches
SaveManager
save(slot, data)— save to slotload(slot)— load from slotexists(slot)— check if slot existsdelete(slot)— delete slotlist_slots()— list all slots
Config
get(key, default)— get value with fallbackset(key, value)— set valuesave()— write to diskreset()— reset to defaultsconfig[key]— bracket access
Camera
follow(x, y, speed, dead_zone)— smooth followlook_at(x, y)— instant snapshake(intensity, duration)— screen shakezoom_to(value, speed)— smooth zoomupdate(dt)— update cameraoffset— (dx, dy) for renderingworld_to_screen(x, y)— coordinate conversionscreen_to_world(x, y)— reverse conversionvisible(rect)— visibility check
AudioManager
play_bgm(path, fade_ms)— play background musicstop_bgm(fade_ms)— stop BGM with fadeplay_sfx(path, volume)— play sound effectset_master_volume(v)— global volumeset_bgm_volume(v)— BGM volumeset_sfx_volume(v)— SFX volumepreload_sfx(paths)— bulk preload
GUI Widgets
Button(x, y, w, h, text, callback)— clickable buttonSlider(x, y, w, min, max, value)— horizontal sliderTextInput(x, y, w, h, placeholder)— text input fieldProgressBar(x, y, w, h, value)— progress barLabel(x, y, text, font_size)— static text- All widgets:
handle_event(event),update(dt),draw(surface)
DebugOverlay
handle_event(event)— toggle on F1update(dt, entity_count, **custom)— update statsdraw(surface, entities)— render overlay + hitboxesset_stat(key, value)— add custom stat
TiledLoader
load(path)— load .tmx file- Returns
TileMapwith:layers— list ofTileLayerobject_layers— list ofObjectLayertilesets— list ofTilesetget_tile(layer_name, x, y)— get tile IDtile_to_pixel(tx, ty)— coordinate conversion
Full Example
import pygame
from pygameP import (
SceneManager, Scene, SceneEntity,
PhysicsWorld, RigidBody, BoxCollider,
InputManager, FPSMonitor, BuiltInEffects
)
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
# Scene
manager = SceneManager()
game = Scene({"name": "Game", "width": 800, "height": 600,
"background_color": [30, 40, 60]})
manager.add("game", game)
manager.switch_to("game")
# Physics
world = PhysicsWorld(gravity=980.0)
player = RigidBody(400, 100, mass=1.0, collider=BoxCollider(32, 32))
world.add_body(player)
ground = RigidBody(0, 550, mass=0, collider=BoxCollider(800, 50))
world.add_body(ground)
# Input
input_mgr = InputManager()
input_mgr.map_action("jump", "keyboard", pygame.K_SPACE)
input_mgr.map_action("left", "keyboard", pygame.K_LEFT)
input_mgr.map_action("right", "keyboard", pygame.K_RIGHT)
# FPS monitor
fps = FPSMonitor(target_fps=60)
# Shader effect
effect = BuiltInEffects.pulse(speed=2.0)
running = True
while running:
dt = clock.tick(60) / 1000.0
fps.tick()
events = pygame.event.get()
input_mgr.update(events)
for event in events:
if event.type == pygame.QUIT:
running = False
# Input
if input_mgr.is_action_just_pressed("jump") and player.grounded:
player.apply_impulse(0, -500)
if input_mgr.is_action_pressed("left"):
player.apply_force(-300, 0)
if input_mgr.is_action_pressed("right"):
player.apply_force(300, 0)
# Update
world.update(dt)
manager.update(dt)
# Draw
manager.draw(screen)
pygame.draw.rect(screen, (255, 200, 100),
(player.x, player.y, 32, 32))
pygame.draw.rect(screen, (100, 100, 100),
(ground.x, ground.y, 800, 50))
pygame.display.flip()
pygame.quit()
New in v1.0.11
14. Lighting System (v1.0.17)
A full 2D lighting engine with raycasted visibility polygons, circular and rectangular shadow casters, and configurable visual effects.
Architecture — Shared Dark Cloth
All lights are composited into a single _light_pass surface per frame. Both render() and render_layer() reuse this surface, avoiding duplicate raycast computation.
from pygameP import Light2D, LightingSystem
lighting = LightingSystem(ambient=(20, 20, 40))
# Add shadow casters (rectangular and circular)
lighting.add_shadow_rect(pygame.Rect(100, 200, 300, 20))
lighting.add_shadow_circle(500, 400, 30)
# Create lights
torch = Light2D(x=400, y=300, radius=200, color=(255, 200, 100))
torch.flicker(speed=5.0, amount=0.15)
lighting.add(torch)
spot = Light2D(x=100, y=100, radius=300, angle=45, spread=30)
lighting.add(spot)
# Game loop
lighting.update(dt)
lighting.render(screen, scene_surface, camera_offset)
# Or per-layer rendering
lit_bg = lighting.render_layer((800, 600), bg_surface, 0, camera_offset)
lit_fg = lighting.render_layer((800, 600), fg_surface, 1, camera_offset)
Light2D — Point Light & Spotlight
| Parameter | Description |
|---|---|
x, y |
World position |
radius |
Maximum reach in pixels |
color |
(r, g, b) light colour |
intensity |
Brightness multiplier (0.0–1.0) |
angle |
Spotlight direction in degrees (None for omnidirectional) |
spread |
Half-angle of spotlight cone in degrees |
affect_layers |
Which layers this light illuminates (None = all) |
| Attribute | Default | Description |
|---|---|---|
enabled |
True |
Set False to disable without removing |
cast_shadow |
True |
Set False to skip shadow computation (faster) |
shadow_bleed |
20.0 |
Pixels to extend light behind occluders (0 = off) |
edge_softness |
0.0 |
Soft-edge width in pixels (0 = hard edge) |
distance_falloff |
0.0 |
0.0 = uniform, 1.0 = fully dark at edge |
# Point light (omnidirectional)
glow = Light2D(200, 300, radius=150, color=(200, 200, 255), intensity=0.5)
# Spotlight (directional cone)
flashlight = Light2D(
x=400, y=300, radius=700,
color=(255, 225, 145), intensity=1.0,
angle=0.0, spread=28.0)
# Dynamic properties
flashlight.x, flashlight.y = player.x, player.y
flashlight.angle = player.facing_degrees
flashlight.radius = 700
flashlight.color = (180, 210, 255) # change colour
Visual Effects
All three effects are per-light configurable and can also be set globally.
# Per-light
flashlight.shadow_bleed = 30 # light peeks behind walls
flashlight.edge_softness = 15 # soft transition at light boundary
flashlight.distance_falloff = 0.5 # darker at edges
# Global (affects ALL lights)
lighting.set_shadow_bleed(25)
lighting.set_edge_softness(10)
lighting.set_distance_falloff(0.3)
| Effect | Visual |
|---|---|
| Shadow Bleed | Light slightly extends behind occluders, revealing their silhouette |
| Edge Softness | Smooth glow transition at the light boundary instead of hard cut |
| Distance Falloff | Gradual darkening from centre to edge |
Raycasting Details
- 360° uniform rays (1° spacing) + vertex-aimed rays (±ε at each wall corner)
- Circle tangent rays for smooth shadow casting around circular obstacles
- Arc interpolation: consecutive circle-boundary hits are connected by interpolated arc points (≤ 12° threshold → arc, > 12° → straight line for wall boundaries)
- Polygon closes through the light source (no wedge-shaped gap at source)
- Screen culling: lights fully outside the viewport are skipped
Light source markers should be drawn after lighting.render(), directly onto the screen, otherwise they get darkened by the multiply blend.
15. Dialogue System
from pygameP import DialogueTree, DialogueBox
tree = DialogueTree()
tree.add_node("start", speaker="Elder", text="Welcome, hero!")
tree.add_node("quest", speaker="Elder", text="Will you help?")
tree.add_choice("start", "quest", "Yes!")
tree.add_choice("start", "decline", "No.")
tree.add_node("decline", speaker="Elder", text="Very well...")
box = DialogueBox(tree)
box.start("start")
# Game loop
box.update(dt)
box.handle_event(event)
box.draw(screen)
16. AI Behavior Tree
from pygameP import BehaviorTree, Selector, Sequence, Action, Condition
patrol = Action("patrol", lambda bt: bt.blackboard["move_patrol"]())
chase = Action("chase", lambda bt: bt.blackboard["move_chase"]())
attack = Action("attack", lambda bt: bt.blackboard["do_attack"]())
visible = Condition("visible?", lambda bt: bt.blackboard["can_see_player"]())
close = Condition("close?", lambda bt: bt.blackboard["dist"]() < 50)
root = Selector("root", [
Sequence("engage", [visible, Selector("combat", [
Sequence("fight", [close, attack]),
chase
])]),
patrol
])
tree = BehaviorTree(root)
tree.tick(dt)
17. Inventory System
from pygameP import Inventory, Item
inv = Inventory(capacity=20)
potion = Item("potion", "Health Potion", stackable=True, max_stack=10)
sword = Item("sword", "Iron Sword", value=100)
inv.register_item(potion)
inv.add(potion, quantity=5)
inv.add(sword)
inv.use_item(0, player)
inv.has("potion", 3) # True
18. Quest System
from pygameP import QuestManager, Quest, QuestObjective
qm = QuestManager()
quest = Quest("slay", "Slay the Dragon", "Defeat 3 dragons")
quest.add_objective(QuestObjective("kill", "Kill dragons", required=3))
quest.add_reward("gold", 500)
qm.add_quest(quest)
qm.accept("slay")
qm.progress("slay", "kill", amount=1)
19. Achievement System
from pygameP import AchievementManager, Achievement
am = AchievementManager()
am.add(Achievement("first_kill", "First Blood", "Defeat your first enemy"))
am.add(Achievement("explorer", "Explorer", "Visit all areas", progress_max=10))
am.unlock("first_kill")
am.progress("explorer", amount=1)
20. Theme System
from pygameP import ThemeManager, Theme, DARK_THEME, LIGHT_THEME, RETRO_THEME
ThemeManager.set_theme(DARK_THEME)
ThemeManager.switch("retro")
# Custom theme
custom = Theme("neon", {"accent": (0, 255, 200), "bg": (10, 10, 20)})
ThemeManager.register(custom)
ThemeManager.switch("neon")
21. ScrollView, TabPanel, Tooltip, ContextMenu
from pygameP import ScrollView, TabPanel, Tooltip, ContextMenu
scroll = ScrollView(x=50, y=50, width=300, height=400)
scroll.add_content(widget)
tabs = TabPanel(x=50, y=50, width=400, height=300)
tabs.add_tab("Settings", widgets)
tabs.add_tab("Items", item_widgets)
tooltip = Tooltip("Hover text")
tooltip.attach(widget.rect)
ctx = ContextMenu()
ctx.add_item("Copy", on_copy)
ctx.add_item("Delete", on_delete)
ctx.show(mouse_x, mouse_y)
22. SpriteAtlas & NineSlice
from pygameP import SpriteAtlas, NineSlice
atlas = SpriteAtlas("assets/atlas.png", tile_size=32)
frame = atlas.get_frame(0)
atlas.define_region("sword", 64, 0, 32, 32)
panel = NineSlice("assets/panel.png", border=12)
panel.draw(screen, pygame.Rect(50, 50, 300, 200))
23. RenderTarget & Post-Processing
from pygameP import RenderTarget, PostProcessChain, Bloom, Vignette
rt = RenderTarget(800, 600)
rt.begin()
# draw scene...
rt.end()
chain = PostProcessChain()
chain.add(Bloom(threshold=0.8, intensity=0.5))
chain.add(Vignette(intensity=0.3))
result = chain.process(rt.surface)
screen.blit(result, (0, 0))
24. In-Game Console
from pygameP import GameConsole, Screenshot
console = GameConsole()
console.register("spawn", lambda args: spawn(args[0]))
console.register("godmode", lambda args: setattr(player, 'invincible', True))
# Toggle with backtick
console.handle_event(event)
console.update(dt)
console.draw(screen)
Screenshot.capture(screen) # saves to screenshots/
25. Virtual Joystick
from pygameP import VirtualJoystick
joy = VirtualJoystick(x=120, y=480, radius=60)
joy.handle_event(event)
dx, dy = joy.get_direction() # -1.0 to 1.0
joy.draw(screen)
26. Audio Effects & Positional Audio
from pygameP import AudioFX, PositionalAudio
fx = AudioFX()
reverb_snd = fx.reverb(original, decay=0.5)
echo_snd = fx.echo(original, repeats=3, delay=0.3)
fast_snd = fx.pitch_shift(original, factor=1.5)
pos = PositionalAudio(listener_x=400, listener_y=300)
pos.add_source("torch", x=200, y=150, sound=snd, max_dist=300)
pos.update(player.x, player.y) # auto volume + stereo pan
27. Script Engine (File + Inline Code)
# In .pgstage JSON:
{
"script": {
"start": "scripts/init.py",
"update": {"code": "entity.x += 100 * dt"},
"event": {"file": "scripts/events.py"}
}
}
28. CLI Commands
pygameP new MyGame # Create project
pygameP run # Run game
pygameP build # Build exe
pygameP pgstage scene.pgstage # Open in editor
pygameP info # Project stats
pygameP validate # Validate .pgstage files
pygameP lint # Check script references
pygameP export # Export as zip
pygameP merge a.pgstage b.pgstage -o out.pgstage
pygameP diff a.pgstage b.pgstage
pygameP deps --install # Install missing deps
pygameP test # Run tests
pygameP clean # Clean build artifacts
pygameP serve # Dev server with hot reload
pygameP watch # Monitor file changes
License
MIT License
Release files for pygameP 1.0.17
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pygamep-1.0.17.tar.gz | 164.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pygamep-1.0.17-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 301.5 kB
Release files / pygamep-1.0.17.tar.gz
| Download URL | pygamep-1.0.17.tar.gz |
|---|---|
| Size | 164.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00178dd7fd66d7772dd83842c4e0acc815926aaea72fec2eee2798d03b570583
|
|
BLAKE2b-256 checksum How to use checksums |
0beac6e46e44b8d2c0be7e2f5ea3dee27e7242dd12b30586211b5e9f7a84331f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.8
|
Release files / pygamep-1.0.17-py3-none-any.whl
| Download URL | pygamep-1.0.17-py3-none-any.whl |
|---|---|
| Size | 137.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
12bc9f3822542b71bd4f6548def850b91280c1f5dafe5a6f670489772993353a
|
|
BLAKE2b-256 checksum How to use checksums |
962313d1e6460d222dac88eb1632aaf1558c10f5819978eb6c0ec54ed43c9a55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.8
|