CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-arcade

Arcade Game Development Library

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

sprite-system.mddocs/

Sprite System and Collision Detection

Complete sprite management system for game objects with support for animations, physics properties, collision detection, and efficient batch rendering through sprite lists.

Capabilities

Core Sprite Classes

Base sprite classes providing the foundation for all game objects in Arcade.

class Sprite:
    """
    Main sprite class for creating game objects with position, rotation, texture, and physics properties.
    """
    def __init__(self, filename: str = None, scale: float = 1, image_x: float = 0, image_y: float = 0, 
                 image_width: float = 0, image_height: float = 0, center_x: float = 0, center_y: float = 0,
                 repeat_count_x: int = 1, repeat_count_y: int = 1, flipped_horizontally: bool = False,
                 flipped_vertically: bool = False, flipped_diagonally: bool = False, hit_box_algorithm: str = "Simple",
                 hit_box_detail: float = 4.5, texture: arcade.Texture = None, angle: float = 0):
        """
        Create a new sprite.

        Args:
            filename: Path to texture file or resource handle (e.g., ":resources:images/...")
            scale: Scale factor for the sprite
            image_x: X offset within source image
            image_y: Y offset within source image  
            image_width: Width of region to use from source image
            image_height: Height of region to use from source image
            center_x: Initial X position
            center_y: Initial Y position
            repeat_count_x: Number of times to repeat texture horizontally
            repeat_count_y: Number of times to repeat texture vertically
            flipped_horizontally: Mirror sprite horizontally
            flipped_vertically: Mirror sprite vertically
            flipped_diagonally: Mirror sprite diagonally
            hit_box_algorithm: Algorithm for hit box calculation ("Simple", "Detailed", or "None")
            hit_box_detail: Detail level for "Detailed" hit box algorithm
            texture: Texture object to use instead of loading from file
            angle: Initial rotation angle in degrees
        """

    # Position properties
    center_x: float
    center_y: float
    left: float
    right: float
    top: float
    bottom: float
    
    # Movement properties
    change_x: float
    change_y: float
    velocity: tuple[float, float]
    
    # Rotation properties
    angle: float
    change_angle: float
    radians: float
    
    # Scale properties
    scale: float
    width: float
    height: float
    
    # Physics properties
    physics_engines: list
    
    # Texture properties
    texture: arcade.Texture
    textures: list[arcade.Texture]
    cur_texture_index: int
    
    # Hit box and collision
    hit_box: list[tuple[float, float]]
    
    # Identification
    guid: str
    
    def update(self) -> None:
        """Update sprite position based on velocity."""
        
    def update_animation(self, delta_time: float = 1/60) -> None:
        """Update sprite animation."""
        
    def on_update(self, delta_time: float = 1/60) -> None:
        """Override this method to add custom update logic."""
        
    def draw(self, *, filter=None, pixelated=None, blend_function=None) -> None:
        """Draw the sprite."""
        
    def draw_hit_box(self, color: arcade.types.Color = arcade.color.BLACK, line_thickness: float = 1) -> None:
        """Draw the sprite's hit box for debugging."""
        
    def set_hit_box(self, points: list[tuple[float, float]]) -> None:
        """Manually set the hit box points."""
        
    def get_adjusted_hit_box(self) -> list[tuple[float, float]]:
        """Get hit box adjusted for current position and rotation."""

class BasicSprite:
    """
    Minimal sprite implementation with reduced memory footprint for simple use cases.
    """
    def __init__(self, filename: str = None, scale: float = 1, center_x: float = 0, center_y: float = 0):
        """Create a basic sprite with minimal properties."""
    
    center_x: float
    center_y: float
    angle: float
    scale: float
    texture: arcade.Texture

Specialized Sprite Types

Pre-configured sprite classes for common game object patterns.

class SpriteSolidColor(arcade.Sprite):
    """
    Sprite with a solid color rectangle instead of a texture.
    """
    def __init__(self, width: int, height: int, color: arcade.types.Color, center_x: float = 0, center_y: float = 0):
        """
        Create a solid color sprite.

        Args:
            width: Width of the rectangle
            height: Height of the rectangle
            color: Color as RGB or RGBA tuple (0-255)
            center_x: Initial X position
            center_y: Initial Y position
        """

class SpriteCircle(arcade.Sprite):
    """
    Sprite with a circular shape.
    """
    def __init__(self, radius: int, color: arcade.types.Color, soft: bool = False, center_x: float = 0, center_y: float = 0):
        """
        Create a circular sprite.

        Args:
            radius: Radius of the circle
            color: Color as RGB or RGBA tuple (0-255)
            soft: Whether to use soft edges
            center_x: Initial X position
            center_y: Initial Y position
        """

class TextureAnimationSprite(arcade.Sprite):
    """
    Sprite with texture-based animation support.
    """
    def __init__(self, filename: str = None, scale: float = 1):
        """Create an animated sprite."""
    
    def update_animation(self, delta_time: float = 1/60) -> None:
        """Update animation based on elapsed time."""

class AnimatedWalkingSprite(arcade.Sprite):
    """
    Sprite with directional walking animations.
    """
    def __init__(self, scale: float = 1):
        """Create a walking animated sprite."""
    
    # Texture lists for different directions
    walk_up_textures: list[arcade.Texture]
    walk_down_textures: list[arcade.Texture]
    walk_left_textures: list[arcade.Texture] 
    walk_right_textures: list[arcade.Texture]
    stand_up_textures: list[arcade.Texture]
    stand_down_textures: list[arcade.Texture]
    stand_left_textures: list[arcade.Texture]
    stand_right_textures: list[arcade.Texture]
    
    def update_animation(self, delta_time: float = 1/60) -> None:
        """Update walking animation based on movement direction."""

Sprite Lists

Efficient containers for managing and rendering groups of sprites.

class SpriteList:
    """
    Container for managing groups of sprites with optimized batch rendering.
    """
    def __init__(self, use_spatial_hash: bool = None, spatial_hash_cell_size: int = 128, 
                 is_static: bool = False, atlas: arcade.TextureAtlasBase = None):
        """
        Create a new sprite list.

        Args:
            use_spatial_hash: Enable spatial hashing for collision optimization
            spatial_hash_cell_size: Size of spatial hash cells
            is_static: Whether sprites in this list move (enables optimizations)
            atlas: Custom texture atlas to use
        """
    
    def append(self, sprite: arcade.Sprite) -> None:
        """Add a sprite to the list."""
    
    def remove(self, sprite: arcade.Sprite) -> None:
        """Remove a sprite from the list."""
    
    def insert(self, index: int, sprite: arcade.Sprite) -> None:
        """Insert a sprite at a specific index."""
    
    def extend(self, sprites: list[arcade.Sprite]) -> None:
        """Add multiple sprites to the list."""
    
    def clear(self) -> None:
        """Remove all sprites from the list."""
    
    def update(self) -> None:
        """Update all sprites in the list."""
    
    def update_animation(self, delta_time: float = 1/60) -> None:
        """Update animations for all sprites in the list."""
    
    def on_update(self, delta_time: float = 1/60) -> None:
        """Override this method for custom update logic."""
    
    def draw(self, *, filter=None, pixelated=None, blend_function=None) -> None:
        """Draw all sprites in the list using batch rendering."""
    
    def draw_hit_boxes(self, color: arcade.types.Color = arcade.color.BLACK, line_thickness: float = 1) -> None:
        """Draw hit boxes for all sprites (debugging)."""
    
    def move(self, change_x: float, change_y: float) -> None:
        """Move all sprites in the list by the specified offset."""
    
    # List-like operations
    def __len__(self) -> int:
        """Get the number of sprites in the list."""
    
    def __getitem__(self, index: int) -> arcade.Sprite:
        """Get a sprite by index."""
    
    def __iter__(self):
        """Iterate over sprites in the list."""
    
    def __contains__(self, sprite: arcade.Sprite) -> bool:
        """Check if a sprite is in the list."""

class SpriteSequence:
    """
    Sequence interface for sprite lists with additional functionality.
    """
    def __init__(self):
        """Create a new sprite sequence."""
    
    def pop(self, index: int = -1) -> arcade.Sprite:
        """Remove and return sprite at index."""
    
    def reverse(self) -> None:
        """Reverse the order of sprites."""
    
    def shuffle(self) -> None:
        """Randomly shuffle the sprites."""

Spatial Indexing

Spatial data structures for optimizing collision detection and spatial queries.

class SpatialHash:
    """
    Spatial hash grid for efficient collision detection and spatial queries.
    """
    def __init__(self, cell_size: int = 128):
        """
        Create a spatial hash.

        Args:
            cell_size: Size of each hash cell in pixels
        """
    
    def insert_object_for_box(self, new_object: arcade.Sprite) -> None:
        """Insert a sprite into the spatial hash."""
    
    def remove_object(self, sprite_to_remove: arcade.Sprite) -> None:
        """Remove a sprite from the spatial hash."""
    
    def get_objects_for_box(self, check_object: arcade.Sprite) -> list[arcade.Sprite]:
        """Get all objects that might collide with the given sprite."""
    
    def reset(self) -> None:
        """Clear all objects from the spatial hash."""

