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

math-operations.mddocs/

Mathematical Operations

Vector mathematics and geometric utilities for game development. Provides 2D and 3D vector operations, rectangle manipulation, and collision detection.

Capabilities

2D Vector Mathematics

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
        """

3D Vector Mathematics

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: ...

Rectangle Mathematics

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."""

Floating-Point Rectangles

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)

Usage Examples

Vector Mathematics

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}")

Advanced Movement

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 time

Rectangle Collision Detection

import 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 movement

Rectangle Manipulation

import 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}")

Game Physics Example

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 * normal

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