or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-drawing.mdaudio-sound.mdcore-system.mddrawing-shapes.mdevent-input.mdgame-objects.mdgraphics-display.mdindex.mdinput-devices.mdjoystick-gamepad.mdmath-utils.mdsurface-image.mdtext-font.mdtime-animation.mdtransform-image.md

game-objects.mddocs/

0

# Game Object Management

1

2

Sprite and collision system for managing game objects. Pygame's sprite system provides an organized way to handle game entities with automatic updating, rendering, and collision detection capabilities.

3

4

## Capabilities

5

6

### Sprite Base Class

7

8

Foundation class for all game objects with lifecycle management.

9

10

```python { .api }

11

class Sprite:

12

def __init__(self, *groups):

13

"""

14

Base class for visible game objects.

15

16

Args:

17

*groups: Sprite groups to add this sprite to

18

"""

19

20

def update(self, *args, **kwargs) -> None:

21

"""

22

Update sprite state (override in subclasses).

23

24

Args:

25

*args, **kwargs: Arguments passed from group.update()

26

"""

27

28

def kill(self) -> None:

29

"""Remove sprite from all groups."""

30

31

def alive(self) -> bool:

32

"""

33

Check if sprite is in any groups.

34

35

Returns:

36

bool: True if sprite belongs to at least one group

37

"""

38

39

def groups(self) -> list:

40

"""

41

Get list of groups containing this sprite.

42

43

Returns:

44

list: List of groups this sprite belongs to

45

"""

46

47

def add(self, *groups) -> None:

48

"""

49

Add sprite to groups.

50

51

Args:

52

*groups: Groups to add sprite to

53

"""

54

55

def remove(self, *groups) -> None:

56

"""

57

Remove sprite from groups.

58

59

Args:

60

*groups: Groups to remove sprite from

61

"""

62

63

# Required attributes for proper sprite behavior:

64

image: pygame.Surface # Visual representation

65

rect: pygame.Rect # Position and collision bounds

66

```

67

68

### Sprite Groups

69

70

Container classes for managing collections of sprites.

71

72

```python { .api }

73

class Group:

74

def __init__(self, *sprites):

75

"""

76

Container for sprites with batch operations.

77

78

Args:

79

*sprites: Initial sprites to add

80

"""

81

82

def sprites(self) -> list:

83

"""

84

Get list of all sprites in group.

85

86

Returns:

87

list: List of sprites in group

88

"""

89

90

def copy(self) -> 'Group':

91

"""

92

Create a copy of the group.

93

94

Returns:

95

Group: New group with same sprites

96

"""

97

98

def add(self, *sprites) -> None:

99

"""

100

Add sprites to group.

101

102

Args:

103

*sprites: Sprites to add

104

"""

105

106

def remove(self, *sprites) -> None:

107

"""

108

Remove sprites from group.

109

110

Args:

111

*sprites: Sprites to remove

112

"""

113

114

def has(self, *sprites) -> bool:

115

"""

116

Check if group contains sprites.

117

118

Args:

119

*sprites: Sprites to check

120

121

Returns:

122

bool: True if all sprites are in group

123

"""

124

125

def update(self, *args, **kwargs) -> None:

126

"""

127

Call update() on all sprites in group.

128

129

Args:

130

*args, **kwargs: Arguments passed to sprite.update()

131

"""

132

133

def draw(self, surface: pygame.Surface) -> list:

134

"""

135

Draw all sprites to a surface.

136

137

Args:

138

surface (pygame.Surface): Surface to draw on

139

140

Returns:

141

list: List of Rect areas that were drawn

142

"""

143

144

def clear(self, surface: pygame.Surface, background) -> list:

145

"""

146

Clear sprites by drawing background over them.

147

148

Args:

149

surface (pygame.Surface): Surface to clear on

150

background: Background to draw (Surface or color)

151

152

Returns:

153

list: List of Rect areas that were cleared

154

"""

155

156

def empty(self) -> None:

157

"""Remove all sprites from group."""

158

159

def __len__(self) -> int:

160

"""Get number of sprites in group."""

161

162

def __iter__(self):

163

"""Iterate over sprites in group."""

164

165

def __contains__(self, sprite) -> bool:

166

"""Check if sprite is in group."""

167

```

168

169

### Specialized Group Classes

170

171

Advanced group classes with additional features for game development.

172

173

