CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pygame-ce

Python Game Development library providing comprehensive multimedia functionality for creating games and interactive applications.

Pending
Overview
Eval results
Files

typing-support.mddocs/

Typing Support

Type hints and protocols for enhanced development experience with pygame-ce. Provides comprehensive type aliases, protocol classes, and type-safe interfaces for better IDE support and static type checking.

Capabilities

Core Type Aliases

Essential type aliases for common pygame data structures and parameters.

# Geometric types
RectLike = Union[Rect, FRect, SequenceLike[float], SequenceLike[Point], _HasRectAttribute]
Point = SequenceLike[float]
IntPoint = SequenceLike[int]
Coordinate = Union[Point, int, float]

# Color types
ColorLike = Union[Color, SequenceLike[int], str, int]
RGB = tuple[int, int, int]
RGBA = tuple[int, int, int, int]

# File and path types
FileLike = Union[str, bytes, PathLike[str], PathLike[bytes], IO[bytes], IO[str]]
PathLike = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]

# Surface types
SurfaceLike = Union[Surface, SequenceLike[SequenceLike[ColorLike]]]
BlendMode = int

# Vector types
Vector2Like = Union[Vector2, SequenceLike[float], tuple[float, float]]
Vector3Like = Union[Vector3, SequenceLike[float], tuple[float, float, float]]

# Font types
FontLike = Union[Font, str, bytes, PathLike]

# Event types
EventType = int

Protocol Classes

Protocol classes for duck typing and structural subtyping support.

class SequenceLike(Protocol[T_co]):
    """Protocol for sequence-like objects that support indexing and length."""
    
    def __getitem__(self, index: int) -> T_co: ...
    def __len__(self) -> int: ...

class _HasRectAttribute(Protocol):
    """Protocol for objects that have a rect attribute."""
    rect: RectLike

class _ColorCompatible(Protocol):
    """Protocol for color-compatible objects."""
    def __iter__(self) -> Iterator[int]: ...
    def __len__(self) -> int: ...

class _SupportsWrite(Protocol[T_contra]):
    """Protocol for file-like objects that support writing."""
    def write(self, data: T_contra) -> int: ...

class _SupportsRead(Protocol[T_co]):
    """Protocol for file-like objects that support reading."""
    def read(self, size: int = -1) -> T_co: ...

Surface Type Support

Type annotations for surface operations and transformations.

# Surface creation types
SurfaceFlags = int
PixelFormat = int
Depth = int
Masks = tuple[int, int, int, int]

# Surface transformation types
ScaleMode = Literal["nearest", "linear"]  
FlipMode = tuple[bool, bool]
RotationAngle = float

# Blending types
BlendModeType = Union[int, str]
SpecialFlags = int

Event Type Annotations

Comprehensive event type support for type-safe event handling.

# Event type unions
KeyEventType = Literal[KEYDOWN, KEYUP]
MouseEventType = Literal[MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION]
JoystickEventType = Literal[JOYAXISMOTION, JOYBUTTONDOWN, JOYBUTTONUP, JOYHATMOTION]
SystemEventType = Literal[QUIT, VIDEORESIZE, VIDEOEXPOSE]

# Event data types
class KeyEventDict(TypedDict):
    key: int
    mod: int
    unicode: str
    scancode: int

class MouseButtonEventDict(TypedDict):
    button: int
    pos: tuple[int, int]

class MouseMotionEventDict(TypedDict):
    pos: tuple[int, int]
    rel: tuple[int, int]
    buttons: tuple[bool, bool, bool]

class JoystickAxisEventDict(TypedDict):
    joy: int
    axis: int
    value: float

class JoystickButtonEventDict(TypedDict):
    joy: int
    button: int

class JoystickHatEventDict(TypedDict):
    joy: int
    hat: int
    value: tuple[int, int]

Function Type Signatures

Generic type signatures for common pygame function patterns.

# Callback types
DrawCallback = Callable[[Surface], None]
UpdateCallback = Callable[[float], None]
EventCallback = Callable[[Event], None]

# Iterator types
SpriteIterator = Iterator[Sprite]
RectIterator = Iterator[Rect]
EventIterator = Iterator[Event]

# Optional types
OptionalSurface = Optional[Surface]
OptionalRect = Optional[Rect]
OptionalColor = Optional[ColorLike]

# Generic collection types
SpriteCollection = Union[Group, Sequence[Sprite]]
RectCollection = Union[Sequence[Rect], Sequence[RectLike]]

Audio Type Support

Type annotations for audio and mixer functionality.

# Audio format types
AudioFormat = Literal[-16, -8, 8, 16]
AudioChannels = Literal[1, 2]
AudioFrequency = Literal[11025, 22050, 44100, 48000]

# Audio data types
AudioArray = Union[bytes, numpy.ndarray]
AudioBuffer = Union[str, bytes, IO[bytes]]

