pygameP
Pygame Plus — An advanced extension framework for Pygame, providing GLSL shader effects, performance optimization tools, JSON scene management, a simple physics engine, and extended input device support.
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 |
| physics | Simple rigid-body physics (gravity, collision, raycasting) |
| input | Unified input for keyboard, mouse, gamepad, and multi-touch |
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 Objector Coder, a visual scene editor. The pygameP library only loads and runs scenes. Download: https://tomlct2015.github.io/Objector-Coder/#download
{
"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
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
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()
License
MIT License
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 pygamep-0.0.2.tar.gz.
File metadata
- Download URL: pygamep-0.0.2.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a522f0e8d0a5c933163926ed707dca0d1287bd081ff47d752998a6eca9c9f36
|
|
| MD5 |
6ab9431af3f53a2f7ca047de3f41d766
|
|
| BLAKE2b-256 |
da3f5ffddfa973ed8525ed3194f9d1386549430789bc6c27a85ccb5f49f19ff6
|
File details
Details for the file pygamep-0.0.2-py3-none-any.whl.
File metadata
- Download URL: pygamep-0.0.2-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4480f0a8544a5d73e07f61584d661bcb0966cc6242377e36eac37caa19ff3fe8
|
|
| MD5 |
49d3421863c2448d9e7b8b55ae26c76f
|
|
| BLAKE2b-256 |
e6fd9004b492f7260d6d2f429fd7ad8d237dc4953e1dd505e95641b24905ffb9
|