Mathi'S
Mathi'S

Reputation: 19

I have a problem with the surface of my pygame script, I debug but can't find the answer

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

Answers (1)

Rabbid76
Rabbid76

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, and Sprite.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

Related Questions