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

texture-management.mddocs/

Texture Management

Comprehensive texture loading, caching, atlas management, procedural texture generation, and sprite sheet handling for efficient graphics resource management and optimal rendering performance.

Capabilities

Core Texture Classes

Base texture classes for managing image data and rendering properties.

class Texture:
    """
    Main texture class for managing image data, rendering properties, and GPU resources.
    Textures can be loaded from files, created programmatically, or extracted from sprite sheets.
    """
    def __init__(self, image: PIL.Image.Image, name: str = None, hit_box_algorithm: str = "Simple",
                 hit_box_detail: float = 4.5, hit_box_points: list[tuple[float, float]] = None):
        """
        Create a texture from a PIL Image.

        Args:
            image: PIL Image object containing texture data
            name: Optional name for the texture (used for caching/debugging)
            hit_box_algorithm: Algorithm for calculating hit box ("Simple", "Detailed", or "None")
            hit_box_detail: Detail level for "Detailed" hit box algorithm
            hit_box_points: Pre-calculated hit box points
        """

    # Properties
    name: str
    width: int
    height: int
    image: PIL.Image.Image
    hit_box_points: list[tuple[float, float]]
    
    # Atlas properties
    atlas: arcade.TextureAtlasBase
    atlas_name: str
    
    def create_empty(name: str, size: tuple[int, int], color: tuple[int, int, int, int] = (0, 0, 0, 0)) -> arcade.Texture:
        """
        Create an empty texture with specified size and color.

        Args:
            name: Name for the texture
            size: (width, height) in pixels
            color: RGBA color tuple (0-255)

        Returns:
            New Texture instance
        """
    
    def create_filled(name: str, size: tuple[int, int], color: tuple[int, int, int, int]) -> arcade.Texture:
        """
        Create a texture filled with a solid color.

        Args:
            name: Name for the texture
            size: (width, height) in pixels
            color: RGBA color tuple (0-255)

        Returns:
            New Texture instance
        """
    
    def flip_horizontally(self) -> arcade.Texture:
        """
        Create a horizontally flipped version of this texture.

        Returns:
            New Texture instance with flipped image
        """
    
    def flip_vertically(self) -> arcade.Texture:
        """
        Create a vertically flipped version of this texture.

        Returns:
            New Texture instance with flipped image
        """
    
    def flip_diagonally(self) -> arcade.Texture:
        """
        Create a diagonally flipped version of this texture.

        Returns:
            New Texture instance with flipped image
        """
    
    def rotate_90(self) -> arcade.Texture:
        """
        Create a texture rotated 90 degrees clockwise.

        Returns:
            New Texture instance with rotated image
        """
    
    def crop(self, x: int, y: int, width: int, height: int) -> arcade.Texture:
        """
        Create a cropped version of this texture.

        Args:
            x: Left coordinate of crop area
            y: Bottom coordinate of crop area
            width: Width of crop area
            height: Height of crop area

        Returns:
            New Texture instance with cropped image
        """
    
    def resize(self, new_size: tuple[int, int], resample: int = PIL.Image.LANCZOS) -> arcade.Texture:
        """
        Create a resized version of this texture.

        Args:
            new_size: (width, height) for resized texture
            resample: PIL resampling algorithm

        Returns:
            New Texture instance with resized image
        """

class TextureCacheManager:
    """
    Manages texture caching and memory usage to prevent duplicate texture loading
    and optimize GPU memory usage.
    """
    def __init__(self):
        """Create a texture cache manager."""
    
    def get_texture_by_name(self, name: str) -> arcade.Texture:
        """
        Get a cached texture by name.

        Args:
            name: Name of the texture to retrieve

        Returns:
            Cached Texture instance or None if not found
        """
    
    def put_texture(self, name: str, texture: arcade.Texture) -> None:
        """
        Store a texture in the cache.

        Args:
            name: Cache key for the texture
            texture: Texture instance to cache
        """
    
    def clear_cache(self) -> None:
        """Clear all cached textures from memory."""
    
    def get_cache_size(self) -> int:
        """
        Get the number of textures currently cached.

        Returns:
            Number of cached textures
        """

Texture Loading Functions

Functions for loading textures from files and resources with various options and transformations.

