How do I use sprite sheets in Pygame? [duplicate]
Asked Answered
B

2

9

The only way I know how to make an animation is by using individual images (as in 1 image per file). I got a sprite sheet but I don't want to spend the time cropping each individual sprite out.

I am using Python 3.2.

Broek answered 20/11, 2013 at 23:39 Comment(3)
there is a nice spritesheet class that is great imho(and easy to understand) ... pygame.org/wiki/SpritesheetKeystone
Post some of your code that's giving you problems? Also some more explanation what you're trying to do would be good (personally, I've got absolutely no idea as to what a sprite sheet is).Liegnitz
In the future, you might want to try Google, or the documentation. Searching either Google or the pygame wiki for "pygame sprite sheet", or your entire question title, turns up the link Joran and I found, as the first hit. Doing that would avoid the need for you to write those two extra paragraphs. And Google can answer in 0.19 seconds instead of taking 3 minutes like a human. Plus, we may end up with your SO question beating the more useful wiki page for future searchers, slowing everyone down.Filbert
F
6

It really isn't very hard to do… but the best sample code I found in a quick search is also a usable library that does the work for you: spritesheet, right from the pygame wiki.

So, you can start off by just using that. I'd give you an example tailored to your use case, but you haven't given us any idea what your code looks like or what you want to do, so I can't possibly give you anything better than is already on that page, so:

import spritesheet
...
ss = spritesheet.spritesheet('somespritesheet.png')
# Sprite is 16x16 pixels at location 0,0 in the file...
image = ss.image_at((0, 0, 16, 16))
images = []
# Load two images into an array, their transparent bit is (255, 255, 255)
images = ss.images_at((0, 0, 16, 16),(17, 0, 16,16), colorkey=(255, 255, 255))
…

Meanwhile, you can read the (very simple) code in that spritesheet class to understand how it works.

Filbert answered 20/11, 2013 at 23:42 Comment(5)
Sorry if this is a really dumb question, but do you know how to find out where a sprite in on a sprite sheet or do I just have to mess around with the values. Like do I have to find the values in GIMP or something?Broek
The image parts in an animation sprite sheet should be of fixed size. All you have to do is divide the resolution of sheet according to the number of sprites in it. If there are too many sprites, just use a simple loop for parsingHighflier
sometimes you need to tweek itKeystone
@ZaidSaeed: For a sprite sheet where everything is the same size, it's easy: Just divide the size of the sheet by the number of sprites (in each direction). Just be aware that a few sprite sheets have spacing between the sprites—e.g., 8 16x16 sprites per row, 1-pixel border between sprites, that's 8*16+1*7=135, and if you just divide 135/8 you'll get 16.875, when you wanted 17.Filbert
@ZaidSaeed: For a sprite sheet with different-sized sprites, there's really no automated way to figure out the boundaries; you have to do it by eye, and write down the values yourself in GIMP. There are a few sprite sheets that have borders in a color not used anywhere else on the sheet, which in theory is automatable, but the code isn't too simple…Filbert
N
0

I use this

from pathlib import Path
from typing import List, Tuple, Union
import pygame

class Spritesheet:
    def __init__(self, filepath: Path, sprite_size: Tuple[int, int], spacing: Tuple[int, int] = (0, 0), scale: Tuple[int, int] = None) -> None:
        """Initialize the spritesheet.

        Args:
            filepath (Path): Path to the spritesheet image file.
            sprite_size (Tuple[int, int]): Width and height of each sprite in the sheet.
            spacing (Tuple[int, int], optional): Spacing between each sprite (row spacing, column spacing). Defaults to (0, 0).
            scale (Tuple[int, int], optional): Rescale each sprite to the given size. Defaults to None.
        """
        self._sheet = pygame.image.load(filepath).convert_alpha()
        self._sprite_size = sprite_size
        self._spacing = spacing
        self._scale = scale

    def get_sprite(self, loc: Tuple[int, int], colorkey: Union[pygame.Color, int, None] = None) -> pygame.Surface:
        """Load a specific sprite from the spritesheet.

        Args:
            loc (Tuple[int, int]): Location of the sprite in the sheet (row, column).
            colorkey (Union[pygame.Color, int, None], optional): Color to be treated as transparent. Defaults to None.

        Returns:
            pygame.Surface: The sprite image.
        """
        x = loc[1] * (self._sprite_size[0] + self._spacing[0])
        y = loc[0] * (self._sprite_size[1] + self._spacing[1])

        rect = pygame.Rect(x, y, *self._sprite_size)
        image = pygame.Surface(self._sprite_size, pygame.SRCALPHA).convert_alpha()
        image.blit(self._sheet, (0, 0), rect)

        if colorkey is not None:
            if colorkey == -1:
                colorkey = image.get_at((0, 0))
            image.set_colorkey(colorkey, pygame.RLEACCEL)

        if self._scale:
            image = pygame.transform.scale(image, self._scale)
        
        return image

    def get_sprites(self, locs: List[Tuple[int, int]], colorkey: Union[pygame.Color, int, None] = None) -> List[pygame.Surface]:
        """Load multiple sprites from the spritesheet.

        Args:
            locs (List[Tuple[int, int]]): List of locations of the sprites in the sheet (row, column).
            colorkey (Union[pygame.Color, int, None], optional): Color to be treated as transparent. Defaults to None.

        Returns:
            List[pygame.Surface]: List of sprite images.
        """
        return [self.get_sprite(loc, colorkey) for loc in locs]

You can use it in this way:

spritesheet = Spritesheet("MySprite.png")

sprite_1 = spritesheet.get_sprite((1, 1)) # Gets sprite in location of (1, 1) from top left corner
sprite_2 = spritesheet.get_sprite((5, 3)) # Gets sprite in location of (5, 3) considering that the starting number is (0, 0)
Nappie answered 23/6, 2024 at 23:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.