# Channel types
ChannelType = Union[Channel, int]
LoopCount = int
FadeTime = int

Math Type Support

Type annotations for mathematical operations and geometry.

# Angle types
Degrees = float
Radians = float
AngleUnit = Union[Degrees, Radians]

# Geometric types  
Distance = float
Scale = float
Ratio = float

# Transform types
Matrix2D = tuple[tuple[float, float], tuple[float, float]]
Transform = Union[Matrix2D, Callable[[Point], Point]]

# Collision types
CollisionCallback = Callable[[Sprite, Sprite], bool]
CollisionMask = Union[Mask, Callable[[Sprite], Mask]]

Usage Examples

Type-Safe Event Handling

import pygame
from pygame.typing import Event, KeyEventType, MouseEventType
from typing import Union

def handle_keyboard_event(event: Event) -> None:
    """Type-safe keyboard event handler."""
    if event.type in (pygame.KEYDOWN, pygame.KEYUP):
        key: int = event.key
        mod: int = event.mod
        unicode_char: str = getattr(event, 'unicode', '')
        
        print(f"Key: {key}, Modifiers: {mod}, Unicode: {unicode_char}")

def handle_mouse_event(event: Event) -> None:
    """Type-safe mouse event handler."""
    if event.type == pygame.MOUSEBUTTONDOWN:
        button: int = event.button
        pos: tuple[int, int] = event.pos
        print(f"Mouse button {button} pressed at {pos}")
    
    elif event.type == pygame.MOUSEMOTION:
        pos: tuple[int, int] = event.pos
        rel: tuple[int, int] = event.rel
        buttons: tuple[bool, bool, bool] = event.buttons
        print(f"Mouse moved to {pos}, relative: {rel}")

# Usage in game loop
pygame.init()
screen = pygame.display.set_mode((800, 600))
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type in (pygame.KEYDOWN, pygame.KEYUP):
            handle_keyboard_event(event)
        elif event.type in (pygame.MOUSEBUTTONDOWN, pygame.MOUSEMOTION):
            handle_mouse_event(event)

pygame.quit()

Type-Safe Surface Operations

import pygame
from pygame.typing import ColorLike, RectLike, SurfaceLike
from typing import Optional

def create_colored_surface(
    size: tuple[int, int], 
    color: ColorLike, 
    alpha: Optional[int] = None
) -> pygame.Surface:
    """Create a surface filled with specified color."""
    surface = pygame.Surface(size)
    if alpha is not None:
        surface.set_alpha(alpha)
    surface.fill(color)
    return surface

def safe_blit(
    dest: pygame.Surface,
    source: pygame.Surface, 
    dest_rect: RectLike,
    source_rect: Optional[RectLike] = None
) -> pygame.Rect:
    """Type-safe surface blitting."""
    return dest.blit(source, dest_rect, source_rect)

# Usage
screen = pygame.display.set_mode((800, 600))

# Type-safe color specifications
red_surface = create_colored_surface((100, 100), "red")
blue_surface = create_colored_surface((50, 50), (0, 0, 255), alpha=128)
green_surface = create_colored_surface((75, 75), pygame.Color(0, 255, 0))

# Type-safe blitting
safe_blit(screen, red_surface, (100, 100))
safe_blit(screen, blue_surface, (200, 200))
safe_blit(screen, green_surface, pygame.Rect(300, 300, 75, 75))

Type-Safe Sprite Groups

import pygame
from pygame.typing import SpriteCollection
from typing import List, Optional

class TypedSprite(pygame.sprite.Sprite):
    """Sprite with type annotations."""
    
    def __init__(self, image: pygame.Surface, position: tuple[int, int]):
        super().__init__()
        self.image: pygame.Surface = image
        self.rect: pygame.Rect = image.get_rect()
        self.rect.topleft = position
        self.velocity: pygame.Vector2 = pygame.Vector2(0, 0)
    
    def update(self, dt: float) -> None:
        """Update sprite position based on velocity."""
        self.rect.x += int(self.velocity.x * dt)
        self.rect.y += int(self.velocity.y * dt)

class TypedGroup(pygame.sprite.Group):
    """Type-safe sprite group."""
    
    def get_sprites_at_pos(self, pos: tuple[int, int]) -> List[TypedSprite]:
        """Get all sprites at the given position."""
        sprites: List[TypedSprite] = []
        for sprite in self.sprites():
            if isinstance(sprite, TypedSprite) and sprite.rect.collidepoint(pos):
                sprites.append(sprite)
        return sprites
    
    def update_all(self, dt: float) -> None:
        """Update all sprites with delta time."""
        sprite: TypedSprite
        for sprite in self.sprites():
            if isinstance(sprite, TypedSprite):
                sprite.update(dt)

# Usage
pygame.init()
screen = pygame.display.set_mode((800, 600))

