or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdaudio-system.mdcore-system.mdcursor-management.mddisplay-graphics.mdevent-handling.mdindex.mdinput-systems.mdmath-operations.mdmidi-support.mdsprites-game-objects.mdtyping-support.md

typing-support.mddocs/

0

# Typing Support

1

2

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.

3

4

## Capabilities

5

6

### Core Type Aliases

7

8

Essential type aliases for common pygame data structures and parameters.

9

10

```python { .api }

11

# Geometric types

12

RectLike = Union[Rect, FRect, SequenceLike[float], SequenceLike[Point], _HasRectAttribute]

13

Point = SequenceLike[float]

14

IntPoint = SequenceLike[int]

15

Coordinate = Union[Point, int, float]

16

17

# Color types

18

ColorLike = Union[Color, SequenceLike[int], str, int]

19

RGB = tuple[int, int, int]

20

RGBA = tuple[int, int, int, int]

21

22

# File and path types

23

FileLike = Union[str, bytes, PathLike[str], PathLike[bytes], IO[bytes], IO[str]]

24

PathLike = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]

25

26

# Surface types

27

SurfaceLike = Union[Surface, SequenceLike[SequenceLike[ColorLike]]]

28

BlendMode = int

29

30

# Vector types

31

Vector2Like = Union[Vector2, SequenceLike[float], tuple[float, float]]

32

Vector3Like = Union[Vector3, SequenceLike[float], tuple[float, float, float]]

33

34

# Font types

35

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

36

37

# Event types

38

EventType = int

39

```

40

41

### Protocol Classes

42

43

Protocol classes for duck typing and structural subtyping support.

44

45

```python { .api }

46

class SequenceLike(Protocol[T_co]):

47

"""Protocol for sequence-like objects that support indexing and length."""

48

49

def __getitem__(self, index: int) -> T_co: ...

50

def __len__(self) -> int: ...

51

52

class _HasRectAttribute(Protocol):

53

"""Protocol for objects that have a rect attribute."""

54

rect: RectLike

55

56

class _ColorCompatible(Protocol):

57

"""Protocol for color-compatible objects."""

58

def __iter__(self) -> Iterator[int]: ...

59

def __len__(self) -> int: ...

60

61

class _SupportsWrite(Protocol[T_contra]):

62

"""Protocol for file-like objects that support writing."""

63

def write(self, data: T_contra) -> int: ...

64

65

class _SupportsRead(Protocol[T_co]):

66

"""Protocol for file-like objects that support reading."""

67

def read(self, size: int = -1) -> T_co: ...

68

```

69

70

### Surface Type Support

71

72

Type annotations for surface operations and transformations.

73

74

```python { .api }

75

# Surface creation types

76

SurfaceFlags = int

77

PixelFormat = int

78

Depth = int

79

Masks = tuple[int, int, int, int]

80

81

# Surface transformation types

82

ScaleMode = Literal["nearest", "linear"]

83

FlipMode = tuple[bool, bool]

84

RotationAngle = float

85

86

# Blending types

87

BlendModeType = Union[int, str]

88

SpecialFlags = int

89

```

90

91

### Event Type Annotations

92

93

Comprehensive event type support for type-safe event handling.

94

95

```python { .api }

96

# Event type unions

97

KeyEventType = Literal[KEYDOWN, KEYUP]

98

MouseEventType = Literal[MOUSEBUTTONDOWN, MOUSEBUTTONUP, MOUSEMOTION]

99

JoystickEventType = Literal[JOYAXISMOTION, JOYBUTTONDOWN, JOYBUTTONUP, JOYHATMOTION]

100

SystemEventType = Literal[QUIT, VIDEORESIZE, VIDEOEXPOSE]

101

102

# Event data types

103

class KeyEventDict(TypedDict):

104

key: int

105

mod: int

106

unicode: str

107

scancode: int

108

109

class MouseButtonEventDict(TypedDict):

110

button: int

111

pos: tuple[int, int]

112

113

class MouseMotionEventDict(TypedDict):

114

pos: tuple[int, int]

115

rel: tuple[int, int]

116

buttons: tuple[bool, bool, bool]

117

118

class JoystickAxisEventDict(TypedDict):

119

joy: int

120

axis: int

121

value: float

122

123

class JoystickButtonEventDict(TypedDict):

124

joy: int

125

button: int

126

127

class JoystickHatEventDict(TypedDict):

128

joy: int

129

hat: int

130

value: tuple[int, int]

131

```