def load_texture(file_path: str, x: int = 0, y: int = 0, width: int = 0, height: int = 0,
                 flipped_horizontally: bool = False, flipped_vertically: bool = False,
                 flipped_diagonally: bool = False, can_cache: bool = True,
                 hit_box_algorithm: str = "Simple", hit_box_detail: float = 4.5) -> arcade.Texture:
    """
    Load a texture from a file with optional transformations and cropping.

    Args:
        file_path: Path to image file or resource handle (e.g., ":resources:images/...")
        x: X offset for cropping (pixels from left)
        y: Y offset for cropping (pixels from bottom)
        width: Width of crop area (0 = full width)
        height: Height of crop area (0 = full height)
        flipped_horizontally: Mirror texture horizontally
        flipped_vertically: Mirror texture vertically
        flipped_diagonally: Mirror texture diagonally
        can_cache: Whether this texture can be cached
        hit_box_algorithm: Hit box calculation method
        hit_box_detail: Detail level for detailed hit boxes

    Returns:
        Loaded Texture instance
    """

def load_image(file_path: str) -> PIL.Image.Image:
    """
    Load an image file as a PIL Image object.

    Args:
        file_path: Path to image file

    Returns:
        PIL Image object
    """

def load_spritesheet(file_path: str, sprite_width: int, sprite_height: int,
                    columns: int, count: int, margin: int = 0, spacing: int = 0) -> list[arcade.Texture]:
    """
    Load a sprite sheet and return individual sprites as textures.

    Args:
        file_path: Path to sprite sheet image
        sprite_width: Width of each sprite in pixels
        sprite_height: Height of each sprite in pixels
        columns: Number of columns in the sprite sheet
        count: Total number of sprites to load
        margin: Margin around the entire sprite sheet
        spacing: Spacing between individual sprites

    Returns:
        List of Texture instances, one for each sprite
    """

def get_default_texture() -> arcade.Texture:
    """
    Get the default fallback texture (used when texture loading fails).

    Returns:
        Default Texture instance (usually a colored square)
    """

def get_default_image() -> PIL.Image.Image:
    """
    Get the default fallback image.

    Returns:
        Default PIL Image object
    """

Procedural Texture Generation

Functions for creating textures programmatically with various shapes, patterns, and effects.

def make_circle_texture(diameter: int, color: arcade.types.Color, name: str = "circle") -> arcade.Texture:
    """
    Generate a circular texture with solid color.

    Args:
        diameter: Diameter of the circle in pixels
        color: Circle color as RGB or RGBA tuple (0-255)
        name: Name for the generated texture

    Returns:
        Generated Texture instance
    """

def make_soft_circle_texture(diameter: int, color: arcade.types.Color, 
                           center_alpha: int = 255, outer_alpha: int = 0,
                           name: str = "soft_circle") -> arcade.Texture:
    """
    Generate a circular texture with soft, gradient edges.

    Args:
        diameter: Diameter of the circle in pixels
        color: Base color as RGB tuple (0-255)
        center_alpha: Alpha value at circle center (0-255)
        outer_alpha: Alpha value at circle edge (0-255)
        name: Name for the generated texture

    Returns:
        Generated Texture instance with gradient alpha
    """

def make_soft_square_texture(size: int, color: arcade.types.Color,
                           center_alpha: int = 255, outer_alpha: int = 0,
                           name: str = "soft_square") -> arcade.Texture:
    """
    Generate a square texture with soft, gradient edges.

    Args:
        size: Size of the square in pixels
        color: Base color as RGB tuple (0-255)
        center_alpha: Alpha value at square center (0-255)
        outer_alpha: Alpha value at square edges (0-255)
        name: Name for the generated texture

    Returns:
        Generated Texture instance with gradient alpha
    """

Sprite Sheet Management

Classes and functions for working with sprite sheets and texture atlases.

class SpriteSheet:
    """
    Manages sprite sheets for extracting individual sprites and optimizing texture usage.
    """
    def __init__(self, file_path: str, sprite_width: int, sprite_height: int,
                 columns: int = None, rows: int = None, margin: int = 0, spacing: int = 0):
        """
        Create a sprite sheet manager.

        Args:
            file_path: Path to sprite sheet image file
            sprite_width: Width of each individual sprite
            sprite_height: Height of each individual sprite
            columns: Number of columns (auto-calculated if None)
            rows: Number of rows (auto-calculated if None)
            margin: Margin around the entire sheet
            spacing: Spacing between individual sprites
        """
    
    # Properties
    file_path: str
    sprite_width: int
    sprite_height: int
    columns: int
    rows: int
    margin: int
    spacing: int
    
    def get_texture(self, column: int, row: int) -> arcade.Texture:
        """
        Extract a single sprite texture from the sheet.

        Args:
            column: Column index (0-based)
            row: Row index (0-based)

        Returns:
            Texture for the sprite at the specified position
        """
    
    def get_textures(self, start_column: int = 0, start_row: int = 0,
                    end_column: int = None, end_row: int = None) -> list[arcade.Texture]:
        """
        Extract multiple sprite textures from a range.

        Args:
            start_column: Starting column (inclusive)
            start_row: Starting row (inclusive)
            end_column: Ending column (inclusive, None = last column)
            end_row: Ending row (inclusive, None = last row)

        Returns:
            List of Texture instances for the specified range
        """
    
    def get_texture_list(self) -> list[arcade.Texture]:
        """
        Get all sprites from the sheet as a list.

        Returns:
            List of all Texture instances in the sheet
        """

