Reputation: 15
I am encountering a problem which says that the source object must be a surface. I asked this question before, and the answer worked, but now it's a different scenario. I looked at the previous question I had, and I couldn't figure out how to solve it.
Error Message:
Traceback (most recent call last):
File "C:\Users\Daniel\Desktop\Thing.py", line 22, in <module>
level.run()
File "C:\Users\Daniel\Desktop\level2.py", line 131, in run
self.clouds.draw(self.display_surface, self.world_shift)
File "C:\Users\Daniel\Desktop\decoration.py", line 67, in draw
self.cloud_sprites.draw(surface)
File "C:\Users\Daniel\AppData\Local\Programs\Python\Python310\lib\site-
packages\pygame\sprite.py", line 551, in draw
self.spritedict.update(zip(sprites, surface.blits((spr.image, spr.rect) for
spr in sprites)))
TypeError: Source objects must be a surface
Basically I am trying to blit things onto a surface, and the thing that confuses me the most is that it worked when I was trying to blit water onto the screen, it had the exact same code but instead of 'cloud' it had 'water', however the water blitting worked while the cloud did not.
Water Class:
class Water:
def __init__(self, top, level_width):
water_start = -width
water_tile_width = 192
tile_x_amount = int((level_width + width) / water_tile_width)
self.water_sprites = pygame.sprite.Group()
for tile in range(tile_x_amount):
x = tile * water_tile_width + water_start
y = top
sprite = AnimatedTile(192, x, y, (x, y),
'C:\\Desktop\\Game\\decoration\\water')
self.water_sprites.add(sprite)
def draw(self, surface, shift):
self.water_sprites.update(shift)
self.water_sprites.draw(surface)
Cloud Class:
class Clouds:
def __init__(self, horizon, level_width, cloud_number):
min_x = -width
max_x = level_width + width
min_y = 0
max_y = horizon
cloud_surface_list = 'C:\\Desktop\\Game\\decoration\\clouds'
self.cloud_sprites = pygame.sprite.Group()
for cloud in range(cloud_number):
cloud = choice(cloud_surface_list)
x = randint(min_x, max_x)
y = randint(min_y, max_y)
sprite = StaticTile(0, x, y, (x, y),
'C:\\Desktop\\Game\\decoration\\clouds')
self.cloud_sprites.add(sprite)
def draw(self, surface, shift):
self.cloud_sprites.update(shift)
self.cloud_sprites.draw(surface)
As you can see the draw method is the exact same code, pretty much. The only difference that I can spot that could be causing the problem would be the inheritance. Water
inherits from a class called AnimatedTile
while Clouds
inherits from StaticTile
. I will put the code for both of those here:
AnimatedTile:
class AnimatedTile(Tile):
def __init__(self, size, x, y, pos, path):
super().__init__(size, x, y, (x, y))
self.frames = import_folder(path)
self.frame_index = 0
self.image = self.frames[int(self.frame_index)]
def animate(self):
self.frame_index += 0.15
if self.frame_index >= 4:
self.frame_index = 0
self.image = self.frames[int(self.frame_index)]
def update(self, shift):
self.animate()
self.rect.x += shift
StaticTile:
class StaticTile(Tile):
def __init__(self, size, x, y, pos, surface):
super().__init__(size, x, y, (x,y))
self.image = surface
self.surface = surface
Drawing and Updating:
self.clouds.draw(self.display_surface,
self.world_shift)
*I know these are surfaces because I drew them the same exact way to blit the water onto the screen (self.water.draw(self.display_surface, self.world_shift)
and it worked.
Other code:
class Level:
def __init__(self, level_data, surface):
self.display_surface = surface
self.world_shift = -8
Tile:
class Tile(pygame.sprite.Sprite):
def __init__(self, size, x, y, pos):
super().__init__()
self.image = pygame.Surface((size, size))
self.rect = self.image.get_rect(topleft = pos)
def update(self, shift):
self.rect.x += shift
world_shift
is basically how fast the level is moving (negative means right, positive means left)
I'm sorry if this sounds stupid and the answer is obvious.
Upvotes: 0
Views: 186
Reputation: 104722
You're not correctly assigning to the image
attribute of your StaticTile
sprite in Clouds
. I'm not sure if it's the caller (Clouds
) or the tile class that is getting it wrong though, you'll have to decide what the API should be.
The mismatch is between your call, here:
sprite = StaticTile(0, x, y, (x, y),
'C:\\Desktop\\Game\\decoration\\clouds')
And the StaticTile.__init__
method, which is declared like this:
def __init__(self, size, x, y, pos, surface):
super().__init__(size, x, y, (x,y))
self.image = surface
self.surface = surface
Note that the calling code is passing a string as the surface
argument. That's similar to how AnimatedTile
is initialized (with a path), but the StaticTile
class expects a surface object to already be loaded.
Upvotes: 2