132

133

### Function Type Signatures

134

135

Generic type signatures for common pygame function patterns.

136

137

```python { .api }

138

# Callback types

139

DrawCallback = Callable[[Surface], None]

140

UpdateCallback = Callable[[float], None]

141

EventCallback = Callable[[Event], None]

142

143

# Iterator types

144

SpriteIterator = Iterator[Sprite]

145

RectIterator = Iterator[Rect]

146

EventIterator = Iterator[Event]

147

148

# Optional types

149

OptionalSurface = Optional[Surface]

150

OptionalRect = Optional[Rect]

151

OptionalColor = Optional[ColorLike]

152

153

# Generic collection types

154

SpriteCollection = Union[Group, Sequence[Sprite]]

155

RectCollection = Union[Sequence[Rect], Sequence[RectLike]]

156

```

157

158

### Audio Type Support

159

160

Type annotations for audio and mixer functionality.

161

162

```python { .api }

163

# Audio format types

164

AudioFormat = Literal[-16, -8, 8, 16]

165

AudioChannels = Literal[1, 2]

166

AudioFrequency = Literal[11025, 22050, 44100, 48000]

167

168

# Audio data types

169

AudioArray = Union[bytes, numpy.ndarray]

170

AudioBuffer = Union[str, bytes, IO[bytes]]

171

172

# Channel types

173

ChannelType = Union[Channel, int]

174

LoopCount = int

175

FadeTime = int

176

```

177

178

### Math Type Support

179

180

Type annotations for mathematical operations and geometry.

181

182

```python { .api }

183

# Angle types

184

Degrees = float

185

Radians = float

186

AngleUnit = Union[Degrees, Radians]

187

188

# Geometric types

189

Distance = float

190

Scale = float

191

Ratio = float

192

193

# Transform types

194

Matrix2D = tuple[tuple[float, float], tuple[float, float]]

195

Transform = Union[Matrix2D, Callable[[Point], Point]]

196

197

# Collision types

198

CollisionCallback = Callable[[Sprite, Sprite], bool]

199

CollisionMask = Union[Mask, Callable[[Sprite], Mask]]

200

```

201

202

## Usage Examples

203

204

### Type-Safe Event Handling

205

206

```python

207

import pygame

208

from pygame.typing import Event, KeyEventType, MouseEventType

209

from typing import Union

210

211

def handle_keyboard_event(event: Event) -> None:

212

"""Type-safe keyboard event handler."""

213

if event.type in (pygame.KEYDOWN, pygame.KEYUP):

214

key: int = event.key

215

mod: int = event.mod

216

unicode_char: str = getattr(event, 'unicode', '')

217

218

print(f"Key: {key}, Modifiers: {mod}, Unicode: {unicode_char}")

219

220

def handle_mouse_event(event: Event) -> None:

221

"""Type-safe mouse event handler."""

222

if event.type == pygame.MOUSEBUTTONDOWN:

223

button: int = event.button

224

pos: tuple[int, int] = event.pos

225

print(f"Mouse button {button} pressed at {pos}")

226

227

elif event.type == pygame.MOUSEMOTION:

228

pos: tuple[int, int] = event.pos

229

rel: tuple[int, int] = event.rel

230

buttons: tuple[bool, bool, bool] = event.buttons

231

print(f"Mouse moved to {pos}, relative: {rel}")

232

233

# Usage in game loop

234

pygame.init()

235

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

236

running = True

237

238

while running:

239

for event in pygame.event.get():

240

if event.type == pygame.QUIT:

241

running = False

242

elif event.type in (pygame.KEYDOWN, pygame.KEYUP):

243

handle_keyboard_event(event)

244

elif event.type in (pygame.MOUSEBUTTONDOWN, pygame.MOUSEMOTION):

245

handle_mouse_event(event)

246

247

pygame.quit()

248

```

249

250

### Type-Safe Surface Operations

251

252

