Source code for rubato.structure.gameobject.sprites.spritesheet

"""
Utility class for loading spritesheets.
"""
import os

from . import Animation
from .... import Vector, get_path, Surface


[docs]class Spritesheet: """ A spritesheet from the filesystem. Args: path: The relative path to the spritesheet. sprite_size: The size of each sprite in the spritesheet. Defaults to (32, 32). grid_size: The size of the grid of sprites in the spritesheet. Set to None to automatically determine the grid size. Defaults to None. Raises: IndexError: If user does not load the entire sheet. """ def __init__( self, path: str, sprite_size: Vector | tuple[float, float] = (32, 32), grid_size: Vector | tuple[float, float] | None = None ): self._sprite_size: tuple[int, int] = (int(sprite_size[0]), int(sprite_size[1])) self._sheet = Surface.from_file(path) self._sprites: list[list[Surface]] = [] if not grid_size: self._grid: tuple[int, int] = (self._sheet.size_scaled() / self._sprite_size).tuple_int() else: self._grid: tuple[int, int] = (int(grid_size[0]), int(grid_size[1])) if Vector(*self._sprite_size) * self._grid != self._sheet.size_scaled(): raise IndexError("Sprite and grid size do not match given spritesheet size.") for y in range(0, self._grid[1] * self._sprite_size[1], self._sprite_size[1]): self._sprites.append([]) for x in range(0, self._grid[0] * self._sprite_size[0], self._sprite_size[0]): surface = Surface(*self._sprite_size) surface._blit( self._sheet, (x, y, self._sprite_size[0], self._sprite_size[1]), ) self._sprites[y // self._sprite_size[1]].append(surface) @property def grid_size(self) -> Vector: """The size of the spritesheet grid (readonly).""" return Vector(*self._grid) @property def sprite_size(self) -> Vector: """The size of each sprite (readonly).""" return Vector(*self._sprite_size) @property def sheet(self) -> Surface: """The actual spritesheet sprite (readonly).""" return self._sheet @property def sprites(self) -> list[list[Surface]]: """The list of all the sprites as sprites (readonly).""" return self._sprites @property def end(self): """ The end indexes of the Spritesheet as a vector. Example: You can use :code:`spritesheet.get(*spritesheet.end)` to get the final Sprite """ return self.grid_size - Vector.one()
[docs] def get(self, x: int, y: int) -> Surface: """ Gets the Sprite at the corresponding grid coordinate of the spritesheet. Args: x: The x grid coordinate. y: The y grid coordinate. Raises: IndexError: One or both of the coordinates are out of range of the spritesheet's size. Returns: The Sprite at the corresponding coordinate. """ if x >= self.grid_size.x or y >= self.grid_size.y: raise IndexError(f"The coordinates ({x}, {y}) are out of range of the spritesheet.") return self.sprites[y][x].clone()
[docs] @staticmethod def from_folder( path: str, sprite_size: Vector | tuple[float, float], default_state: str | None = None, recursive: bool = True ) -> Animation: """ Creates an Animation from a folder of spritesheets. Directory must be comprised solely of spritesheets. Added alphabetically. Default is the first sheet loaded. Args: path: The relative path to the folder you wish to import sprite_size: The size of a single sprite in your spritesheet, should be the same in all imported sheets. default_state: Sets the default state of the animation. recursive: Whether it will import an animation shallowly or recursively. Defaults to True. Returns: Animation: the animation loaded from the folder of spritesheets """ anim = Animation() path = get_path(path) if not recursive: _, _, files = next(os.walk(path)) # walk to directory path and ignore name and subdirectories files.sort() for sprite_path in files: path_to_spritesheet = os.path.join(path, sprite_path) sprite_sheet = Spritesheet( path=path_to_spritesheet, sprite_size=sprite_size, ) anim.add_spritesheet(sprite_path.split(".")[0], sprite_sheet, to_coord=sprite_sheet.end) else: for _, _, files in os.walk(path): # walk to directory path and ignore name and subdirectories files.sort() for sprite_path in files: path_to_spritesheet = os.path.join(path, sprite_path) sprite_sheet = Spritesheet( path=path_to_spritesheet, sprite_size=sprite_size, ) anim.add_spritesheet(sprite_path.split(".")[0], sprite_sheet, to_coord=sprite_sheet.end) if default_state: anim.default_state = default_state anim.current_state = default_state anim.reset() return anim