1
votes

So I've been testing out this code, I found a tutorial on how I can add spritesheets in pygame and decided to try this one: https://www.spriters-resource.com/3ds/dragonballzextremebutoden/sheet/67257/

I did as the video said and counted the columns and rows, this is my code:

pygame.init()
CLOCK = pygame.time.Clock()
DS = pygame.display.set_mode((W, H))
FPS = 60

class spritesheet:
    def __init__(self, filename, cols, rows):
        self.sheet = pygame.image.load(filename).convert_alpha()

        self.cols = cols
        self.rows = rows
        self.totalCellCount = cols * rows

        self.rect = self.sheet.get_rect()
        w = self.cellWidth = self.rect.width / cols
        h = self.cellHeight = self.rect.height / rows
        hw, hh = self.cellCenter = (w / 2, h / 2)

        self.cells = list([(index % cols * w, index / cols * h, w, h) for index in range(self.totalCellCount)])
        self.handle = list([
            (0,0), (-hw, 0), (-w, 0),
            (0, -hh), (-hw, -hh), (-w, -hh),
            (0, -h), (-hw, -h), (-w, -h),])

    def draw(self, surface, cellIndex, x, y, handle = 0):
        surface.blit(self.sheet, 
        (x + self.handle[handle][0], y + self.handle[handle][1],
         self.cells[cellIndex][2], self.cells[cellIndex][3]))


s = spritesheet('Number18.png', 58, 6)

CENTER_HANDLE = 6

Index = 0

#mainloop
run = True
while run:

    s.draw(DS, Index % s.totalCellCount, HW, HH, CENTER_HANDLE)
    Index +=1

    #pygame.draw.circle(DS, WHITE, (HW, HW), 20, 10)
    DS.blit(bg,(0,0))

    pygame.display.update()
    CLOCK.tick(FPS)
    DS.fill(BLACK)

The line s = spritesheet("Number18.png", 58, 6) has the numbers 58, 6 which are basically the number of rows and columns I counted on this spritesheet block, but I'm getting problems such as the pygame window on "not responding", the image does not load up and I can't move the pygame screen.

1
"the image does not load up" are you sure that the image is located in the working directory of the application? Use an absolute path to the image for debug reasons. - Rabbid76
Can you try printing self.sheet after it is assigned a value? Do you get any exception anywhere? - Sameer Naik
Is the issue solved? - Rabbid76

1 Answers

1
votes

I'm getting problems such as the pygame window on "not responding", [...]

The fist thing what you've to do is to add en event loop to the main loop of the application.
pygame.event removes a pending event message from the queue and returns it. At least you should handle the QUIT event. Set the value of control variable for the main loop False:

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

The tiles in the sprite sheet don't have equal size. Limit the cells list to some parts of the sheet which have equal size.
Try the following:

class spritesheet:
    def __init__(self, filename, py, tw, th, tiles):
        self.sheet = pygame.image.load(filename).convert_alpha()

        self.py = py
        self.tw = tw
        self.th = th
        self.totalCellCount = tiles

        self.rect = self.sheet.get_rect()
        w, h = tw, th
        hw, hh = self.cellCenter = (w / 2, h / 2)

        self.cells = [(1+i*tw, self.py, tw-1, th-1) for i in range(tiles)]
        self.handle = list([
            (0,0), (-hw, 0), (-w, 0),
            (0, -hh), (-hw, -hh), (-w, -hh),
            (0, -h), (-hw, -h), (-w, -h),])
s = spritesheet('Number18.png', 1085, 80, 134, 8)

[...] the image does not load up [...]

Make sure that the image is located int the working directory of the application.
If you want to draw a sub-image of a spritsheet then you've to set the area parameter (3rd parameter) of pygame.Surface.blit to the rectangle area of the sub-image:

def draw(self, surface, cellIndex, x, y, handle = 0):
    hdl = self.handle[handle]
    surface.blit(self.sheet, (x + hdl[0], y + hdl[1]), area=self.cells[cellIndex])

[...] I can't move [...]

You have to change the position of the sprite. Handle the KEYDOWN event. Store the position of the sprite (px, py). Change the position when the K_UP, K_DOWN, K_LEFT or K_RIGHT key is pressed:

run = True
px, py, speed = HW, HH, 10
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                py -= speed
            elif event.key == pygame.K_DOWN:
                py += speed
            elif event.key == pygame.K_LEFT:
                px -= speed
            elif event.key == pygame.K_RIGHT:
                px += speed

Minimal Sprite Sheet example:

import os
import pygame

class SpriteSheet:
    def __init__(self, filename, px, py, tw, th, m, tiles, color_key = None):
        self.sheet = pygame.image.load(filename)
        if color_key:
            self.sheet = self.sheet.convert()
            self.sheet.set_colorkey(color_key)
        else:
            self.sheet = self.sheet.convert_alpha()
        self.cells = [(px + tw * i, py, tw-m, th) for i in range(tiles)]
        self.index = 0

    def update(self):
        self.tile_rect = self.cells[self.index % len(self.cells)]
        self.index += 1

    def draw(self, surface, x, y):
        rect = pygame.Rect(self.tile_rect)
        rect.center = (x, y) 
        surface.blit(self.sheet, rect, self.tile_rect)

pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()

sprite_sheet = SpriteSheet('awesomepossum sheet.bmp', 18, 580, 64, 66, 0, 6, (0, 128, 0))

run = True
while run:
    clock.tick(10)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    sprite_sheet.update()

    window.fill(0)
    sprite_sheet.draw(window, *window.get_rect().center)
    pygame.display.update()
    
pygame.quit()
exit()

Sprite sheet form OpenGameArt.org: