Texture

SFML Texture object for sprite atlases and tile sheets.

Overview

A Texture loads an image file and divides it into a grid of sprites based on the specified tile dimensions. Textures are shared across Sprites, Grids, Entities, and TileLayers. McRogueFace caches textures internally, so loading the same image with the same tile size returns the same texture object.

Quick Reference

import mcrfpy

# Load a 16x16 tile sprite sheet
texture = mcrfpy.Texture("assets/sprites/dungeon.png", 16, 16)

# Check texture properties
print(f"Sprite size: {texture.sprite_width}x{texture.sprite_height}")
print(f"Sheet size: {texture.sheet_width}x{texture.sheet_height}")
print(f"Total sprites: {texture.sprite_count}")

# Use with Sprite
sprite = mcrfpy.Sprite(pos=(100, 100), texture=texture, sprite_index=0)

# Use with Grid
grid = mcrfpy.Grid(grid_size=(20, 15), texture=texture)

# Use with Entity
player = mcrfpy.Entity(grid_pos=(5, 5), texture=texture, sprite_index=84)

Constructor

mcrfpy.Texture(filename: str, sprite_width: int, sprite_height: int)
Parameter Type Description
filename str Path to image file (PNG, JPG, etc.)
sprite_width int Width of each sprite in pixels
sprite_height int Height of each sprite in pixels

Raises IOError if the image file cannot be loaded.

The constructor also accepts optional display_size and display_origin parameters: Texture(filename, sprite_width=0, sprite_height=0, display_size=None, display_origin=None).

Classmethods

  • Texture.from_bytes(data, width, height, sprite_width, sprite_height) — construct a texture from raw bytes.
  • Texture.composite(layers, sprite_width, sprite_height) — composite multiple layers into a new texture.
  • texture.hsl_shift(h, s, l) — instance method returning a NEW texture with a hue/saturation/lightness shift applied.

Properties

Property Type Access Description
source str read-only Path to the loaded image file
sprite_width int read-only Width of each sprite in pixels
sprite_height int read-only Height of each sprite in pixels
sheet_width int read-only Number of sprite columns (texture_width / sprite_width)
sheet_height int read-only Number of sprite rows
sprite_count int read-only Total number of sprites in the sheet

Sprite Index Calculation

Sprites are indexed left-to-right, top-to-bottom, starting from 0:

+----+----+----+----+
|  0 |  1 |  2 |  3 |
+----+----+----+----+
|  4 |  5 |  6 |  7 |
+----+----+----+----+
|  8 |  9 | 10 | 11 |
+----+----+----+----+

To calculate the index for a sprite at row r, column c:

columns = texture.sheet_width
index = r * columns + c

Examples

Basic Texture Loading

import mcrfpy

# Load a sprite sheet
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)

# Create sprites using different indices
floor = mcrfpy.Sprite(pos=(0, 0), texture=texture, sprite_index=0)
wall = mcrfpy.Sprite(pos=(16, 0), texture=texture, sprite_index=1)
player = mcrfpy.Sprite(pos=(32, 0), texture=texture, sprite_index=84)

Texture for Grid and Entities

# Load texture
texture = mcrfpy.Texture("assets/tiles.png", 16, 16)

# Create grid using texture
grid = mcrfpy.Grid(
    grid_size=(40, 30),
    texture=texture,
    pos=(0, 0),
    size=(640, 480)
)

# Set tile sprites via a TileLayer
layer = mcrfpy.TileLayer(name="floor", z_index=0, texture=texture)
grid.add_layer(layer)
layer.fill(0)  # Floor tile

# Add entity with same texture
player = mcrfpy.Entity(
    grid_pos=(5, 5),
    texture=texture,
    sprite_index=84  # Player sprite
)
grid.entities.append(player)

Texture Manager

class TextureManager:
    _textures = {}

    @classmethod
    def get(cls, name):
        """Get a preloaded texture by name."""
        return cls._textures.get(name)

    @classmethod
    def load(cls, name, path, tile_w, tile_h):
        """Load and register a texture."""
        cls._textures[name] = mcrfpy.Texture(path, tile_w, tile_h)
        return cls._textures[name]

    @classmethod
    def preload_all(cls):
        """Load all game textures."""
        cls.load("dungeon", "assets/dungeon.png", 16, 16)
        cls.load("characters", "assets/chars.png", 16, 16)
        cls.load("ui", "assets/ui.png", 8, 8)
        cls.load("effects", "assets/effects.png", 32, 32)

# Usage
TextureManager.preload_all()
dungeon_tex = TextureManager.get("dungeon")

Sprite Sheet Information

def print_texture_info(texture):
    """Display texture properties."""
    cols = texture.sheet_width
    rows = texture.sheet_height

    print(f"Source: {texture.source}")
    print(f"Sheet size: {texture.sheet_width}x{texture.sheet_height}")
    print(f"Sprite size: {texture.sprite_width}x{texture.sprite_height} pixels")
    print(f"Grid: {cols} columns x {rows} rows")
    print(f"Total sprites: {texture.sprite_count}")

texture = mcrfpy.Texture("assets/sprites.png", 16, 16)
print_texture_info(texture)

Animated Sprite Frames

class AnimatedSprite:
    def __init__(self, sprite, start_index, frame_count):
        self.sprite = sprite
        self.start_index = start_index
        self.frame_count = frame_count
        self.current_frame = 0
        self.frame_time = 0.1  # seconds per frame
        self.elapsed = 0

    def update(self, dt):
        self.elapsed += dt
        if self.elapsed >= self.frame_time:
            self.elapsed -= self.frame_time
            self.current_frame = (self.current_frame + 1) % self.frame_count
            self.sprite.sprite_index = self.start_index + self.current_frame

# Usage: Character walk animation (frames 0-3)
texture = mcrfpy.Texture("assets/character.png", 16, 16)
sprite = mcrfpy.Sprite(pos=(100, 100), texture=texture, sprite_index=0)
anim = AnimatedSprite(sprite, start_index=0, frame_count=4)

Different Tile Sizes

# Standard dungeon tiles
tiles_16 = mcrfpy.Texture("assets/tiles_16x16.png", 16, 16)

# Larger character sprites
chars_32 = mcrfpy.Texture("assets/characters_32x32.png", 32, 32)

# Small UI icons
icons_8 = mcrfpy.Texture("assets/icons_8x8.png", 8, 8)

# Non-square tiles (isometric)
iso_tiles = mcrfpy.Texture("assets/isometric.png", 64, 32)

Notes

  • Supported formats: PNG (recommended), JPG, BMP, TGA
  • PNG with transparency is recommended for sprites
  • Textures are cached internally - same file + tile size returns same object
  • Large textures may impact memory and performance
  • Sprite indices are 0-based and wrap left-to-right, top-to-bottom