Reputation: 19
So, to start I was developing a game in pygame, and it worked very well until then, but when adding my animations for my characters, the script has an error, a surface problem; "TypeError: Source objects must be a surface". I searched for several hours if someone already had my problem but without result...
I attach my code below.
My main.py :
import pygame
from game import Game
if __name__ == '__main__':
pygame.init()
game = Game()
game.run()
My game.py :
import pygame
import pytmx
import pyscroll
from playr import Player
class Game:
def __init__(self):
self.screen = pygame.display.set_mode((800, 800))
pygame.display.set_caption("Labyrinthe DVT")
tmx_data = pytmx.util_pygame.load_pygame('carte.tmx')
map_data = pyscroll.data.TiledMapData(tmx_data)
map_layer = pyscroll.orthographic.BufferedRenderer(map_data, self.screen.get_size())
map_layer.zoom = 2
player_position = tmx_data.get_object_by_name("player")
self.player = Player(player_position.x, player_position.y)
self.group = pyscroll.PyscrollGroup(map_layer = map_layer, default_layer= 5)
self.group.add(self.player)
def handle_input(self):
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
self.player.move_up()
self.player.change_animation('up')
elif pressed[pygame.K_DOWN]:
self.player.move_down()
self.player.change_animation('down')
elif pressed[pygame.K_RIGHT]:
self.player.move_right()
self.player.change_animation('right')
elif pressed[pygame.K_LEFT]:
self.player.move_left()
self.player.change_animation('left')
def run(self):
clock = pygame.time.Clock()
running = True
while running:
self.handle_input()
self.group.update()
#centrer la camera
self.group.center(self.player.rect)
#dessiner les calques
self.group.draw(self.screen) #error
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
clock.tick(60)
pygame.quit()
My player.py :
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.sprite_sheet = pygame.image.load('player sheet.png')
self.image = self.get_image(0 ,0)
self.image.set_colorkey([0, 0, 0])
self.rect = self.image.get_rect()
self.position = [x, y]
self.vitesse = 2
#stocker les image pour l'effet
self.image = {
'down' : self.get_image(0, 0),
'left': self.get_image(0, 32),
'right': self.get_image(0, 64),
'up': self.get_image(0, 96)
}
def change_animation(self, name):
self.image = self.images[name]
self.image.set_colorkey((0, 0, 0))
def move_right(self): self.position[0] += self.vitesse
def move_left(self): self.position[0] -= self.vitesse
def move_down(self): self.position[1] += self.vitesse
def move_up(self): self.position[1] -= self.vitesse
def update(self):
self.rect.topleft = self.position
def get_image(self, x, y):
image = pygame.Surface([32, 32])
image.blit(self.sprite_sheet, (0, 0), (x, y, 32, 32))
return image
Here is the entirety of my code, if you have more questions in order to be able to help me, do not hesitate.
PS: I recall the error: "TypeError: Source objects must be a surface"
Upvotes: 1
Views: 84
Reputation: 210948
The problem is that self.image
is used twice. First it is a pygame.Surface
:
self.image = self.get_image(0 ,0)
Then it is a dictionary:
self.image = { 'down' : self.get_image(0, 0), 'left': self.get_image(0, 32), 'right': self.get_image(0, 64), 'up': self.get_image(0, 96) }
However, since Player
is a pygame.sprite.Sprite
object, the iamge
attribute must be a pygame.Surface
object, but not an dictionary. This is because of pygame.sprite.Group.draw()
:
Draws the contained Sprites to the Surface argument. This uses the
Sprite.image
attribute for the source surface, andSprite.rect
. [...]
Rename the dictionary to solve the issue. e.g.:
self.direction_images = {
'down' : self.get_image(0, 0),
'left': self.get_image(0, 32),
'right': self.get_image(0, 64),
'up': self.get_image(0, 96)
}
Upvotes: 1