CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pysdl2

Pure Python wrapper around SDL2 libraries for cross-platform multimedia development

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

sprites-animation.mddocs/

Sprite and Animation System

High-level sprite management, animation, and rendering systems for 2D games and applications. The PySDL2 extension module provides object-oriented sprite classes and efficient batch rendering systems.

Capabilities

Sprite Classes

Core sprite classes for representing game objects and visual elements.

class Sprite:
    """
    Base sprite class for 2D game objects.
    
    Attributes:
    - x: horizontal position
    - y: vertical position  
    - size: (width, height) tuple
    """
    
    def __init__(self, x: int = 0, y: int = 0):
        """
        Create sprite at position.
        
        Parameters:
        - x: initial X coordinate
        - y: initial Y coordinate
        """
    
    @property
    def position(self) -> tuple[int, int]:
        """Get sprite position as (x, y) tuple."""
    
    @position.setter
    def position(self, value: tuple[int, int]) -> None:
        """Set sprite position from (x, y) tuple."""
    
    @property
    def size(self) -> tuple[int, int]:
        """Get sprite size as (width, height) tuple."""

class SoftwareSprite(Sprite):
    """
    Software-rendered sprite using SDL surfaces.
    
    Uses CPU-based blitting for rendering. Best for applications with
    few sprites or when hardware acceleration is unavailable.
    """
    
    def __init__(self, surface: SDL_Surface, free: bool = False, x: int = 0, y: int = 0):
        """
        Create software sprite from surface.
        
        Parameters:
        - surface: SDL_Surface containing sprite image
        - free: whether to free surface when sprite is destroyed
        - x, y: initial position
        """

class TextureSprite(Sprite):
    """
    Hardware-accelerated sprite using SDL textures.
    
    Uses GPU-based rendering for better performance. Requires
    hardware-accelerated renderer.
    """
    
    def __init__(self, texture: SDL_Texture, x: int = 0, y: int = 0):
        """
        Create texture sprite from texture.
        
        Parameters:
        - texture: SDL_Texture containing sprite image
        - x, y: initial position
        """

Sprite Factory

Factory class for creating sprites from various sources.

class SpriteFactory:
    """Factory for creating sprites from images and other sources."""
    
    def __init__(self, sprite_type: int = TEXTURE, renderer: Renderer = None, 
                 fontmanager: FontManager = None):
        """
        Create sprite factory.
        
        Parameters:
        - sprite_type: TEXTURE for TextureSprite, SOFTWARE for SoftwareSprite
        - renderer: Renderer for texture sprites (required for TEXTURE type)
        - fontmanager: FontManager for text sprites
        """
    
    def from_image(self, fname: str) -> Sprite:
        """
        Create sprite from image file.
        
        Parameters:
        - fname: path to image file
        
        Returns:
        Sprite object loaded from image
        """
    
    def from_surface(self, surface: SDL_Surface, free: bool = False) -> Sprite:
        """
        Create sprite from SDL surface.
        
        Parameters:
        - surface: SDL_Surface to create sprite from
        - free: whether to free surface when sprite is destroyed
        
        Returns:
        Sprite object created from surface
        """
    
    def from_color(self, color: tuple[int, int, int, int], size: tuple[int, int]) -> Sprite:
        """
        Create solid color sprite.
        
        Parameters:
        - color: RGBA color tuple (0-255 each component)
        - size: (width, height) sprite dimensions
        
        Returns:
        Sprite filled with solid color
        """
    
    def from_text(self, text: str, font: FontTTF = None, size: int = 12, 
                  color: tuple[int, int, int] = (255, 255, 255)) -> Sprite:
        """
        Create text sprite.
        
        Parameters:
        - text: text string to render
        - font: font to use (None for default)
        - size: font size in points
        - color: RGB text color
        
        Returns:
        Sprite containing rendered text
        """
    
    def create_texture_sprite(self, renderer: Renderer, size: tuple[int, int]) -> TextureSprite:
        """
        Create empty texture sprite for custom drawing.
        
        Parameters:
        - renderer: renderer to create texture for
        - size: (width, height) texture dimensions
        
        Returns:
        Empty TextureSprite that can be drawn to
        """

Sprite Factory Constants

TEXTURE: int = 1    # Create TextureSprite objects
SOFTWARE: int = 2   # Create SoftwareSprite objects

Sprite Rendering Systems

Efficient batch rendering systems for sprites.

class SpriteRenderSystem:
    """Base class for sprite rendering systems."""
    
    def render(self, sprites: list[Sprite]) -> None:
        """
        Render list of sprites.
        
        Parameters:
        - sprites: list of Sprite objects to render
        """

class SoftwareSpriteRenderSystem(SpriteRenderSystem):
    """Software-based sprite rendering system using surface blitting."""
    
    def __init__(self, window: Window):
        """
        Create software sprite renderer.
        
        Parameters:
        - window: Window to render sprites to
        """
    
    def render(self, sprites: list[Sprite]) -> None:
        """Render sprites using CPU blitting."""

