Subsurface ValueError: 'subsurface rectangle outside surface area'

Question:

I am trying to get the images of a spritesheet and adding them to an animation dictionary.

It seems that I am stupid or don’t understand how subsurfaces work because I really don’t understand why I get this error:

ValueError: subsurface rectangle outside surface area

Here is my simplified code:

import pygame as pg
pg.init()

animations = {"animation": []}
sprite_frame_number = 18

img = pg.Surface((1440, 80))  # that would be the sprite sheet
size = [int(img.get_width() / sprite_frame_number), img.get_height()]  # so in this case size = [80,80]

for x in range(sprite_frame_number):
    frame_location = [size[0] * x, 0]  # so starting with 0, x moves with each iteration 80 pxl to the right
    img_rect = pg.Rect(frame_location, size)
    
    try:  # i used this to see when it starts to crash
        img = img.subsurface(img_rect)
    except ValueError:
        print(x)        
    
    animations["animation"].append(img)
print(animations)

The ValueError prints for x ‘1’ to ’17’. So it crashes after creating one subsurface, right?

The print(animations) shows with {'idle': [<Surface(80x80x32 SW)>,...] that there are 18 surfaces in my dictionary.

First how is it possible that there is a created rect that is outside the surface area and second why are there 18 surfaces in the dict when it says it is not possible?
I am confused.

Asked By: Loopin94

||

Answers:

The problem is that you use the same variable, img, for both the original image and the subsurface. The first time, everything is still working, because the surface stored in the imgvariable is still the original surface. The second however, this surface is replaced by the first subsurface. This surface is not as big as the original surface, causing the rectangle to be outside of the surface area.

The way to fix this is creating a new variable to store the subsurface instead of img. This can be any other name you want, but I would go for new_img:

import pygame as pg
pg.init()

animations = {"animation": []}
sprite_frame_number = 18

img = pg.Surface((1440, 80))  # that would be the sprite sheet
size = [int(img.get_width() / sprite_frame_number), img.get_height()]  # so in this case size = [80,80]

for x in range(sprite_frame_number):
    frame_location = [size[0] * x, 0]  # so starting with 0, x moves with each iteration 80 pxl to the right
    img_rect = pg.Rect(frame_location, size)
    
    new_img = img.subsurface(img_rect)  # not the same variable as img
    animations["animation"].append(new_img)
    
print(animations)
Answered By: The_spider
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.