Animation System

Classes for managing texture-based sprite animations.

class TextureAnimation:
    """
    Container for managing a sequence of animation frames.
    """
    def __init__(self, keyframes: list[arcade.TextureKeyframe] = None):
        """
        Create a texture animation.

        Args:
            keyframes: List of animation keyframes
        """
    
    keyframes: list[arcade.TextureKeyframe]
    
    def add_keyframe(self, keyframe: arcade.TextureKeyframe) -> None:
        """Add a keyframe to the animation."""

class TextureKeyframe:
    """
    Single frame in a texture animation with timing information.
    """
    def __init__(self, texture: arcade.Texture, duration: float = 1.0):
        """
        Create an animation keyframe.

        Args:
            texture: Texture to display during this frame
            duration: Duration to display this frame (in seconds or frame counts)
        """
    
    texture: arcade.Texture
    duration: float

def load_animated_gif(filename: str, scale: float = 1) -> arcade.TextureAnimationSprite:
    """
    Load an animated GIF file as an animated sprite.

    Args:
        filename: Path to GIF file
        scale: Scale factor for the sprite

    Returns:
        TextureAnimationSprite with frames from the GIF
    """

Physics Integration

Mixins and types for integrating sprites with physics engines.

class PymunkMixin:
    """
    Mixin class for adding Pymunk physics integration to sprites.
    """
    pymunk_shape: object  # pymunk.Shape
    pymunk_body: object   # pymunk.Body
    
    def pymunk_moved(self, physics_engine: arcade.PymunkPhysicsEngine, dx: float, dy: float, d_angle: float) -> None:
        """Called when the physics engine moves the sprite."""

# Type alias for sprites with Pymunk physics
PyMunk = arcade.Sprite  # Sprite with PymunkMixin

Collision Detection

Comprehensive collision detection functions for sprite interactions.

def check_for_collision(sprite1: arcade.Sprite, sprite2: arcade.Sprite) -> bool:
    """
    Check if two sprites are colliding.

    Args:
        sprite1: First sprite
        sprite2: Second sprite

    Returns:
        True if sprites are colliding, False otherwise
    """

def check_for_collision_with_list(sprite: arcade.Sprite, sprite_list: arcade.SpriteList) -> list[arcade.Sprite]:
    """
    Check if a sprite collides with any sprites in a list.

    Args:
        sprite: Sprite to check
        sprite_list: List of sprites to check against

    Returns:
        List of sprites that are colliding with the input sprite
    """

def check_for_collision_with_lists(sprite: arcade.Sprite, sprite_lists: list[arcade.SpriteList]) -> list[arcade.Sprite]:
    """
    Check if a sprite collides with sprites in multiple lists.

    Args:
        sprite: Sprite to check
        sprite_lists: List of sprite lists to check against

    Returns:
        List of sprites that are colliding with the input sprite
    """

def get_closest_sprite(sprite: arcade.Sprite, sprite_list: arcade.SpriteList) -> tuple[arcade.Sprite, float]:
    """
    Find the closest sprite in a list to the given sprite.

    Args:
        sprite: Reference sprite
        sprite_list: List of sprites to search

    Returns:
        Tuple of (closest_sprite, distance) or (None, None) if list is empty
    """

def get_distance_between_sprites(sprite1: arcade.Sprite, sprite2: arcade.Sprite) -> float:
    """
    Calculate the distance between two sprites.

    Args:
        sprite1: First sprite
        sprite2: Second sprite

    Returns:
        Distance between sprite centers in pixels
    """

def get_sprites_at_point(point: tuple[float, float], sprite_list: arcade.SpriteList) -> list[arcade.Sprite]:
    """
    Get all sprites that contain a specific point.

    Args:
        point: (x, y) coordinate tuple
        sprite_list: List of sprites to check

    Returns:
        List of sprites containing the point
    """

def get_sprites_at_exact_point(point: tuple[float, float], sprite_list: arcade.SpriteList) -> list[arcade.Sprite]:
    """
    Get sprites at an exact point (no hit box checking).

    Args:
        point: (x, y) coordinate tuple
        sprite_list: List of sprites to check

    Returns:
        List of sprites at the exact point
    """