class TextureSpriteRenderSystem(SpriteRenderSystem):
    """Hardware-accelerated sprite rendering system using textures."""
    
    def __init__(self, renderer: Renderer):
        """
        Create texture sprite renderer.
        
        Parameters:
        - renderer: Renderer to use for sprite rendering
        """
    
    def render(self, sprites: list[Sprite]) -> None:
        """Render sprites using GPU acceleration."""
    
    def render_sprite(self, sprite: TextureSprite, x: int = None, y: int = None, 
                     area: SDL_Rect = None) -> None:
        """
        Render single sprite.
        
        Parameters:
        - sprite: TextureSprite to render
        - x, y: override position (None to use sprite position)
        - area: source area to render (None for entire sprite)
        """

Entity-Component System

Framework for managing game entities with component-based architecture.

class Entity:
    """
    Game entity in entity-component system.
    
    Entities are containers for components that define behavior
    and properties.
    """
    
    def __init__(self, world: World = None, *args, **kwargs):
        """
        Create entity.
        
        Parameters:
        - world: World to add entity to
        - args, kwargs: additional arguments
        """

class World:
    """
    Container for entities and systems.
    
    Manages entity lifecycle and system processing.
    """
    
    def __init__(self):
        """Create empty world."""
    
    def add_system(self, system: System) -> None:
        """
        Add system to world.
        
        Parameters:
        - system: System to add
        """
    
    def remove_system(self, system: System) -> None:
        """
        Remove system from world.
        
        Parameters:
        - system: System to remove
        """
    
    def get_entities(self, component: type) -> list[Entity]:
        """
        Get entities that have specific component.
        
        Parameters:
        - component: component type to search for
        
        Returns:
        List of entities with the component
        """
    
    def process(self) -> None:
        """Process all systems in the world."""

class System:
    """
    Base class for entity-component systems.
    
    Systems process entities that have specific components.
    """
    
    def __init__(self):
        """Create system."""
    
    def process(self, world: World, components: dict) -> None:
        """
        Process entities with required components.
        
        Parameters:
        - world: World containing entities
        - components: dictionary of component types to process
        """

class Applicator:
    """
    Utility for applying functions to entities with specific components.
    
    Provides functional programming interface for entity processing.
    """
    
    def __init__(self, world: World):
        """
        Create applicator for world.
        
        Parameters:
        - world: World to operate on
        """
    
    def apply(self, func: callable, *component_types) -> None:
        """
        Apply function to entities with specified components.
        
        Parameters:
        - func: function to apply to matching entities
        - component_types: component types entities must have
        """

Particle System

Basic particle system for visual effects.

class ParticleEngine:
    """
    Basic particle system for effects.
    
    Note: This is from the particles module which may have encoding issues.
    Check source if this doesn't work as expected.
    """
    
    def __init__(self):
        """Create particle engine."""
    
    def process(self, world: World, componentsets: dict) -> None:
        """Process particle components."""

Usage Examples

Basic Sprite Creation and Rendering

import sdl2.ext

# Initialize SDL2 extensions
sdl2.ext.init()

# Create window and renderer
window = sdl2.ext.Window("Sprite Example", size=(800, 600))
window.show()
renderer = sdl2.ext.Renderer(window)

# Create sprite factory for texture sprites
factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=renderer)

# Create sprite from image file
player_sprite = factory.from_image("player.png")
player_sprite.position = (100, 100)

# Create colored sprite
enemy_sprite = factory.from_color((255, 0, 0, 255), (32, 32))  # Red 32x32 square
enemy_sprite.position = (200, 150)

# Create rendering system
render_system = sdl2.ext.TextureSpriteRenderSystem(renderer)

# Main game loop
running = True
while running:
    # Handle events
    events = sdl2.ext.get_events()
    for event in events:
        if event.type == sdl2.SDL_QUIT:
            running = False
        elif event.type == sdl2.SDL_KEYDOWN:
            # Move player sprite with arrow keys
            if event.key.keysym.sym == sdl2.SDLK_LEFT:
                player_sprite.x -= 5
            elif event.key.keysym.sym == sdl2.SDLK_RIGHT:
                player_sprite.x += 5
            elif event.key.keysym.sym == sdl2.SDLK_UP:
                player_sprite.y -= 5
            elif event.key.keysym.sym == sdl2.SDLK_DOWN:
                player_sprite.y += 5
    
    # Clear screen
    renderer.clear((0, 50, 100))
    
    # Render sprites
    render_system.render([player_sprite, enemy_sprite])
    
    # Present frame
    renderer.present()

sdl2.ext.quit()

Software Sprite Rendering

import sdl2.ext

# Initialize with software rendering
sdl2.ext.init()
window = sdl2.ext.Window("Software Sprites", size=(640, 480))
window.show()

