Problème avec un attribut Pygame [Python]

Résolu
Bonsoir,

Je débute en programmation du python et en ce moment j'utilise le module Pygame.
J'ai créer une classe qui s'appelle BluePlayer:
# Créer le joueur bleu
class BluePlayer(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.vie = 250
        self.kick = 5
        self.max_vie = 250
        self.attack = 10
        self.speed = 5
        self.image = pygame.image.load('archerbleu.png')
        self.rect = self.image.get_rect()
        self.rect.x = 50
        self.rect.y = 500

    def move_right(self):
        self.rect.x += self.speed

    def move_left(self):
        self.rect.x -= self.speed


Tout est normal pour le moment j'arrive à faire apparaître le joueur sur la fenêtre mais quand je veux créer un autre joueur comma par exemple une classe RedPlayer:
# Créer le joueur rouge
class RedPlayer(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.vie = 250
        self.kick = 5
        self.max_vie = 250
        self.attack = 10
        self.speed = 5
        self.photo = pygame.image.load('archerrouge.png')
        self.rect = self.photo.get_rect()
        self.rect.x = 400
        self.rect.y = 500

Lorsque je lance mon programme une erreur apparaît disant:
screen.blit(game.red_player.photo, game.red_player.rect)
AttributeError: type object 'RedPlayer' has no attribute 'photo'

Python me dit que la classe RedPlayer n'as pas d'attribut photo alors que si...
self.photo = pygame.image.load('archerrouge.png')


Je ne comprend pas...

Si vous savez pourquoi cela fait cela, pouriez-vous me le dire ?

Merci, Cordialement

4 réponses

  1. Bonsoir,

    Tu as forcément fait une erreur quelque part.
    Comment est instancié ta classe et où ? Même fichier ? Tu n'aurais pas déclaré une autre classe de même nom que tu utiliserais au lieu de celle-là ?

    Tu peux déjà regarder ce que contient ton objet game.red_player en utilisant dir
    print(dir(game.red_player))
    .

    Toutefois, dans ton code, tu devrais avoir une classe Player héritant de Sprite, tes 2 classes players (bleu, rouge) héritant de Player, ici l'héritage est plus que judicieux puisque il y a exactement les mêmes propriétés dans tes classes.
    1. Quand j’exécute la commande avec dire, j'obtiens ce-ci:
      ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'add', 'add_internal', 'alive', 'groups', 'kill', 'remove', 'remove_internal', 'update']
      


      Donc ce que vous voulez dire c'est que je peux créer une spuerclasse contenant BluePlayer et RedPlayer ?

      Voilà mon programme en entier au cas ou (Personnellement je ne vois pas d’erreur mais l'erreur doit être au moment ou il y a:)
      # Appliquer l'image du joueur rouge
          screen.blit(game.red_player.photo, game.red_player.rect)


      Sinon voilà le programme en entier:
      Main:
      import pygame
      import time
      from game import Game
      
      pygame.init()
      
      # Générer la fenêtre du jeu
      pygame.display.set_caption("ArcherWars")
      screen = pygame.display.set_mode((1080, 720))
      logo = pygame.image.load("icon.png").convert()
      pygame.display.set_icon(logo)
      
      # Importer l'arrière plan du jeu
      fond = pygame.image.load('fond.jpg')
      
      # Charger le jeu
      game = Game()
      
      
      run = True
      
      # Boucle qui s'éxécute tant que run = True
      while run:
      
      
      
          # Appliquer l'arière plan du jeu
          screen.blit(fond, (0, -77))
      
          # Appliquer l'image du joueur bleu
          screen.blit(game.blue_player.image, game.blue_player.rect)
      
          # Appliquer l'image du joueur rouge
          screen.blit(game.red_player.photo, game.red_player.rect)
      
          # Vérifier si le joueur shouaite aller à gauche ou à droite
          if game.pressed.get(pygame.K_f) and game.blue_player.rect.x + game.blue_player.rect.width < screen.get_width():
              game.blue_player.move_right()
          elif game.pressed.get(pygame.K_d) and game.blue_player.rect.x > 0:
              game.blue_player.move_left()
      
          # Mettre à jour l'écran
          pygame.display.flip()
      
          # Si le joueur ferme cette fenêtre
          for event in pygame.event.get():
              # Vérifier que l'évenement est fermeture de fenêtre
              if event.type == pygame.QUIT:
                  run = False
                  pygame.quit()
                  print("Fermeture du jeu en cours veuillez patienter...")
                  time.sleep(2.5)
                  print("Le jeu à bien été fermé !")
              # Détecter si un joueur lache une touche du clavier
              elif event.type == pygame.KEYDOWN:
                  game.pressed[event.key] = True
              elif event.type == pygame.KEYUP:
                  game.pressed[event.key] = False
      

      Game:
      import pygame
      from blue_player import BluePlayer
      from red_player import RedPlayer
      
      
      # Créer une seconde classe qui va représenter le jeu
      class Game:
      
          def __init__(self):
              # Générer le joueur quand une partie est créer
              self.blue_player = BluePlayer()
              self.red_player = RedPlayer
              self.pressed = {}
      

      Blue_Player:
      import pygame
      
      
      # Créer le joueur bleu
      class BluePlayer(pygame.sprite.Sprite):
      
          def __init__(self):
              super().__init__()
              self.vie = 250
              self.kick = 5
              self.max_vie = 250
              self.attack = 10
              self.speed = 5
              self.image = pygame.image.load('archerbleu.png')
              self.rect = self.image.get_rect()
              self.rect.x = 50
              self.rect.y = 500
      
          def move_right(self):
              self.rect.x += self.speed
      
          def move_left(self):
              self.rect.x -= self.speed
      

      red_player:
      import pygame
      
      
      # Créer le joueur rouge
      class RedPlayer(pygame.sprite.Sprite):
      
          def __init__(self):
              super().__init__()
              self.vie = 250
              self.kick = 5
              self.max_vie = 250
              self.attack = 10
              self.speed = 5
              self.photo = pygame.image.load('archerrouge.png')
              self.rect = self.photo.get_rect()
              self.rect.x = 400
              self.rect.y = 500
      


      Merci pour la réponse, cordialement
      1. Bonjour,

        Tu n'as pas instancié ton objet (omission des parenthèses).

        self.red_player = RedPlayer


        > Donc ce que vous voulez dire c'est que je peux créer une spuerclasse contenant BluePlayer et RedPlayer ?

        Non, une classe PLayer dont BluePlayer et RedPlayer dériveront.
    2. Bonjour,

      Si j'ai instancié mon objet dans la classe game:
      mport pygame
      from blue_player import BluePlayer
      from red_player import RedPlayer
      
      
      # Créer une seconde classe qui va représenter le jeu
      class Game:
      
          def __init__(self):
              # Générer le joueur quand une partie est créer
              self.blue_player = BluePlayer()
              self.red_player = RedPlayer
              # Ci dessus j’instancie ma classe red_player et blue_player


      Et pour la classe Player dont RedPlayer et BluePlayer dériveront, comme ça ça marche ?
      import pygame
      import game
      
      
      # Créer la super classe de joueur
      class Player(pygame.sprite.Sprite):
          def __init__(self):
              super().__init__()
              self.vie = 250
              self.kick = 5
              self.max_vie = 250
              self.attack = 10
              self.speed = 5
              self.saut = 5
      
      # Puis quand je créer la classe RedPlayer et BluePlayer je fais ça:
      
      import pygame
      import player
      
      
      # Créer le joueur rouge
      class RedPlayer(player.Player):
      
           # Ci dessus je fais dériver la classe RedPlayer de la classe Player et pareil pour la classe                      BluePlayer puis j'ajoute les composants supplémentaires
          def __init__(self):
              super().__init__()
              self.photo = pygame.image.load('archerrouge.png')
              self.rect = self.photo.get_rect()
              self.rect.x = 400
              self.rect.y = 500


      Je ne sais pas d'où vient le problème si tous les codes fonctionnent bien...
      Merci pour vos réponses, cordialement
      1. Pas bien réveillé ?

        # Créer une seconde classe qui va représenter le jeu
        class Game:
        
            def __init__(self):
                # Générer le joueur quand une partie est créer
                self.blue_player = BluePlayer()
                self.red_player = RedPlayer # «««««« IL MANQUE LES PARENTHÈSES !
                # Ci dessus j’instancie ma classe red_player et blue_player


        Oui c'est ça pour ta classe Player, sachant que seuls le nom d'image et pos x, y varient alors ça pourrait faire

        class Player(class Player(pygame.sprite.Sprite):
            def __init__(self, image_file, x, y):
                super().__init__()
                self.vie = 250
                self.kick = 5
                self.max_vie = 250
                self.attack = 10
                self.speed = 5
                self.photo = pygame.image.load(image_file)
                self.rect = self.photo.get_rect()
                self.rect.x = x
                self.rect.y = y


        Puis
        class BluePlayer(Player):
            def __init__(self):
                super().__init__('archerbleu.png', 50, 500)
        
            def move_right(self):
                self.rect.x += self.speed
        
            def move_left(self):
                self.rect.x -= self.speed


        Et
        class RedPlayer(Player):
            def __init__(self):
                super().__init__('archerrouge.png', 400, 500)


        Si RedPlayer doit aussi implémenter les méthodes move_* alors il faudrait les déclarer dans Player.
    3. Merci, je n'avais pas remarqué !

      Je test le programme et...

      Tout fonctionne bien, merci :-)