```python

253

import pygame

254

from pygame.typing import ColorLike, RectLike, SurfaceLike

255

from typing import Optional

256

257

def create_colored_surface(

258

size: tuple[int, int],

259

color: ColorLike,

260

alpha: Optional[int] = None

261

) -> pygame.Surface:

262

"""Create a surface filled with specified color."""

263

surface = pygame.Surface(size)

264

if alpha is not None:

265

surface.set_alpha(alpha)

266

surface.fill(color)

267

return surface

268

269

def safe_blit(

270

dest: pygame.Surface,

271

source: pygame.Surface,

272

dest_rect: RectLike,

273

source_rect: Optional[RectLike] = None

274

) -> pygame.Rect:

275

"""Type-safe surface blitting."""

276

return dest.blit(source, dest_rect, source_rect)

277

278

# Usage

279

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

280

281

# Type-safe color specifications

282

red_surface = create_colored_surface((100, 100), "red")

283

blue_surface = create_colored_surface((50, 50), (0, 0, 255), alpha=128)

284

green_surface = create_colored_surface((75, 75), pygame.Color(0, 255, 0))

285

286

# Type-safe blitting

287

safe_blit(screen, red_surface, (100, 100))

288

safe_blit(screen, blue_surface, (200, 200))

289

safe_blit(screen, green_surface, pygame.Rect(300, 300, 75, 75))

290

```

291

292

### Type-Safe Sprite Groups

293

294

```python

295

import pygame

296

from pygame.typing import SpriteCollection

297

from typing import List, Optional

298

299

class TypedSprite(pygame.sprite.Sprite):

300

"""Sprite with type annotations."""

301

302

def __init__(self, image: pygame.Surface, position: tuple[int, int]):

303

super().__init__()

304

self.image: pygame.Surface = image

305

self.rect: pygame.Rect = image.get_rect()

306

self.rect.topleft = position

307

self.velocity: pygame.Vector2 = pygame.Vector2(0, 0)

308

309

def update(self, dt: float) -> None:

310

"""Update sprite position based on velocity."""

311

self.rect.x += int(self.velocity.x * dt)

312

self.rect.y += int(self.velocity.y * dt)

313

314

class TypedGroup(pygame.sprite.Group):

315

"""Type-safe sprite group."""

316

317

def get_sprites_at_pos(self, pos: tuple[int, int]) -> List[TypedSprite]:

318

"""Get all sprites at the given position."""

319

sprites: List[TypedSprite] = []

320

for sprite in self.sprites():

321

if isinstance(sprite, TypedSprite) and sprite.rect.collidepoint(pos):

322

sprites.append(sprite)

323

return sprites

324

325

def update_all(self, dt: float) -> None:

326

"""Update all sprites with delta time."""

327

sprite: TypedSprite

328

for sprite in self.sprites():

329

if isinstance(sprite, TypedSprite):

330

sprite.update(dt)

331

332

# Usage

333

pygame.init()

334

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

335

336

# Create typed sprites

337

player_image = pygame.Surface((50, 50))

338

player_image.fill((0, 255, 0))

339

player = TypedSprite(player_image, (400, 300))

340

player.velocity = pygame.Vector2(100, 0)

341

342

enemy_image = pygame.Surface((30, 30))

343

enemy_image.fill((255, 0, 0))

344

enemy = TypedSprite(enemy_image, (100, 100))

345

enemy.velocity = pygame.Vector2(50, 50)

346

347

# Create typed group

348

all_sprites = TypedGroup()

349

all_sprites.add(player, enemy)

350

351

# Type-safe operations

352

clock = pygame.time.Clock()

353

running = True

354

355

while running:

356

dt = clock.tick(60) / 1000.0 # Delta time in seconds

357

358

for event in pygame.event.get():

359

if event.type == pygame.QUIT:

360

running = False

361

elif event.type == pygame.MOUSEBUTTONDOWN:

362

clicked_sprites = all_sprites.get_sprites_at_pos(event.pos)

363

print(f"Clicked on {len(clicked_sprites)} sprites")

364

365

all_sprites.update_all(dt)

366

367

screen.fill((0, 0, 0))

368

all_sprites.draw(screen)

369

pygame.display.flip()

370

371

pygame.quit()

372

```

373

374

### Type-Safe Vector Math

375

376

