Cross-platform windowing and multimedia library for Python with OpenGL graphics, event handling, and audio/video playback
Automatic resource loading with path resolution, ZIP support, and caching.
import pyglet
# Set resource paths
pyglet.resource.path = ['assets', 'assets/images', 'assets/sounds']
pyglet.resource.reindex()
# Load resources (automatically cached)
image = pyglet.resource.image('player.png')
sound = pyglet.resource.media('jump.wav', streaming=False)
texture = pyglet.resource.texture('wall.png')
# Custom loader
loader = pyglet.resource.Loader(['data', 'data/textures'])
sprite_img = loader.image('sprite.png')# Module-level functions use default loader
def pyglet.resource.image(name, flip_x=False, flip_y=False, rotate=0) -> AbstractImage
def pyglet.resource.animation(name) -> Animation
def pyglet.resource.texture(name) -> Texture
def pyglet.resource.media(name, streaming=True) -> Source
def pyglet.resource.file(name, mode='rb') -> file
def pyglet.resource.location(name) -> Location
def pyglet.resource.add_font(name)
# Configure paths
pyglet.resource.path: list # Search paths
pyglet.resource.reindex() # Rebuild index after changing pathclass pyglet.resource.Loader:
"""Custom resource loader"""
__init__(path=None, script_home=None)
# Load methods
def image(name, flip_x=False, flip_y=False, rotate=0) -> AbstractImage
def animation(name) -> Animation
def texture(name) -> Texture
def media(name, streaming=True) -> Source
def file(name, mode='rb') -> file
def add_font(name)
# Shader loading
def shader(name, shader_type=None) -> Shader
# Location methods
def location(name) -> Location
def add_location(location: Location)
# Properties
_cached_images: dict # Image cache
_cached_textures: dict # Texture cache
_cached_animations: dict # Animation cacheclass pyglet.resource.Location:
"""Abstract resource location"""
class pyglet.resource.FileLocation:
"""Filesystem directory"""
__init__(path)
class pyglet.resource.ZIPLocation:
"""ZIP archive"""
__init__(zip_file, directory='')
class pyglet.resource.URLLocation:
"""Remote URL"""
__init__(base_url)
# Add custom locations
loader = pyglet.resource.Loader()
loader.add_location(pyglet.resource.FileLocation('assets'))
loader.add_location(pyglet.resource.ZIPLocation('data.zip'))import pyglet
# Setup paths (relative to script location)
pyglet.resource.path = ['assets']
pyglet.resource.reindex()
# Load and use
player_img = pyglet.resource.image('player.png')
sprite = pyglet.sprite.Sprite(player_img, x=100, y=100)
jump_sound = pyglet.resource.media('jump.wav', streaming=False)
jump_sound.play()# Directory structure:
# assets/
# images/
# player.png
# enemies/
# zombie.png
# sounds/
# jump.wav
# fonts/
# custom.ttf
pyglet.resource.path = [
'assets/images',
'assets/images/enemies',
'assets/sounds',
'assets/fonts'
]
pyglet.resource.reindex()
# Load from any registered path
player = pyglet.resource.image('player.png')
zombie = pyglet.resource.image('zombie.png')
jump = pyglet.resource.media('jump.wav', streaming=False)
# Add font
pyglet.resource.add_font('custom.ttf')
font = pyglet.font.load('Custom Font Name', 16)# Separate loaders for different asset types
ui_loader = pyglet.resource.Loader(['assets/ui'])
game_loader = pyglet.resource.Loader(['assets/game', 'assets/game/levels'])
# Load from specific loaders
button_img = ui_loader.image('button.png')
level_data = game_loader.file('level1.json')# Load from ZIP file
loader = pyglet.resource.Loader()
loader.add_location(pyglet.resource.ZIPLocation('assets.zip', 'images/'))
# Load as normal
sprite_img = loader.image('sprite.png') # Loads from assets.zip/images/sprite.pngloader = pyglet.resource.Loader(['shaders'])
# Auto-detect type from extension (.vert, .frag, etc.)
vert = loader.shader('basic.vert')
# Or specify type
frag = loader.shader('basic.frag', shader_type='fragment')
program = pyglet.graphics.shader.ShaderProgram(vert, frag)class ResourceManager:
"""Centralized resource management"""
def __init__(self):
pyglet.resource.path = ['assets/images', 'assets/sounds']
pyglet.resource.reindex()
# Preload common resources
self.images = {
'player': pyglet.resource.image('player.png'),
'enemy': pyglet.resource.image('enemy.png'),
'bullet': pyglet.resource.image('bullet.png'),
}
self.sounds = {
'jump': pyglet.resource.media('jump.wav', streaming=False),
'shoot': pyglet.resource.media('shoot.wav', streaming=False),
}
self.music = {
'menu': pyglet.resource.media('menu_music.mp3', streaming=True),
'game': pyglet.resource.media('game_music.mp3', streaming=True),
}
def get_image(self, name):
return self.images.get(name)
def get_sound(self, name):
return self.sounds.get(name)
def play_music(self, name):
music = self.music.get(name)
if music:
music.play()
# Usage
resources = ResourceManager()
player_sprite = pyglet.sprite.Sprite(resources.get_image('player'))
resources.get_sound('jump').play()class LoadingScreen:
def __init__(self, window):
self.window = window
self.label = pyglet.text.Label(
'Loading...',
x=window.width // 2,
y=window.height // 2,
anchor_x='center'
)
def load_resources(self):
"""Load all game resources"""
resources_to_load = [
('player.png', 'image'),
('enemy.png', 'image'),
('background.png', 'image'),
('music.mp3', 'media'),
]
loaded = {}
total = len(resources_to_load)
for i, (name, rtype) in enumerate(resources_to_load):
# Update progress
self.label.text = f'Loading... {i}/{total}'
self.window.dispatch_event('on_draw')
self.window.flip()
# Load resource
if rtype == 'image':
loaded[name] = pyglet.resource.image(name)
elif rtype == 'media':
loaded[name] = pyglet.resource.media(name)
return loadedResources are automatically cached after first load:
# First load: reads from disk
img1 = pyglet.resource.image('sprite.png')
# Second load: returns cached instance
img2 = pyglet.resource.image('sprite.png')
assert img1 is img2 # Same objectpyglet.resource.path before loadingstreaming=False for SFX, True for musicpyglet.resource.path and call reindex()/ even on WindowsInstall with Tessl CLI
npx tessl i tessl/pypi-pyglet@2.1.1