Python Game Development library providing comprehensive multimedia functionality for creating games and interactive applications.
—
Vector mathematics and geometric utilities for game development. Provides 2D and 3D vector operations, rectangle manipulation, and collision detection.
The Vector2 class provides comprehensive 2D vector operations for game mathematics.
class Vector2:
def __init__(self, x: float = 0, y: float = 0):
"""
Initialize 2D vector.
Parameters:
x: X component
y: Y component
"""
x: float # X component
y: float # Y component
# Properties
length: float # Vector magnitude (read-only)
length_squared: float # Squared magnitude (read-only, faster than length)
magnitude: float # Alias for length
magnitude_squared: float # Alias for length_squared
def normalize(self) -> Vector2:
"""
Get normalized vector (length 1).
Returns:
Vector2: New normalized vector
"""
def normalize_ip(self) -> None:
"""Normalize vector in place."""
def is_normalized(self, tolerance: float = 1e-6) -> bool:
"""
Check if vector is normalized.
Parameters:
tolerance: Tolerance for comparison
Returns:
bool: True if vector length is approximately 1
"""
def scale_to_length(self, length: float) -> Vector2:
"""
Scale vector to specific length.
Parameters:
length: Target length
Returns:
Vector2: New vector with specified length
"""
def distance_to(self, other: Vector2) -> float:
"""
Calculate distance to another vector.
Parameters:
other: Other vector
Returns:
float: Distance between vectors
"""
def distance_squared_to(self, other: Vector2) -> float:
"""
Calculate squared distance (faster than distance_to).
Parameters:
other: Other vector
Returns:
float: Squared distance
"""
def dot(self, other: Vector2) -> float:
"""
Calculate dot product.
Parameters:
other: Other vector
Returns:
float: Dot product
"""
def cross(self, other: Vector2) -> float:
"""
Calculate cross product (returns scalar in 2D).
Parameters:
other: Other vector
Returns:
float: Cross product magnitude
"""
def angle_to(self, other: Vector2) -> float:
"""
Calculate angle between vectors in degrees.
Parameters:
other: Other vector
Returns:
float: Angle in degrees
"""
def rotate(self, angle: float) -> Vector2:
"""
Rotate vector by angle in degrees.
Parameters:
angle: Rotation angle in degrees
Returns:
Vector2: New rotated vector
"""
def rotate_ip(self, angle: float) -> None:
"""
Rotate vector in place.
Parameters:
angle: Rotation angle in degrees
"""
def rotate_rad(self, angle: float) -> Vector2:
"""
Rotate vector by angle in radians.
Parameters:
angle: Rotation angle in radians
Returns:
Vector2: New rotated vector
"""
def rotate_rad_ip(self, angle: float) -> None:
"""
Rotate vector in place by radians.
Parameters:
angle: Rotation angle in radians
"""
def reflect(self, normal: Vector2) -> Vector2:
"""
Reflect vector across normal.
Parameters:
normal: Surface normal vector
Returns:
Vector2: Reflected vector
"""
def reflect_ip(self, normal: Vector2) -> None:
"""
Reflect vector in place.
Parameters:
normal: Surface normal vector
"""
def lerp(self, other: Vector2, t: float) -> Vector2:
"""
Linear interpolation between vectors.
Parameters:
other: Target vector
t: Interpolation factor (0.0 to 1.0)
Returns:
Vector2: Interpolated vector
"""
def slerp(self, other: Vector2, t: float) -> Vector2:
"""
Spherical linear interpolation.
Parameters:
other: Target vector
t: Interpolation factor (0.0 to 1.0)
Returns:
Vector2: Interpolated vector
"""
def move_towards(self, target: Vector2, max_distance: float) -> Vector2:
"""
Move towards target by maximum distance.
Parameters:
target: Target vector
max_distance: Maximum distance to move
Returns:
Vector2: New vector moved towards target
"""
def move_towards_ip(self, target: Vector2, max_distance: float) -> None:
"""
Move towards target in place.
Parameters:
target: Target vector
max_distance: Maximum distance to move
"""
def clamp_magnitude(self, max_length: float) -> Vector2:
"""
Clamp vector magnitude to maximum length.
Parameters:
max_length: Maximum allowed length
Returns:
Vector2: Clamped vector
"""
def clamp_magnitude_ip(self, max_length: float) -> None:
"""
Clamp magnitude in place.
Parameters:
max_length: Maximum allowed length
"""
def copy(self) -> Vector2:
"""
Create copy of vector.
Returns:
Vector2: Vector copy
"""
def as_polar(self) -> tuple[float, float]:
"""
Convert to polar coordinates.
Returns:
tuple[float, float]: (radius, angle_degrees)
"""
@classmethod
def from_polar(cls, polar: tuple[float, float]) -> Vector2:
"""
Create vector from polar coordinates.
Parameters:
polar: (radius, angle_degrees)
Returns:
Vector2: New vector from polar coordinates
"""
def elementwise(self) -> VectorElementwiseProxy:
"""
Get elementwise operations proxy.
Returns:
VectorElementwiseProxy: Proxy for elementwise operations
"""The Vector3 class extends vector operations to three dimensions.
class Vector3:
def __init__(self, x: float = 0, y: float = 0, z: float = 0):
"""
Initialize 3D vector.
Parameters:
x: X component
y: Y component
z: Z component
"""
x: float # X component
y: float # Y component
z: float # Z component
# Properties (similar to Vector2)
length: float
length_squared: float
magnitude: float
magnitude_squared: float
# Methods (similar to Vector2 with 3D extensions)
def normalize(self) -> Vector3: ...
def normalize_ip(self) -> None: ...
def scale_to_length(self, length: float) -> Vector3: ...
def distance_to(self, other: Vector3) -> float: ...
def distance_squared_to(self, other: Vector3) -> float: ...
def dot(self, other: Vector3) -> float: ...
def cross(self, other: Vector3) -> Vector3:
"""
Calculate cross product (returns Vector3 in 3D).
Parameters:
other: Other vector
Returns:
Vector3: Cross product vector
"""
def rotate_x(self, angle: float) -> Vector3:
"""
Rotate around X axis.
Parameters:
angle: Rotation angle in degrees
Returns:
Vector3: Rotated vector
"""
def rotate_x_ip(self, angle: float) -> None: ...
def rotate_y(self, angle: float) -> Vector3: ...
def rotate_y_ip(self, angle: float) -> None: ...
def rotate_z(self, angle: float) -> Vector3: ...
def rotate_z_ip(self, angle: float) -> None: ...
def reflect(self, normal: Vector3) -> Vector3: ...
def reflect_ip(self, normal: Vector3) -> None: ...
def lerp(self, other: Vector3, t: float) -> Vector3: ...
def slerp(self, other: Vector3, t: float) -> Vector3: ...
def copy(self) -> Vector3: ...Enhanced rectangle operations for collision detection and positioning.
class Rect:
def __init__(self, left: int, top: int, width: int, height: int):
"""
Initialize rectangle.
Parameters:
left: Left coordinate
top: Top coordinate
width: Rectangle width
height: Rectangle height
"""
# Position and size attributes
x: int # Left coordinate (alias for left)
y: int # Top coordinate (alias for top)
left: int # Left edge
top: int # Top edge
width: int # Width
height: int # Height
w: int # Width alias
h: int # Height alias
# Computed attributes
right: int # Right edge (left + width)
bottom: int # Bottom edge (top + height)
# Corner positions
topleft: tuple[int, int] # (left, top)
topright: tuple[int, int] # (right, top)
bottomleft: tuple[int, int] # (left, bottom)
bottomright: tuple[int, int] # (right, bottom)
# Edge midpoints
midtop: tuple[int, int] # (centerx, top)
midleft: tuple[int, int] # (left, centery)
midbottom: tuple[int, int] # (centerx, bottom)
midright: tuple[int, int] # (right, centery)
# Center
center: tuple[int, int] # (centerx, centery)
centerx: int # Horizontal center
centery: int # Vertical center
# Size
size: tuple[int, int] # (width, height)
def copy(self) -> Rect:
"""Create copy of rectangle."""
def move(self, x: int, y: int) -> Rect:
"""
Create moved rectangle.
Parameters:
x: Horizontal offset
y: Vertical offset
Returns:
Rect: New moved rectangle
"""
def move_ip(self, x: int, y: int) -> None:
"""Move rectangle in place."""
def inflate(self, x: int, y: int) -> Rect:
"""
Create inflated rectangle (grow/shrink).
Parameters:
x: Horizontal size change
y: Vertical size change
Returns:
Rect: New inflated rectangle
"""
def inflate_ip(self, x: int, y: int) -> None:
"""Inflate rectangle in place."""
def scale_by(self, scalar: float) -> Rect:
"""
Scale rectangle by factor.
Parameters:
scalar: Scale factor
Returns:
Rect: Scaled rectangle
"""
def scale_by_ip(self, scalar: float) -> None:
"""Scale rectangle in place."""
def clamp(self, rect: Rect) -> Rect:
"""
Create rectangle clamped inside another rectangle.
Parameters:
rect: Bounding rectangle
Returns:
Rect: Clamped rectangle
"""
def clamp_ip(self, rect: Rect) -> None:
"""Clamp rectangle in place."""
def clip(self, rect: Rect) -> Rect:
"""
Get intersection with another rectangle.
Parameters:
rect: Rectangle to intersect with
Returns:
Rect: Intersection rectangle (may have zero area)
"""
def clipline(self, line: tuple[tuple[int, int], tuple[int, int]]) -> tuple[tuple[int, int], tuple[int, int]] | tuple[]:
"""
Clip line to rectangle boundaries.
Parameters:
line: ((x1, y1), (x2, y2)) line endpoints
Returns:
tuple: Clipped line endpoints or empty tuple if no intersection
"""
def union(self, rect: Rect) -> Rect:
"""
Get union with another rectangle.
Parameters:
rect: Rectangle to union with
Returns:
Rect: Bounding rectangle containing both
"""
def union_ip(self, rect: Rect) -> None:
"""Union rectangle in place."""
def unionall(self, rect_sequence: list[Rect]) -> Rect:
"""
Union with multiple rectangles.
Parameters:
rect_sequence: List of rectangles
Returns:
Rect: Bounding rectangle containing all
"""
def unionall_ip(self, rect_sequence: list[Rect]) -> None:
"""Union all rectangles in place."""
def fit(self, rect: Rect) -> Rect:
"""
Fit rectangle inside another rectangle, maintaining aspect ratio.
Parameters:
rect: Container rectangle
Returns:
Rect: Fitted rectangle
"""
def normalize(self) -> None:
"""Ensure width and height are positive."""
def contains(self, rect: Rect) -> bool:
"""
Check if rectangle completely contains another.
Parameters:
rect: Rectangle to test
Returns:
bool: True if rect is completely inside this rectangle
"""
def collidepoint(self, point: tuple[int, int]) -> bool:
"""
Check if point is inside rectangle.
Parameters:
point: (x, y) point to test
Returns:
bool: True if point is inside
"""
def colliderect(self, rect: Rect) -> bool:
"""
Check if rectangles overlap.
Parameters:
rect: Rectangle to test
Returns:
bool: True if rectangles overlap
"""
def collidelist(self, list: list[Rect]) -> int:
"""
Find first colliding rectangle in list.
Parameters:
list: List of rectangles to test
Returns:
int: Index of first collision, or -1 if none
"""
def collidelistall(self, list: list[Rect]) -> list[int]:
"""
Find all colliding rectangles in list.
Parameters:
list: List of rectangles to test
Returns:
list[int]: Indices of all colliding rectangles
"""
def collidedict(self, dict: dict) -> tuple | None:
"""
Find first colliding rectangle in dictionary.
Parameters:
dict: Dictionary with Rect values
Returns:
tuple | None: (key, value) of first collision or None
"""
def collidedictall(self, dict: dict) -> list[tuple]:
"""
Find all colliding rectangles in dictionary.
Parameters:
dict: Dictionary with Rect values
Returns:
list[tuple]: List of (key, value) pairs for collisions
"""
def update(self, *args) -> None:
"""Update rectangle with new position/size."""FRect provides the same interface as Rect but with floating-point precision.
class FRect:
"""Floating-point rectangle with same methods as Rect."""
def __init__(self, left: float, top: float, width: float, height: float): ...
# All attributes and methods same as Rect but with float types
x: float
y: float
width: float
height: float
# ... (same interface as Rect)import pygame
import math
# Create vectors
velocity = pygame.Vector2(5, 3)
position = pygame.Vector2(100, 100)
target = pygame.Vector2(400, 300)
# Basic operations
print(f"Velocity magnitude: {velocity.length}")
print(f"Distance to target: {position.distance_to(target)}")
# Normalize for direction
direction = (target - position).normalize()
print(f"Direction to target: {direction}")
# Move towards target
max_speed = 200 # pixels per second
dt = 1/60 # delta time (60 FPS)
new_position = position.move_towards(target, max_speed * dt)
# Rotation
velocity_rotated = velocity.rotate(45) # 45 degrees
print(f"Rotated velocity: {velocity_rotated}")
# Reflection (for bouncing)
wall_normal = pygame.Vector2(0, -1) # Upward normal
reflected_velocity = velocity.reflect(wall_normal)
# Dot product (for angle calculations)
angle = math.degrees(math.acos(velocity.normalize().dot(direction)))
print(f"Angle between velocity and direction: {angle}")import pygame
import math
class MovingObject:
def __init__(self, x, y):
self.position = pygame.Vector2(x, y)
self.velocity = pygame.Vector2(0, 0)
self.acceleration = pygame.Vector2(0, 0)
self.max_speed = 200
self.friction = 0.95
def seek(self, target):
"""Steer towards target position"""
desired = (target - self.position).normalize() * self.max_speed
steer = desired - self.velocity
return steer.clamp_magnitude(5) # Max steering force
def update(self, dt):
# Apply physics
self.velocity += self.acceleration * dt
self.velocity *= self.friction # Apply friction
self.velocity = self.velocity.clamp_magnitude(self.max_speed)
self.position += self.velocity * dt
# Reset acceleration
self.acceleration *= 0
# Example usage
obj = MovingObject(100, 100)
target = pygame.Vector2(400, 300)
# Apply steering force
steering = obj.seek(target)
obj.acceleration += steering
obj.update(1/60) # Update with 60 FPS delta timeimport pygame
# Create rectangles
player = pygame.Rect(100, 100, 50, 50)
wall = pygame.Rect(200, 150, 20, 100)
enemies = [
pygame.Rect(300, 120, 40, 40),
pygame.Rect(350, 180, 30, 30),
pygame.Rect(400, 200, 35, 35)
]
# Point collision
mouse_pos = pygame.mouse.get_pos()
if player.collidepoint(mouse_pos):
print("Mouse over player")
# Rectangle collision
if player.colliderect(wall):
print("Player hit wall")
# Multiple collision testing
hit_enemy = player.collidelist(enemies)
if hit_enemy >= 0:
print(f"Player hit enemy {hit_enemy}")
# Get all collisions
all_hits = player.collidelistall(enemies)
print(f"Player hit enemies: {all_hits}")
# Movement with collision
keys = pygame.key.get_pressed()
old_pos = player.topleft
if keys[pygame.K_LEFT]:
player.x -= 5
if keys[pygame.K_RIGHT]:
player.x += 5
if keys[pygame.K_UP]:
player.y -= 5
if keys[pygame.K_DOWN]:
player.y += 5
# Check for wall collision and revert if needed
if player.colliderect(wall):
player.topleft = old_pos # Revert movementimport pygame
# Create rectangle
rect = pygame.Rect(100, 100, 200, 150)
# Position by different anchors
rect.center = (400, 300) # Center at point
rect.topleft = (50, 50) # Top-left corner
rect.bottomright = (800, 600) # Bottom-right corner
# Resize and move
larger_rect = rect.inflate(50, 30) # Grow by 50x30
moved_rect = rect.move(10, -5) # Move by offset
# Clamp inside screen
screen_rect = pygame.Rect(0, 0, 800, 600)
clamped_rect = rect.clamp(screen_rect)
# Get intersection
overlap = rect.clip(larger_rect)
if overlap.width > 0 and overlap.height > 0:
print(f"Overlap area: {overlap}")
# Union (bounding box)
bounding_box = rect.union(moved_rect)
print(f"Bounding box: {bounding_box}")
# Line clipping
line = ((0, 0), (800, 600)) # Diagonal line
clipped_line = rect.clipline(line)
if clipped_line:
print(f"Line enters/exits rect at: {clipped_line}")import pygame
import math
class PhysicsObject:
def __init__(self, x, y, mass=1.0):
self.position = pygame.Vector2(x, y)
self.velocity = pygame.Vector2(0, 0)
self.acceleration = pygame.Vector2(0, 0)
self.mass = mass
self.radius = 20
def apply_force(self, force):
"""Apply force (F = ma, so a = F/m)"""
self.acceleration += force / self.mass
def update(self, dt):
# Integrate physics
self.velocity += self.acceleration * dt
self.position += self.velocity * dt
# Clear acceleration
self.acceleration *= 0
# Boundary collision (simple bounce)
if self.position.x < self.radius or self.position.x > 800 - self.radius:
self.velocity.x *= -0.8 # Bounce with energy loss
if self.position.y < self.radius or self.position.y > 600 - self.radius:
self.velocity.y *= -0.8
# Clamp position to screen
self.position.x = max(self.radius, min(800 - self.radius, self.position.x))
self.position.y = max(self.radius, min(600 - self.radius, self.position.y))
# Create objects
ball1 = PhysicsObject(200, 100, mass=2.0)
ball2 = PhysicsObject(600, 100, mass=1.0)
# Apply different forces
gravity = pygame.Vector2(0, 500) # Downward gravity
wind = pygame.Vector2(-100, 0) # Left wind
# Game loop
clock = pygame.time.Clock()
dt = 0
while True:
dt = clock.tick(60) / 1000.0 # Delta time in seconds
# Apply forces
ball1.apply_force(gravity * ball1.mass) # Weight = mg
ball1.apply_force(wind)
ball2.apply_force(gravity * ball2.mass)
# Update physics
ball1.update(dt)
ball2.update(dt)
# Check collision between balls
distance = ball1.position.distance_to(ball2.position)
if distance < ball1.radius + ball2.radius:
# Simple collision response
normal = (ball2.position - ball1.position).normalize()
relative_velocity = ball2.velocity - ball1.velocity
impulse = 2 * relative_velocity.dot(normal) / (ball1.mass + ball2.mass)
ball1.velocity += impulse * ball2.mass * normal
ball2.velocity -= impulse * ball1.mass * normalInstall with Tessl CLI
npx tessl i tessl/pypi-pygame-ce