Skip to main content

pygameP

Pygame Plus — 一个面向 Pygame 的高级扩展框架,提供 GLSL 着色器特效、性能优化工具、JSON 场景管理、简单物理引擎和扩展输入设备支持。

安装

pip install pygameP

依赖项会自动安装:

  • pygame >= 2.0.0
  • PyOpenGL >= 3.1.0(用于着色器支持)

核心特性

模块 功能
shaders GLSL 着色器系统 + 内置特效(灰度/模糊/反转/亮度/脉冲/波浪)
performance 对象池、空间哈希、帧率监控、批处理渲染
scene .pgstage JSON 场景文件,支持多场景切换
physics 简单刚体物理(重力、碰撞、射线检测)
input 键盘、鼠标、手柄、多点触摸统一输入管理

快速开始

1. GLSL 着色器特效

支持从 .glsl 文件加载或从代码字符串创建着色器。可作用于整个屏幕或单个精灵。

from pygameP import Shader, ShaderEffect, BuiltInEffects

# 使用内置特效
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)

# 应用到整个屏幕
grayscale.apply(screen)

# 应用到单个精灵
pulse.apply(my_sprite)

# 自定义 GLSL 代码
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);
}
""")

# 从文件加载
custom = Shader(
    vertex_file="assets/shaders/default.vert",
    fragment_file="assets/shaders/plasma.frag"
)

2. 性能优化

from pygameP import ObjectPool, SpatialHash, FPSMonitor, BatchRenderer

# 对象池 - 减少子弹/粒子的创建开销
bullet_pool = ObjectPool(lambda: Bullet(), initial_size=200)
bullet = bullet_pool.acquire()  # 从池中获取
# ... 使用后 ...
bullet_pool.release(bullet)     # 归还

# 空间哈希 - 快速碰撞检测
spatial = SpatialHash(cell_size=64)
spatial.insert(enemy, enemy.rect)
nearby = spatial.query(player.rect)  # 只检测附近对象

# FPS 监控 + 自适应质量
fps_monitor = FPSMonitor(target_fps=60)
while running:
    dt = fps_monitor.tick()
    if fps_monitor.should_reduce_quality():
        reduce_particle_count()

# 批处理渲染 - 合并绘制调用
batch = BatchRenderer(screen)
for sprite in sprites:
    batch.blit(sprite.image, sprite.rect.topleft)
batch.render()  # 一次性执行

3. 场景管理(.pgstage)

.pgstage 是 pygameP 的自定义场景文件格式,基于 JSON。

场景编辑器下载: .pgstage 文件由 Objector Coder 可视化编辑器创建和管理,pygameP 库只负责加载和运行场景。 下载地址: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"
    }
  ]
}

Python 中使用:

from pygameP import Scene, SceneManager, SceneEntity

# 创建场景
scene = Scene("Level1", width=1600, height=1200)
scene.background_color = (20, 25, 40)
scene.add_entity(SceneEntity(100, 800, hp=100, tag="player"))

# 保存为 .pgstage 文件
scene.save("levels/level1.pgstage")

# 加载场景
loaded = Scene.load("levels/level1.pgstage")

# 多场景管理(带过渡效果)
manager = SceneManager()
manager.add_scene("menu", Scene("Menu"))
manager.add_scene("game", Scene.load("levels/level1.pgstage"))
manager.switch_to("game", transition_duration=0.5)

# 游戏主循环
while running:
    dt = clock.tick(60) / 1000.0
    manager.update(dt)
    manager.draw(screen)

4. 简单物理引擎

from pygameP import RigidBody, PhysicsWorld, BoxCollider, CircleCollider

# 创建物理世界
world = PhysicsWorld(gravity=980.0)

# 动态刚体(受重力影响)
player = RigidBody(x=100, y=0, mass=1.0, collider=BoxCollider(32, 64))
player.restitution = 0.3  # 弹性
player.friction = 0.2     # 摩擦
world.add_body(player)

# 静态刚体(地面、平台)
ground = RigidBody(x=0, y=600, mass=0, collider=BoxCollider(800, 40))
world.add_body(ground)

# 施加力或冲量
player.apply_force(500, 0)        # 持续力
player.apply_impulse(0, -300)     # 跳跃(瞬间)

# 每帧更新
world.update(dt)

# 碰撞回调
def on_hit(body1, body2):
    print("碰撞!")
world.on_collision = on_hit

# 射线检测
hit = world.raycast((100, 300), (1, 0), max_distance=500)
if hit:
    body, distance, point = hit
    print(f"命中 {body},距离 {distance}")

5. 扩展输入设备

from pygameP import InputManager

input_mgr = InputManager()

# 映射动作到多种输入
input_mgr.map_action("jump", "keyboard", pygame.K_SPACE)
input_mgr.map_action("jump", "gamepad", (0, 0))  # 手柄 0 的按钮 0

input_mgr.map_action("shoot", "mouse", 1)  # 鼠标左键
input_mgr.map_action("move_right", "gamepad", (0, "axis_0"))

# 游戏主循环
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()

    # 模拟输入(手柄摇杆)
    move_x = input_mgr.get_action_value("move_right")

    # 直接访问手柄
    pad = input_mgr.get_gamepad(0)
    if pad:
        left_stick = pad.get_left_stick()
        pad.rumble(0.5, 0.5, 100)  # 震动

    # 触摸输入
    if input_mgr.touch.is_touching():
        pos = input_mgr.touch.get_touch_position()

支持的输入设备:

  • 键盘 — 按键按下/释放/刚刚按下
  • 鼠标 — 位置、相对运动、滚轮、按钮状态
  • 手柄 — 按钮、摇杆轴、方向帽、震动(rumble)
  • 触摸 — 多点触控、触摸开始/结束/移动

API 参考

Shader

  • Shader(vertex_source, fragment_source, vertex_file, fragment_file) — 创建着色器
  • shader.use() / shader.stop() — 启用/停用
  • shader.set_uniform(name, value) — 设置 uniform(支持 float/int/vec2/vec3/vec4)
  • shader.apply_to_surface(surface) — 应用于整个屏幕
  • shader.apply_to_sprite(sprite) — 应用于单个精灵

BuiltInEffects(内置特效)

  • grayscale() — 灰度
  • blur(radius) — 模糊
  • invert() — 颜色反转
  • brightness(amount) — 亮度
  • pulse(speed) — 脉冲发光
  • wave(amplitude, frequency) — 波浪扭曲

ObjectPool

  • acquire() — 获取对象
  • release(obj) — 归还对象
  • release_all() — 归还所有
  • resize(n) — 调整池大小

SpatialHash

  • insert(obj, rect) — 插入对象
  • query(rect) — 查询区域内对象
  • query_nearby(obj, rect) — 查询附近(排除自己)
  • remove(obj) / clear()

Scene / SceneManager

  • scene.save(path) — 保存为 .pgstage
  • Scene.load(path) — 加载 .pgstage
  • manager.switch_to(name, transition_duration) — 切换场景

PhysicsWorld

  • add_body(body) / remove_body(body)
  • update(dt) — 更新物理(自动处理重力和碰撞)
  • raycast(start, direction, max_distance) — 射线检测

InputManager

  • update(events) — 更新所有输入设备
  • is_action_pressed(action) — 动作是否被按住
  • is_action_just_pressed(action) — 动作是否刚刚按下
  • get_action_value(action) — 获取模拟值(-1 到 1)
  • map_action(action, device, binding) — 映射动作

完整示例

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()

# 场景
manager = SceneManager()
game = Scene("Game", 800, 600)
game.background_color = (30, 40, 60)
manager.add_scene("game", game)
manager.switch_to("game")

# 物理
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_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 = FPSMonitor(target_fps=60)

# 着色器
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

    # 输入
    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)

    # 更新
    world.update(dt)
    manager.update(dt)

    # 绘制
    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()

许可证

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.1.tar.gz (30.9 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.1-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file pygamep-0.0.1.tar.gz.

File metadata

  • Download URL: pygamep-0.0.1.tar.gz
  • Upload date:
  • Size: 30.9 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.1.tar.gz
Algorithm Hash digest
SHA256 fda5991a7a6716a04f89cc8948efc24a5e2c6decb9e5c75b35033f83d53c77a6
MD5 32892288eaf4bc0896f2becc795cdefe
BLAKE2b-256 b9bea88daffbed10b7d4091be179f513ff518406789842bafb1d14c200ead64c

See more details on using hashes here.

File details

Details for the file pygamep-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: pygamep-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 24.7 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0e7aca1056ac51cf4f0baa5bd4870086244333200308a89da7653b197e7fd89b
MD5 b92770a48d3fd85532b017943a02d53b
BLAKE2b-256 0a2151ac07a023f7d6c7a0dd715d64086346cecb3deeb606fa09ce1d4101dc3f

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

0.0.2

2 files

This release

0.0.1 This release

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