```python { .api }

174

class RenderUpdates(Group):

175

def __init__(self, *sprites):

176

"""Group that tracks dirty rectangles for efficient screen updates."""

177

178

def draw(self, surface: pygame.Surface) -> list:

179

"""

180

Draw sprites and return list of updated areas.

181

182

Returns:

183

list[pygame.Rect]: Areas that were drawn (for display updates)

184

"""

185

186

class OrderedUpdates(RenderUpdates):

187

def __init__(self, *sprites):

188

"""Group that maintains sprite order for drawing."""

189

190

class LayeredUpdates(OrderedUpdates):

191

def __init__(self, *sprites, **kwargs):

192

"""

193

Group with sprite layers for depth sorting.

194

195

Keyword Args:

196

default_layer (int): Default layer for new sprites

197

"""

198

199

def add(self, *sprites, **kwargs) -> None:

200

"""

201

Add sprites to group with optional layer.

202

203

Keyword Args:

204

layer (int): Layer to add sprites to

205

"""

206

207

def change_layer(self, sprite, new_layer: int) -> None:

208

"""

209

Move sprite to different layer.

210

211

Args:

212

sprite: Sprite to move

213

new_layer (int): New layer number

214

"""

215

216

def get_layer_of_sprite(self, sprite) -> int:

217

"""

218

Get layer of a sprite.

219

220

Args:

221

sprite: Sprite to check

222

223

Returns:

224

int: Layer number

225

"""

226

227

def get_sprites_at(self, layer: int) -> list:

228

"""

229

Get all sprites at a specific layer.

230

231

Args:

232

layer (int): Layer to check

233

234

Returns:

235

list: Sprites at the layer

236

"""

237

238

def layers(self) -> list:

239

"""

240

Get list of all layers.

241

242

Returns:

243

list[int]: Sorted list of layer numbers

244

"""

245

246

class GroupSingle(Group):

247

def __init__(self, sprite = None):

248

"""

249

Group that holds only one sprite at a time.

250

251

Args:

252

sprite: Initial sprite (optional)

253

"""

254

255

@property

256

def sprite(self):

257

"""Get the single sprite in group (or None)."""

258

```

259

260

### Sprite Variants

261

262

Specialized sprite classes with additional functionality.

263

264

```python { .api }

265

class DirtySprite(Sprite):

266

def __init__(self, *groups):

267

"""Sprite that tracks changes for efficient rendering."""

268

269

dirty: int # 0=clean, 1=dirty, 2=always dirty

270

source_rect: pygame.Rect # Source area for blitting

271

visible: int # Visibility flag

272

273

class WeakSprite(Sprite):

274

def __init__(self, *groups):

275

"""Sprite with weak references to groups (for memory management)."""

276

277

class WeakDirtySprite(WeakSprite, DirtySprite):

278

def __init__(self, *groups):

279

"""Sprite combining weak references and dirty tracking."""

280

```

281

282

## Collision Detection

283

284

Functions for detecting collisions between sprites and groups.

285

286

```python { .api }

287

def spritecollide(sprite, group: Group, dokill: bool, collided = None) -> list:

288

"""

289

Find sprites in group that collide with given sprite.

290

291

Args:

292

sprite: Sprite to check collisions for

293

group (Group): Group to check against

294

dokill (bool): Remove colliding sprites from group

295

collided: Collision detection function (default: collide_rect)

296

297

Returns:

298

list: List of sprites that collide

299

"""

300

301

def groupcollide(group1: Group, group2: Group, dokill1: bool, dokill2: bool, collided = None) -> dict:

302

"""

303

Detect collisions between two sprite groups.

304

305

Args:

306

group1 (Group): First group

307

group2 (Group): Second group

308

dokill1 (bool): Remove colliding sprites from group1

309

dokill2 (bool): Remove colliding sprites from group2

310

collided: Collision detection function

311

312

Returns:

313

dict: Mapping of group1 sprites to list of colliding group2 sprites

314

"""

315

316

def spritecollideany(sprite, group: Group, collided = None):

317

"""

318

Find first sprite in group that collides with given sprite.

319

320

Args:

321

sprite: Sprite to check collisions for

322

group (Group): Group to check against

323

collided: Collision detection function

324

325

Returns:

326

Sprite or None: First colliding sprite found

327

"""

328

```

329

330

### Collision Detection Functions

331

332

Different collision detection algorithms for various game needs.

333

334

```python { .api }

335

def collide_rect(left, right) -> bool:

336

"""

337

Collision detection using sprite rectangles.

338

339

Args:

340

left, right: Sprites to check

341

342

Returns:

343

bool: True if rectangles overlap

344

"""

345

346

def collide_rect_ratio(ratio: float):

347

"""

348

Create collision function using scaled rectangles.

349

350

Args:

351

ratio (float): Scale factor for rectangles

352

353

Returns:

354

function: Collision detection function

355

"""

356

357

def collide_circle(left, right) -> bool:

358

"""

359

Collision detection using circular areas.

360

361

Args:

362

left, right: Sprites to check (must have .radius attribute)

363

364

Returns:

365

bool: True if circles overlap

366

"""

367

368

def collide_circle_ratio(ratio: float):

369

"""

370

Create collision function using scaled circles.

371

372

Args:

373

ratio (float): Scale factor for circles

374

375

Returns:

376

function: Collision detection function

377

"""

378

379

def collide_mask(left, right):

380

"""

381

Pixel-perfect collision detection using masks.

382

383

Args:

384

left, right: Sprites to check (must have .mask attribute)

385

386

Returns:

387

tuple or None: Collision point or None if no collision

388

"""

389

```

