Python Game Development library providing comprehensive multimedia functionality for creating games and interactive applications.
—
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.
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 = intProtocol 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: ...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 = intComprehensive 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]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]]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 = intType 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]]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()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))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()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}")# 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()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 runtimeInstall with Tessl CLI
npx tessl i tessl/pypi-pygame-ce