def get_sprites_in_rect(rect: arcade.types.Rect, sprite_list: arcade.SpriteList) -> list[arcade.Sprite]:
    """
    Get all sprites within a rectangular area.

    Args:
        rect: Rectangle to check (x, y, width, height)
        sprite_list: List of sprites to check

    Returns:
        List of sprites within the rectangle
    """

Sprite Constants and Types

Direction constants and type definitions for sprite system.

# Direction constants for sprite facing
FACE_LEFT: str = "left"
FACE_RIGHT: str = "right"
FACE_UP: str = "up"
FACE_DOWN: str = "down"

# Type definitions
SpriteType = arcade.Sprite  # Base sprite type
SpriteType_co = arcade.Sprite  # Covariant sprite type (for type hints)

Usage Examples

Basic Sprite Creation and Management

import arcade

class GameView(arcade.View):
    def __init__(self):
        super().__init__()
        
        # Create sprite lists
        self.player_list = arcade.SpriteList()
        self.enemy_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()
        
    def setup(self):
        # Create player sprite
        self.player = arcade.Sprite(":resources:images/space_shooter/meteorGrey_med1.png", 0.5)
        self.player.center_x = 400
        self.player.center_y = 300
        self.player_list.append(self.player)
        
        # Create enemy sprites
        for i in range(5):
            enemy = arcade.Sprite(":resources:images/space_shooter/meteorGrey_med2.png", 0.3)
            enemy.center_x = 100 + i * 150
            enemy.center_y = 500
            enemy.change_y = -2
            self.enemy_list.append(enemy)
        
        # Create collectible coins
        for i in range(10):
            coin = arcade.SpriteCircle(15, arcade.color.YELLOW)
            coin.center_x = 50 + i * 70
            coin.center_y = 100
            self.coin_list.append(coin)
    
    def on_update(self, delta_time):
        # Update all sprites
        self.player_list.update()
        self.enemy_list.update()
        
        # Check collisions
        hit_list = arcade.check_for_collision_with_list(self.player, self.coin_list)
        for coin in hit_list:
            coin.remove_from_sprite_lists()
        
        # Check enemy collisions
        if arcade.check_for_collision_with_list(self.player, self.enemy_list):
            print("Player hit by enemy!")
    
    def on_draw(self):
        self.clear()
        self.player_list.draw()
        self.enemy_list.draw()
        self.coin_list.draw()

Animated Sprite Example

import arcade

class AnimatedPlayer(arcade.AnimatedWalkingSprite):
    def __init__(self):
        super().__init__(scale=0.5)
        
        # Load walking animations
        self.walk_right_textures = []
        for i in range(8):
            texture = arcade.load_texture(f":resources:images/animated_characters/female_person/femalePerson_walk{i}.png")
            self.walk_right_textures.append(texture)
        
        # Mirror for left walking
        self.walk_left_textures = []
        for texture in self.walk_right_textures:
            self.walk_left_textures.append(texture.texture.flip_horizontally())
        
        # Set initial texture
        self.texture = self.walk_right_textures[0]
    
    def update_animation(self, delta_time: float = 1/60):
        # Update animation based on movement
        if self.change_x > 0:
            self.texture = self.walk_right_textures[int(self.cur_texture_index)]
        elif self.change_x < 0:
            self.texture = self.walk_left_textures[int(self.cur_texture_index)]
        
        # Advance animation frame
        if abs(self.change_x) > 0:
            self.cur_texture_index += 0.1
            if self.cur_texture_index >= len(self.walk_right_textures):
                self.cur_texture_index = 0

class GameView(arcade.View):
    def setup(self):
        self.player_list = arcade.SpriteList()
        self.player = AnimatedPlayer()
        self.player.center_x = 400
        self.player.center_y = 300
        self.player_list.append(self.player)
    
    def on_update(self, delta_time):
        self.player_list.update()
        self.player_list.update_animation(delta_time)
    
    def on_key_press(self, key, modifiers):
        if key == arcade.key.LEFT:
            self.player.change_x = -5
        elif key == arcade.key.RIGHT:
            self.player.change_x = 5
    
    def on_key_release(self, key, modifiers):
        if key in (arcade.key.LEFT, arcade.key.RIGHT):
            self.player.change_x = 0

Install with Tessl CLI

npx tessl i tessl/pypi-arcade

docs

camera-system.md

core-graphics.md

gui-framework.md

index.md

math-utilities.md

physics-engines.md

sound-system.md

specialized-features.md

sprite-system.md

texture-management.md

window-management.md

tile.json