390

391

## Usage Examples

392

393

### Basic Sprite Usage

394

395

```python

396

import pygame

397

398

class Player(pygame.sprite.Sprite):

399

def __init__(self):

400

super().__init__()

401

402

# Required sprite attributes

403

self.image = pygame.Surface((32, 32))

404

self.image.fill((0, 128, 255)) # Blue player

405

self.rect = self.image.get_rect()

406

self.rect.center = (400, 300)

407

408

# Custom attributes

409

self.speed = 5

410

411

def update(self):

412

# Move based on keyboard input

413

keys = pygame.key.get_pressed()

414

if keys[pygame.K_LEFT]:

415

self.rect.x -= self.speed

416

if keys[pygame.K_RIGHT]:

417

self.rect.x += self.speed

418

if keys[pygame.K_UP]:

419

self.rect.y -= self.speed

420

if keys[pygame.K_DOWN]:

421

self.rect.y += self.speed

422

423

# Keep player on screen

424

self.rect.clamp_ip(pygame.Rect(0, 0, 800, 600))

425

426

class Enemy(pygame.sprite.Sprite):

427

def __init__(self, x, y):

428

super().__init__()

429

430

self.image = pygame.Surface((24, 24))

431

self.image.fill((255, 0, 0)) # Red enemy

432

self.rect = self.image.get_rect()

433

self.rect.center = (x, y)

434

435

self.speed = 2

436

self.direction = 1

437

438

def update(self):

439

# Simple back and forth movement

440

self.rect.x += self.speed * self.direction

441

if self.rect.left < 0 or self.rect.right > 800:

442

self.direction *= -1

443

444

# Initialize pygame

445

pygame.init()

446

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

447

clock = pygame.time.Clock()

448

449

# Create sprite groups

450

all_sprites = pygame.sprite.Group()

451

enemies = pygame.sprite.Group()

452

453

# Create player

454

player = Player()

455

all_sprites.add(player)

456

457

# Create enemies

458

for i in range(5):

459

enemy = Enemy(100 + i * 120, 100)

460

all_sprites.add(enemy)

461

enemies.add(enemy)

462

463

running = True

464

while running:

465

for event in pygame.event.get():

466

if event.type == pygame.QUIT:

467

running = False

468

469

# Update all sprites

470

all_sprites.update()

471

472

# Check collisions

473

hits = pygame.sprite.spritecollide(player, enemies, True)

474

for hit in hits:

475

print("Player hit enemy!")

476

477

# Draw everything

478

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

479

all_sprites.draw(screen)

480

481

pygame.display.flip()

482

clock.tick(60)

483

484

pygame.quit()

485

```

486

487

### Advanced Collision Detection

488

489

```python

490

import pygame

491

import math

492

493

class Ball(pygame.sprite.Sprite):

494

def __init__(self, x, y):

495

super().__init__()

496

497

# Create circular sprite

498

self.radius = 15

499

self.image = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)

500

pygame.draw.circle(self.image, (255, 255, 0), (self.radius, self.radius), self.radius)

501

502

self.rect = self.image.get_rect()

503

self.rect.center = (x, y)

504

505

# Physics

506

self.vel_x = random.uniform(-5, 5)

507

self.vel_y = random.uniform(-5, 5)

508

509

def update(self):

510

self.rect.x += self.vel_x

511

self.rect.y += self.vel_y

512

513

# Bounce off walls

514

if self.rect.left < 0 or self.rect.right > 800:

515

self.vel_x *= -1

516

if self.rect.top < 0 or self.rect.bottom > 600:

517

self.vel_y *= -1

518

519

import random

520

521

pygame.init()

522

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

523

clock = pygame.time.Clock()

524

525

# Create balls

526

balls = pygame.sprite.Group()

527

for _ in range(10):

528

ball = Ball(random.randint(50, 750), random.randint(50, 550))

529

balls.add(ball)

530

531

running = True

532

while running:

533

for event in pygame.event.get():

534

if event.type == pygame.QUIT:

535

running = False

536

537

balls.update()

538

539

# Check ball-to-ball collisions using circle collision

540

for ball in balls:

541

collisions = pygame.sprite.spritecollide(ball, balls, False, pygame.sprite.collide_circle)

542

for other in collisions:

543

if ball != other:

544

# Simple collision response

545

dx = ball.rect.centerx - other.rect.centerx

546

dy = ball.rect.centery - other.rect.centery

547

distance = math.sqrt(dx*dx + dy*dy)

548

549

if distance > 0:

550

# Normalize and separate

551

dx /= distance

552

dy /= distance

553

ball.rect.centerx += dx * 2

554

ball.rect.centery += dy * 2

555

556

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

557

balls.draw(screen)

558

pygame.display.flip()

559

clock.tick(60)

560

561

pygame.quit()

562

```