Texture Atlas System

Advanced texture management for optimizing GPU memory and rendering performance.

class DefaultTextureAtlas:
    """
    Default texture atlas implementation for batching textures into a single GPU texture
    to improve rendering performance and reduce GPU memory usage.
    """
    def __init__(self, size: tuple[int, int] = (2048, 2048), auto_resize: bool = True,
                 ctx: arcade.ArcadeContext = None):
        """
        Create a texture atlas.

        Args:
            size: (width, height) of the atlas texture in pixels
            auto_resize: Whether to automatically resize when full
            ctx: OpenGL context (uses current context if None)
        """
    
    # Properties
    size: tuple[int, int]
    auto_resize: bool
    ctx: arcade.ArcadeContext
    
    def add(self, texture: arcade.Texture) -> bool:
        """
        Add a texture to the atlas.

        Args:
            texture: Texture to add

        Returns:
            True if successfully added, False if atlas is full
        """
    
    def remove(self, texture: arcade.Texture) -> bool:
        """
        Remove a texture from the atlas.

        Args:
            texture: Texture to remove

        Returns:
            True if successfully removed, False if not found
        """
    
    def clear(self) -> None:
        """Remove all textures from the atlas."""
    
    def resize(self, new_size: tuple[int, int]) -> None:
        """
        Resize the atlas texture.

        Args:
            new_size: New (width, height) for the atlas
        """
    
    def get_texture_count(self) -> int:
        """
        Get the number of textures currently in the atlas.

        Returns:
            Number of textures in the atlas
        """
    
    def get_usage_percent(self) -> float:
        """
        Get the percentage of atlas space currently used.

        Returns:
            Usage percentage (0.0 to 100.0)
        """

class TextureAtlasBase:
    """
    Base class for texture atlas implementations.
    """
    def __init__(self):
        """Create base texture atlas."""
    
    def add(self, texture: arcade.Texture) -> bool:
        """Add a texture to the atlas."""
    
    def remove(self, texture: arcade.Texture) -> bool:
        """Remove a texture from the atlas."""
    
    def clear(self) -> None:
        """Clear all textures from the atlas."""

class AtlasRegion:
    """
    Represents a region within a texture atlas containing a specific texture.
    """
    def __init__(self, atlas: arcade.TextureAtlasBase, x: int, y: int, width: int, height: int):
        """
        Create an atlas region.

        Args:
            atlas: The texture atlas containing this region
            x: X coordinate within the atlas
            y: Y coordinate within the atlas
            width: Width of the region
            height: Height of the region
        """
    
    atlas: arcade.TextureAtlasBase
    x: int
    y: int
    width: int
    height: int

Usage Examples

Basic Texture Loading and Usage

import arcade

class TextureExample(arcade.Window):
    def __init__(self):
        super().__init__(800, 600, "Texture Example")
        
        self.texture_list = []
        self.sprite_list = arcade.SpriteList()
        
    def setup(self):
        # Load individual textures
        player_texture = arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png")
        
        # Load with transformations
        flipped_texture = arcade.load_texture(
            ":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png",
            flipped_horizontally=True
        )
        
        # Load cropped portion
        cropped_texture = arcade.load_texture(
            ":resources:images/tiles/grassMid.png",
            x=0, y=0, width=32, height=32
        )
        
        # Create sprites using loaded textures
        player = arcade.Sprite(texture=player_texture, scale=0.5)
        player.center_x = 200
        player.center_y = 300
        self.sprite_list.append(player)
        
        flipped_player = arcade.Sprite(texture=flipped_texture, scale=0.5)
        flipped_player.center_x = 400
        flipped_player.center_y = 300
        self.sprite_list.append(flipped_player)
        
        # Generate procedural textures
        circle_texture = arcade.make_circle_texture(50, arcade.color.RED)
        circle_sprite = arcade.Sprite(texture=circle_texture)
        circle_sprite.center_x = 600
        circle_sprite.center_y = 300
        self.sprite_list.append(circle_sprite)
        
        # Soft circle with gradient
        soft_texture = arcade.make_soft_circle_texture(80, arcade.color.BLUE, 255, 50)
        soft_sprite = arcade.Sprite(texture=soft_texture)
        soft_sprite.center_x = 200
        soft_sprite.center_y = 150
        self.sprite_list.append(soft_sprite)
    
    def on_draw(self):
        self.clear()
        self.sprite_list.draw()