# Create software sprite factory
factory = sdl2.ext.SpriteFactory(sdl2.ext.SOFTWARE)

# Create sprites from images
sprites = []
for i in range(5):
    sprite = factory.from_image(f"sprite_{i}.bmp")
    sprite.position = (i * 100, 100)
    sprites.append(sprite)

# Create software rendering system
render_system = sdl2.ext.SoftwareSpriteRenderSystem(window)

# Main loop
running = True
while running:
    events = sdl2.ext.get_events()
    for event in events:
        if event.type == sdl2.SDL_QUIT:
            running = False
    
    # Move sprites
    for sprite in sprites:
        sprite.y = 100 + 50 * math.sin((sprite.x + frame_count) * 0.05)
    
    # Render all sprites
    render_system.render(sprites)
    
    frame_count += 1

sdl2.ext.quit()

Entity-Component System Example

import sdl2.ext

# Define components
class Position:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

class Velocity:
    def __init__(self, vx=0, vy=0):
        self.vx = vx
        self.vy = vy

class Renderable:
    def __init__(self, sprite):
        self.sprite = sprite

# Define movement system
class MovementSystem(sdl2.ext.System):
    def __init__(self):
        super().__init__()
        self.componenttypes = (Position, Velocity)
    
    def process(self, world, componentsets):
        for entity in componentsets:
            position = entity[Position]
            velocity = entity[Velocity]
            
            position.x += velocity.vx
            position.y += velocity.vy
            
            # Wrap around screen edges
            if position.x < 0:
                position.x = 800
            elif position.x > 800:
                position.x = 0

# Initialize SDL2
sdl2.ext.init()
window = sdl2.ext.Window("ECS Example", size=(800, 600))
window.show()
renderer = sdl2.ext.Renderer(window)

# Create world and systems
world = sdl2.ext.World()
movement_system = MovementSystem()
render_system = sdl2.ext.TextureSpriteRenderSystem(renderer)

world.add_system(movement_system)

# Create sprite factory
factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=renderer)

# Create entities
for i in range(10):
    entity = sdl2.ext.Entity(world)
    
    # Add components
    entity.components[Position] = Position(i * 80, 200)
    entity.components[Velocity] = Velocity(random.randint(-3, 3), random.randint(-2, 2))
    
    sprite = factory.from_color((255, 255, 0, 255), (16, 16))
    entity.components[Renderable] = Renderable(sprite)

# Main loop
running = True
while running:
    events = sdl2.ext.get_events()
    for event in events:
        if event.type == sdl2.SDL_QUIT:
            running = False
    
    # Process systems
    world.process()
    
    # Render
    renderer.clear((0, 0, 0))
    
    # Get all entities with Position and Renderable components
    renderable_entities = world.get_entities((Position, Renderable))
    sprites_to_render = []
    
    for entity in renderable_entities:
        position = entity.components[Position]
        renderable = entity.components[Renderable]
        
        renderable.sprite.position = (position.x, position.y)
        sprites_to_render.append(renderable.sprite)
    
    render_system.render(sprites_to_render)
    renderer.present()

sdl2.ext.quit()

Sprite Animation Example

import sdl2.ext
import time

# Initialize SDL2
sdl2.ext.init()
window = sdl2.ext.Window("Sprite Animation", size=(800, 600))
window.show()
renderer = sdl2.ext.Renderer(window)

# Create sprite factory
factory = sdl2.ext.SpriteFactory(sdl2.ext.TEXTURE, renderer=renderer)

# Load animation frames
animation_frames = []
for i in range(8):  # Assuming 8 frame animation
    frame = factory.from_image(f"animation_frame_{i}.png")
    animation_frames.append(frame)

# Animation variables
current_frame = 0
frame_duration = 0.1  # 100ms per frame
last_frame_time = time.time()

# Create rendering system
render_system = sdl2.ext.TextureSpriteRenderSystem(renderer)

# Main loop
running = True
while running:
    current_time = time.time()
    
    events = sdl2.ext.get_events()
    for event in events:
        if event.type == sdl2.SDL_QUIT:
            running = False
    
    # Update animation
    if current_time - last_frame_time >= frame_duration:
        current_frame = (current_frame + 1) % len(animation_frames)
        last_frame_time = current_time
    
    # Position current frame
    current_sprite = animation_frames[current_frame]
    current_sprite.position = (350, 250)
    
    # Render
    renderer.clear((0, 0, 0))
    render_system.render([current_sprite])
    renderer.present()

sdl2.ext.quit()

Install with Tessl CLI

npx tessl i tessl/pypi-pysdl2

docs

audio.md

events-input.md

file-io.md

fonts-text.md

graphics-rendering.md

image-processing.md

index.md

joystick-input.md

sprites-animation.md

system-utils.md

timer.md

window-display.md

tile.json