Pygame sprite group won't draw because of error: Source objects must be a suface
Question:
im having a problem with my 2D Platformer game and when trying to display sprite group, an error message appears saying: Pygame: TypeError: Source objects must be a surface, The problem seems to be around the coins sprite group when trying to draw it to the self.display_surface
in my code here.
I would highly appreciate any help.
Here is my code for my level.py:
import pygame
from support import import_csv_layout, import_cut_graphics
from settings import tile_size
from tiles import Tile, StaticTile, Crate, AnimatedTile
class Level:
def __init__(self, level_data, surface):
# general setup
self.display_surface = surface
self.world_shift = -5
# terrain setup
terrain_layout = import_csv_layout(level_data['terrain'])
self.terrain_sprites = self.create_tile_group(terrain_layout, 'terrain')
# grass setup
grass_layout = import_csv_layout(level_data['grass'])
self.grass_sprites = self.create_tile_group(grass_layout, 'grass')
# crates
crate_layout = import_csv_layout(level_data['crates'])
self.crate_sprites = self.create_tile_group(crate_layout, 'crates')
# coins
coins_layout = import_csv_layout(level_data['coins'])
self.coin_sprites = self.create_tile_group(coins_layout, 'coins')
def create_tile_group(self, layout, type):
sprite_group = pygame.sprite.Group()
for row_index, row in enumerate(layout):
for col_index, val in enumerate(row):
if val != '-1':
x = col_index * tile_size
y = row_index * tile_size
if type == 'terrain':
terrain_tile_list = import_cut_graphics('../gfx/terrain/terrain_tiles.png')
tile_surface = terrain_tile_list[int(val)]
sprite = StaticTile(tile_size, x, y, tile_surface)
if type == 'grass':
grass_tile_list = import_cut_graphics('../gfx/decoration/grass/grass.png')
tile_surface = grass_tile_list[int(val)]
sprite = StaticTile(tile_size, x, y, tile_surface)
if type == 'crates':
sprite = Crate(tile_size, x, y)
if type == 'coins':
sprite = AnimatedTile(tile_size, x, y, '../gfx/coins/gold')
sprite_group.add(sprite)
return sprite_group
def run(self):
# run the entire game / level
# terrain
self.terrain_sprites.update(self.world_shift)
self.terrain_sprites.draw(self.display_surface)
# grass
self.grass_sprites.update(self.world_shift)
self.grass_sprites.draw(self.display_surface)
# crate
self.crate_sprites.update(self.world_shift)
self.crate_sprites.draw(self.display_surface)
# coins
self.coin_sprites.update(self.world_shift)
self.coin_sprites.draw(self.display_surface)
And Here is the tile.py file: AnimatedTile and SaticTile class:
class AnimatedTile(Tile):
def __init__(self, size, x, y, path):
super().__init__(size, x, y)
self.frames = import_folder(path)
self.frame_index = 0
self.image = self.frames[self.frame_index]
class StaticTile(Tile):
def __init__(self, size, x, y, surface):
super().__init__(size, x, y)
self.image = surface
Also import folder has a surface variable, so i can’t tell if its in here:
surface_list = []
for _,__, image_files in walk(path):
for image in image_files:
full_path = path + '/' + image
image_surf = pygame.image.load(full_path).convert_alpha()
surface_list.append(image)
return surface_list
Crate:
class Crate(StaticTile):
def __init__(self, size, x, y):
super().__init__(size, x, y, pygame.image.load('../gfx/terrain/crate.png').convert_alpha())
offset_y = y + size
self.rect = self.image.get_rect(bottomleft = (x,offset_y))
Answers:
The bug is in the code that creates the surface_list
. You have to append image_surf
to the surface_list
, but not image
:
surface_list.append(image)
surface_list.append(image_surf)
im having a problem with my 2D Platformer game and when trying to display sprite group, an error message appears saying: Pygame: TypeError: Source objects must be a surface, The problem seems to be around the coins sprite group when trying to draw it to the self.display_surface
in my code here.
I would highly appreciate any help.
Here is my code for my level.py:
import pygame
from support import import_csv_layout, import_cut_graphics
from settings import tile_size
from tiles import Tile, StaticTile, Crate, AnimatedTile
class Level:
def __init__(self, level_data, surface):
# general setup
self.display_surface = surface
self.world_shift = -5
# terrain setup
terrain_layout = import_csv_layout(level_data['terrain'])
self.terrain_sprites = self.create_tile_group(terrain_layout, 'terrain')
# grass setup
grass_layout = import_csv_layout(level_data['grass'])
self.grass_sprites = self.create_tile_group(grass_layout, 'grass')
# crates
crate_layout = import_csv_layout(level_data['crates'])
self.crate_sprites = self.create_tile_group(crate_layout, 'crates')
# coins
coins_layout = import_csv_layout(level_data['coins'])
self.coin_sprites = self.create_tile_group(coins_layout, 'coins')
def create_tile_group(self, layout, type):
sprite_group = pygame.sprite.Group()
for row_index, row in enumerate(layout):
for col_index, val in enumerate(row):
if val != '-1':
x = col_index * tile_size
y = row_index * tile_size
if type == 'terrain':
terrain_tile_list = import_cut_graphics('../gfx/terrain/terrain_tiles.png')
tile_surface = terrain_tile_list[int(val)]
sprite = StaticTile(tile_size, x, y, tile_surface)
if type == 'grass':
grass_tile_list = import_cut_graphics('../gfx/decoration/grass/grass.png')
tile_surface = grass_tile_list[int(val)]
sprite = StaticTile(tile_size, x, y, tile_surface)
if type == 'crates':
sprite = Crate(tile_size, x, y)
if type == 'coins':
sprite = AnimatedTile(tile_size, x, y, '../gfx/coins/gold')
sprite_group.add(sprite)
return sprite_group
def run(self):
# run the entire game / level
# terrain
self.terrain_sprites.update(self.world_shift)
self.terrain_sprites.draw(self.display_surface)
# grass
self.grass_sprites.update(self.world_shift)
self.grass_sprites.draw(self.display_surface)
# crate
self.crate_sprites.update(self.world_shift)
self.crate_sprites.draw(self.display_surface)
# coins
self.coin_sprites.update(self.world_shift)
self.coin_sprites.draw(self.display_surface)
And Here is the tile.py file: AnimatedTile and SaticTile class:
class AnimatedTile(Tile):
def __init__(self, size, x, y, path):
super().__init__(size, x, y)
self.frames = import_folder(path)
self.frame_index = 0
self.image = self.frames[self.frame_index]
class StaticTile(Tile):
def __init__(self, size, x, y, surface):
super().__init__(size, x, y)
self.image = surface
Also import folder has a surface variable, so i can’t tell if its in here:
surface_list = []
for _,__, image_files in walk(path):
for image in image_files:
full_path = path + '/' + image
image_surf = pygame.image.load(full_path).convert_alpha()
surface_list.append(image)
return surface_list
Crate:
class Crate(StaticTile):
def __init__(self, size, x, y):
super().__init__(size, x, y, pygame.image.load('../gfx/terrain/crate.png').convert_alpha())
offset_y = y + size
self.rect = self.image.get_rect(bottomleft = (x,offset_y))
The bug is in the code that creates the surface_list
. You have to append image_surf
to the surface_list
, but not image
:
surface_list.append(image)
surface_list.append(image_surf)