```python

377

import pygame

378

from pygame.typing import Vector2Like, Vector3Like

379

from typing import Union

380

381

def normalize_vector2(vector: Vector2Like) -> pygame.Vector2:

382

"""Normalize a 2D vector, accepting various input types."""

383

if isinstance(vector, pygame.Vector2):

384

return vector.normalize()

385

elif isinstance(vector, (tuple, list)) and len(vector) >= 2:

386

v = pygame.Vector2(vector[0], vector[1])

387

return v.normalize()

388

else:

389

raise TypeError("Invalid vector type")

390

391

def distance_between_points(

392

point1: Vector2Like,

393

point2: Vector2Like

394

) -> float:

395

"""Calculate distance between two points."""

396

p1 = pygame.Vector2(point1) if not isinstance(point1, pygame.Vector2) else point1

397

p2 = pygame.Vector2(point2) if not isinstance(point2, pygame.Vector2) else point2

398

return p1.distance_to(p2)

399

400

def interpolate_vectors(

401

start: Vector2Like,

402

end: Vector2Like,

403

t: float

404

) -> pygame.Vector2:

405

"""Linear interpolation between two vectors."""

406

v1 = pygame.Vector2(start) if not isinstance(start, pygame.Vector2) else start

407

v2 = pygame.Vector2(end) if not isinstance(end, pygame.Vector2) else end

408

return v1.lerp(v2, t)

409

410

# Usage examples

411

pos1 = pygame.Vector2(100, 100)

412

pos2 = (200, 200) # Tuple also accepted

413

pos3 = [300, 300] # List also accepted

414

415

# All these work with type safety

416

normalized = normalize_vector2(pos1)

417

distance = distance_between_points(pos1, pos2)

418

midpoint = interpolate_vectors(pos1, pos3, 0.5)

419

420

print(f"Normalized: {normalized}")

421

print(f"Distance: {distance}")

422

print(f"Midpoint: {midpoint}")

423

```

424

425

### IDE Integration Example

426

427

```python

428

# mypy configuration example for pygame-ce projects

429

# mypy.ini or pyproject.toml

430

431

# [tool.mypy]

432

# python_version = "3.9"

433

# warn_return_any = true

434

# warn_unused_configs = true

435

# disallow_untyped_defs = true

436

437

import pygame

438

from pygame.typing import * # Import all type definitions

439

from typing import TYPE_CHECKING

440

441

if TYPE_CHECKING:

442

# Additional imports for type checking only

443

from typing import Any, Dict, List, Optional, Union

444

from pygame import Surface, Rect, Color

445

446

def type_safe_game_function(

447

screen: Surface,

448

sprites: List[pygame.sprite.Sprite],

449

background_color: ColorLike = (0, 0, 0),

450

fps: int = 60

451

) -> None:

452

"""Example of fully type-annotated game function."""

453

clock = pygame.time.Clock()

454

sprite_group = pygame.sprite.Group()

455

sprite_group.add(*sprites)

456

457

running: bool = True

458

while running:

459

dt: float = clock.tick(fps) / 1000.0

460

461

event: pygame.event.Event

462

for event in pygame.event.get():

463

if event.type == pygame.QUIT:

464

running = False

465

466

sprite_group.update(dt)

467

468

screen.fill(background_color)

469

sprite_group.draw(screen)

470

pygame.display.flip()

471

```

472

473

## Constants

474

475

Type-related constants and literals:

476

477

```python { .api }

478

# Literal types for common enumerations

479

BlendModes = Literal[

480

"BLENDMODE_NONE",

481

"BLENDMODE_BLEND",

482

"BLENDMODE_ADD",

483

"BLENDMODE_SUB",

484

"BLENDMODE_MULT"

485

]

486

487

SurfaceFlags = Literal[

488

"SRCALPHA",

489

"SRCCOLORKEY",

490

"RLEACCEL"

491

]

492

493

EventTypes = Literal[

494

"QUIT", "KEYDOWN", "KEYUP",

495

"MOUSEBUTTONDOWN", "MOUSEBUTTONUP", "MOUSEMOTION",

496

"JOYAXISMOTION", "JOYBUTTONDOWN", "JOYBUTTONUP"

497

]

498

499

# Type checking utilities

500

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

501

```