def main():
    game = TextureExample()
    game.setup()
    arcade.run()

if __name__ == "__main__":
    main()

Sprite Sheet Animation

import arcade

class AnimationExample(arcade.Window):
    def __init__(self):
        super().__init__(800, 600, "Sprite Sheet Animation")
        
        self.player_list = arcade.SpriteList()
        self.walk_textures = []
        
    def setup(self):
        # Load walking animation frames from sprite sheet
        self.walk_textures = arcade.load_spritesheet(
            ":resources:images/animated_characters/female_adventurer/femaleAdventurer_walk.png",
            sprite_width=128,
            sprite_height=128, 
            columns=8,
            count=8
        )
        
        # Alternative: Load individual frames
        # self.walk_textures = []
        # for i in range(8):
        #     texture = arcade.load_texture(f":resources:images/animated_characters/female_adventurer/femaleAdventurer_walk{i}.png")
        #     self.walk_textures.append(texture)
        
        # Create animated player
        self.player = arcade.Sprite()
        self.player.center_x = 400
        self.player.center_y = 300
        self.player.scale = 0.5
        
        # Set initial texture
        self.player.texture = self.walk_textures[0]
        self.player_list.append(self.player)
        
        # Animation state
        self.current_frame = 0
        self.frame_timer = 0
        self.frame_duration = 0.1  # seconds per frame
        
    def on_draw(self):
        self.clear()
        self.player_list.draw()
        
        # Draw frame counter
        arcade.draw_text(f"Frame: {self.current_frame}", 10, 550, arcade.color.WHITE, 16)
        
    def on_update(self, delta_time):
        # Update animation
        self.frame_timer += delta_time
        
        if self.frame_timer >= self.frame_duration:
            self.frame_timer = 0
            self.current_frame = (self.current_frame + 1) % len(self.walk_textures)
            self.player.texture = self.walk_textures[self.current_frame]

def main():
    game = AnimationExample()
    game.setup()
    arcade.run()

if __name__ == "__main__":
    main()

Texture Atlas Management

import arcade

class AtlasExample(arcade.Window):
    def __init__(self):
        super().__init__(800, 600, "Texture Atlas Example")
        
        self.sprite_list = arcade.SpriteList(use_spatial_hash=True)
        self.atlas = None
        
    def setup(self):
        # Create texture atlas for optimal rendering
        self.atlas = arcade.DefaultTextureAtlas(size=(1024, 1024))
        
        # Load various textures
        textures = [
            arcade.load_texture(":resources:images/animated_characters/female_adventurer/femaleAdventurer_idle.png"),
            arcade.load_texture(":resources:images/animated_characters/male_adventurer/maleAdventurer_idle.png"),
            arcade.load_texture(":resources:images/enemies/bee.png"),
            arcade.load_texture(":resources:images/items/coinGold.png"),
        ]
        
        # Add textures to atlas
        for texture in textures:
            success = self.atlas.add(texture)
            print(f"Added texture '{texture.name}' to atlas: {success}")
        
        # Create sprites using atlas textures
        for i, texture in enumerate(textures):
            for j in range(10):
                sprite = arcade.Sprite(texture=texture, scale=0.3)
                sprite.center_x = 100 + (i * 150) + (j * 15)
                sprite.center_y = 300
                self.sprite_list.append(sprite)
        
        # Print atlas statistics
        print(f"Atlas usage: {self.atlas.get_usage_percent():.1f}%")
        print(f"Textures in atlas: {self.atlas.get_texture_count()}")
        
    def on_draw(self):
        self.clear()
        self.sprite_list.draw()
        
        # Draw atlas info
        if self.atlas:
            usage = self.atlas.get_usage_percent()
            texture_count = self.atlas.get_texture_count()
            arcade.draw_text(f"Atlas Usage: {usage:.1f}%", 10, 550, arcade.color.WHITE, 16)
            arcade.draw_text(f"Textures: {texture_count}", 10, 525, arcade.color.WHITE, 16)

def main():
    game = AtlasExample()
    game.setup()
    arcade.run()

if __name__ == "__main__":
    main()

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