563

564

### Layered Sprite Management

565

566

```python

567

import pygame

568

569

class Background(pygame.sprite.Sprite):

570

def __init__(self):

571

super().__init__()

572

self.image = pygame.Surface((800, 600))

573

self.image.fill((50, 100, 50)) # Green background

574

self.rect = self.image.get_rect()

575

576

class Player(pygame.sprite.Sprite):

577

def __init__(self):

578

super().__init__()

579

self.image = pygame.Surface((32, 32))

580

self.image.fill((0, 0, 255)) # Blue player

581

self.rect = self.image.get_rect()

582

self.rect.center = (400, 300)

583

584

class Bullet(pygame.sprite.Sprite):

585

def __init__(self, x, y):

586

super().__init__()

587

self.image = pygame.Surface((4, 8))

588

self.image.fill((255, 255, 0)) # Yellow bullet

589

self.rect = self.image.get_rect()

590

self.rect.centerx = x

591

self.rect.bottom = y

592

593

self.speed = -10

594

595

def update(self):

596

self.rect.y += self.speed

597

if self.rect.bottom < 0:

598

self.kill()

599

600

pygame.init()

601

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

602

clock = pygame.time.Clock()

603

604

# Use layered group for depth sorting

605

all_sprites = pygame.sprite.LayeredUpdates()

606

607

# Add sprites to specific layers (lower numbers = behind, higher = in front)

608

background = Background()

609

all_sprites.add(background, layer=0)

610

611

player = Player()

612

all_sprites.add(player, layer=2)

613

614

bullets = pygame.sprite.Group()

615

616

running = True

617

while running:

618

for event in pygame.event.get():

619

if event.type == pygame.QUIT:

620

running = False

621

elif event.type == pygame.KEYDOWN:

622

if event.key == pygame.K_SPACE:

623

bullet = Bullet(player.rect.centerx, player.rect.top)

624

all_sprites.add(bullet, layer=1) # Behind player

625

bullets.add(bullet)

626

627

all_sprites.update()

628

629

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

630

all_sprites.draw(screen) # Draws in layer order

631

632

pygame.display.flip()

633

clock.tick(60)

634

635

pygame.quit()

636

```

637

638

### Performance Optimization with Dirty Rectangles

639

640

```python

641

import pygame

642

643

class MovingSprite(pygame.sprite.DirtySprite):

644

def __init__(self, x, y, color):

645

super().__init__()

646

647

self.image = pygame.Surface((20, 20))

648

self.image.fill(color)

649

self.rect = self.image.get_rect()

650

self.rect.center = (x, y)

651

652

# DirtySprite attributes

653

self.dirty = 1 # Start dirty

654

655

self.vel_x = random.uniform(-3, 3)

656

self.vel_y = random.uniform(-3, 3)

657

658

def update(self):

659

old_rect = self.rect.copy()

660

661

self.rect.x += self.vel_x

662

self.rect.y += self.vel_y

663

664

# Bounce off walls

665

if self.rect.left < 0 or self.rect.right > 800:

666

self.vel_x *= -1

667

if self.rect.top < 0 or self.rect.bottom > 600:

668

self.vel_y *= -1

669

670

# Mark as dirty if moved

671

if self.rect != old_rect:

672

self.dirty = 1

673

674

import random

675

676

pygame.init()

677

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

678

clock = pygame.time.Clock()

679

680

# Use RenderUpdates for efficient screen updates

681

sprites = pygame.sprite.RenderUpdates()

682

683

# Create many moving sprites

684

for _ in range(50):

685

color = (random.randint(100, 255), random.randint(100, 255), random.randint(100, 255))

686

sprite = MovingSprite(random.randint(0, 800), random.randint(0, 600), color)

687

sprites.add(sprite)

688

689

background = pygame.Surface(screen.get_size())

690

background.fill((30, 30, 30))

691

692

running = True

693

while running:

694

for event in pygame.event.get():

695

if event.type == pygame.QUIT:

696

running = False

697

698

sprites.update()

699

700

# Only update changed areas

701

dirty_rects = sprites.draw(screen)

702

pygame.display.update(dirty_rects)

703

704

# Clear sprites for next frame (only dirty areas)

705

sprites.clear(screen, background)

706

707

clock.tick(60)

708

709

pygame.quit()

710

```