# Create typed sprites
player_image = pygame.Surface((50, 50))
player_image.fill((0, 255, 0))
player = TypedSprite(player_image, (400, 300))
player.velocity = pygame.Vector2(100, 0)

enemy_image = pygame.Surface((30, 30))
enemy_image.fill((255, 0, 0))
enemy = TypedSprite(enemy_image, (100, 100))
enemy.velocity = pygame.Vector2(50, 50)

# Create typed group
all_sprites = TypedGroup()
all_sprites.add(player, enemy)

# Type-safe operations
clock = pygame.time.Clock()
running = True

while running:
    dt = clock.tick(60) / 1000.0  # Delta time in seconds
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            clicked_sprites = all_sprites.get_sprites_at_pos(event.pos)
            print(f"Clicked on {len(clicked_sprites)} sprites")
    
    all_sprites.update_all(dt)
    
    screen.fill((0, 0, 0))
    all_sprites.draw(screen)
    pygame.display.flip()

pygame.quit()

Type-Safe Vector Math

import pygame
from pygame.typing import Vector2Like, Vector3Like
from typing import Union

def normalize_vector2(vector: Vector2Like) -> pygame.Vector2:
    """Normalize a 2D vector, accepting various input types."""
    if isinstance(vector, pygame.Vector2):
        return vector.normalize()
    elif isinstance(vector, (tuple, list)) and len(vector) >= 2:
        v = pygame.Vector2(vector[0], vector[1])
        return v.normalize()
    else:
        raise TypeError("Invalid vector type")

def distance_between_points(
    point1: Vector2Like, 
    point2: Vector2Like
) -> float:
    """Calculate distance between two points."""
    p1 = pygame.Vector2(point1) if not isinstance(point1, pygame.Vector2) else point1
    p2 = pygame.Vector2(point2) if not isinstance(point2, pygame.Vector2) else point2
    return p1.distance_to(p2)

def interpolate_vectors(
    start: Vector2Like,
    end: Vector2Like, 
    t: float
) -> pygame.Vector2:
    """Linear interpolation between two vectors."""
    v1 = pygame.Vector2(start) if not isinstance(start, pygame.Vector2) else start
    v2 = pygame.Vector2(end) if not isinstance(end, pygame.Vector2) else end
    return v1.lerp(v2, t)

# Usage examples
pos1 = pygame.Vector2(100, 100)
pos2 = (200, 200)  # Tuple also accepted
pos3 = [300, 300]  # List also accepted

# All these work with type safety
normalized = normalize_vector2(pos1)
distance = distance_between_points(pos1, pos2)
midpoint = interpolate_vectors(pos1, pos3, 0.5)

print(f"Normalized: {normalized}")
print(f"Distance: {distance}")  
print(f"Midpoint: {midpoint}")

IDE Integration Example

# mypy configuration example for pygame-ce projects
# mypy.ini or pyproject.toml

# [tool.mypy]
# python_version = "3.9"
# warn_return_any = true
# warn_unused_configs = true
# disallow_untyped_defs = true

import pygame
from pygame.typing import *  # Import all type definitions
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    # Additional imports for type checking only
    from typing import Any, Dict, List, Optional, Union
    from pygame import Surface, Rect, Color

def type_safe_game_function(
    screen: Surface,
    sprites: List[pygame.sprite.Sprite],
    background_color: ColorLike = (0, 0, 0),
    fps: int = 60
) -> None:
    """Example of fully type-annotated game function."""
    clock = pygame.time.Clock()
    sprite_group = pygame.sprite.Group()
    sprite_group.add(*sprites)
    
    running: bool = True
    while running:
        dt: float = clock.tick(fps) / 1000.0
        
        event: pygame.event.Event
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        
        sprite_group.update(dt)
        
        screen.fill(background_color)
        sprite_group.draw(screen)
        pygame.display.flip()

Constants

Type-related constants and literals:

# Literal types for common enumerations
BlendModes = Literal[
    "BLENDMODE_NONE",
    "BLENDMODE_BLEND", 
    "BLENDMODE_ADD",
    "BLENDMODE_SUB",
    "BLENDMODE_MULT"
]

SurfaceFlags = Literal[
    "SRCALPHA",
    "SRCCOLORKEY", 
    "RLEACCEL"
]

EventTypes = Literal[
    "QUIT", "KEYDOWN", "KEYUP",
    "MOUSEBUTTONDOWN", "MOUSEBUTTONUP", "MOUSEMOTION",
    "JOYAXISMOTION", "JOYBUTTONDOWN", "JOYBUTTONUP"
]

# Type checking utilities
TYPE_CHECKING: bool  # True during static analysis, False at runtime

Install with Tessl CLI

npx tessl i tessl/pypi-pygame-ce

docs

advanced-features.md

audio-system.md

core-system.md

cursor-management.md

display-graphics.md

event-handling.md

index.md

input-systems.md

math-operations.md

midi-support.md

sprites-game-objects.md

typing-support.md

tile.json