Source code for arcade.texture.spritesheet

from PIL import Image
from pathlib import Path
from typing import Union, Tuple, Optional, List, TYPE_CHECKING

# from arcade import Texture
from arcade.types import Rect
from .texture import Texture

if TYPE_CHECKING:
    from arcade.hitbox import HitBoxAlgorithm


[docs] class SpriteSheet: """ Class to hold a sprite sheet. A sprite sheet is a single image that contains multiple textures. Textures can be created from the sprite sheet by cropping out sections of the image. This is only a utility class. It does not have any special functionality :param path: Path to the file to load. :param image: PIL image to use. """ def __init__( self, path: Optional[Union[str, Path]] = None, image: Optional[Image.Image] = None, ): from arcade.resources import resolve self._path = None if path: self._path = resolve(path) self._image = Image.open(self._path).convert("RGBA") elif image: self._image = image else: raise ValueError("Must provide either path or image") self._flip_flags = (False, False)
[docs] @classmethod def from_image(cls, image: Image.Image): """ Create a sprite sheet from a PIL image. :param image: PIL image to use. """ return cls(image=image)
@property def image(self) -> Image.Image: """ Get or set the PIL image for this sprite sheet. """ return self._image @image.setter def image(self, image: Image.Image): self._image = image @property def path(self) -> Optional[Path]: """ The path to the sprite sheet. :return: The path. """ return self._path @property def flip_flags(self) -> Tuple[bool, bool]: """ Query the orientation of the sprite sheet. This can be used to determine if the sprite sheet needs to be flipped. Default values are ``(False, False)``. Will be modified when :py:meth:`flip_left_right` or :py:meth:`flip_top_bottom` is called. :return: Tuple of booleans ``(flip_left_right, flip_top_bottom)``. """ return self._flip_flags
[docs] def flip_left_right(self) -> None: """ Flip the sprite sheet left/right. """ self._image = self._image.transpose(Image.FLIP_LEFT_RIGHT) self._flip_flags = (not self._flip_flags[0], self._flip_flags[1])
[docs] def flip_top_bottom(self): """ Flip the sprite sheet up/down. """ self._image = self._image.transpose(Image.FLIP_TOP_BOTTOM) self._flip_flags = (self._flip_flags[0], not self._flip_flags[1])
[docs] def crop(self, area: Rect): """ Crop a texture from the sprite sheet. :param area: Area to crop ``(x, y, width, height)`` """ pass
[docs] def crop_sections(self, sections: List[Rect]): """ Crop multiple textures from the sprite sheet by specifying a list of areas to crop. :param sections: List of areas to crop ``[(x, y, width, height), ...]`` """ pass
[docs] def crop_grid( self, size: Tuple[int, int], columns: int, count: int, margin: Rect = (0, 0, 0, 0), hit_box_algorithm: Optional["HitBoxAlgorithm"] = None, ) -> List[Texture]: """ Crop a grid of textures from the sprite sheet. :param size: Size of each texture ``(width, height)`` :param columns: Number of columns in the grid :param count: Number of textures to crop :param margin: The margin around each texture ``(left, right, bottom, top)`` :param hit_box_algorithm: Hit box algorithm to use for the textures. """ textures = [] width, height = size left, right, bottom, top = margin for sprite_no in range(count): row = sprite_no // columns column = sprite_no % columns x = (width + left + right) * column y = (height + top + bottom) * row im = self.image.crop((x, y, x + width, y + height)) texture = Texture(im, hit_box_algorithm=hit_box_algorithm) texture.file_path = self._path texture.crop_values = x, y, width, height textures.append(texture) return textures