Skip to main content

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.0
  • PyOpenGL >= 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: .pgstage files 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 shader
  • shader.use() / shader.stop() — enable/disable
  • shader.set_uniform(name, value) — set uniform (float, int, vec2, vec3, vec4)
  • shader.apply_to_surface(surface) — apply to entire screen
  • shader.apply_to_sprite(sprite) — apply to single sprite

BuiltInEffects

  • grayscale() — grayscale filter
  • blur(radius) — blur effect
  • invert() — color inversion
  • brightness(amount) — brightness adjustment
  • pulse(speed) — pulsing glow
  • wave(amplitude, frequency) — wave distortion

ObjectPool

  • acquire() — get object from pool
  • release(obj) — return object
  • release_all() — return all objects
  • resize(n) — adjust pool size

SpatialHash

  • insert(obj, rect) — insert object
  • query(rect) — query objects in area
  • query_nearby(obj, rect) — query nearby (excludes self)
  • remove(obj) / clear()

Scene / SceneManager

  • Scene.load(path) — load .pgstage file
  • SceneManager.load(name, path) — load and register scene
  • SceneManager.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 devices
  • is_action_pressed(action) — is action held down
  • is_action_just_pressed(action) — was action just pressed this frame
  • get_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

pygamep-0.0.2.tar.gz (30.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pygamep-0.0.2-py3-none-any.whl (24.2 kB view details)

Uploaded Python 3

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

Hashes for pygamep-0.0.2.tar.gz
Algorithm Hash digest
SHA256 1a522f0e8d0a5c933163926ed707dca0d1287bd081ff47d752998a6eca9c9f36
MD5 6ab9431af3f53a2f7ca047de3f41d766
BLAKE2b-256 da3f5ffddfa973ed8525ed3194f9d1386549430789bc6c27a85ccb5f49f19ff6

See more details on using hashes here.

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

Hashes for pygamep-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4480f0a8544a5d73e07f61584d661bcb0966cc6242377e36eac37caa19ff3fe8
MD5 49d3421863c2448d9e7b8b55ae26c76f
BLAKE2b-256 e6fd9004b492f7260d6d2f429fd7ad8d237dc4953e1dd505e95641b24905ffb9

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.10

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

This release

0.0.2 This release

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page