Partage
  • Partager sur Facebook
  • Partager sur Twitter

AttributeError : object has no attribute [...]

    28 juin 2020 à 21:29:47

    Bonjour je débute en Python particulièrement en pygame. Apres avoir visionné les vidéos de Graven, j'ai essayé de réaliser mon propre jeu pour que 2 joueurs s'affrontent en 1v1 en local en m'appuyant sur le code de Graven. Cependant lorsque je souhaite me déplacer ou lancer un projectile, j'ai cette erreur :

    File "C:/Users/Moi/PycharmProjects/MyGame/main.py", line 39, in <module>

        game.shooter.move_left()

      File "C:\Users\Moi\PycharmProjects\MyGame\player.py", line 75, in move_left

        if not self.game.check_collision(self, self.game.warrior):

    AttributeError: 'Shooter' object has no attribute 'check_collision'


    Voici le code principale :

    import pygame
    from game import Game
    pygame.init()
    
    
    pygame.display.set_caption("Destroy him")
    screen = pygame.display.set_mode((625,556))
    
    background = pygame.image.load('game/bg1.jpg')
    
    game = Game()
    
    
    
    running = True
    
    while running:
    
        screen.blit(background,(0,0))
    
        screen.blit(game.warrior.image, game.warrior.rect)
        screen.blit(game.shooter.image, game.shooter.rect)
    
        game.warrior.update_health_bar(screen)
        game.shooter.update_health_bar(screen)
    
        for projectile in game.warrior.all_projectile:
          projectile.move()
    
    
    
        game.warrior.all_projectile.draw(screen)
    
    
    
        if game.pressed.get(pygame.K_RIGHT) and game.shooter.rect.x + game.warrior.rect.width < screen.get_width():
            game.shooter.move_right()
        elif game.pressed.get(pygame.K_LEFT) and game.shooter.rect.x > 15:
            game.shooter.move_left()
    
        if game.pressed.get(pygame.K_q) and game.shooter.rect.x + game.warrior.rect.width < screen.get_width():
            game.warrior.move_left()
        elif game.pressed.get(pygame.K_d) and game.shooter.rect.x > 15:
            game.warrior.move_right()
    
        pygame.display.flip()
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
               running = False
               pygame.quit()
    
            elif event.type == pygame.KEYDOWN:
                game.pressed[event.key] = True
    
                if event.key == pygame.K_SPACE:
                    game.shooter.launch_laser()
                if event.key == pygame.K_RETURN:
                    game.warrior.launch_lance()
    
            elif event.type == pygame.KEYUP:
                game.pressed[event.key] = False

    La classe Game :

    import pygame
    from player import Warrior, Shooter
    
    class Game:
    
        def __init__(self):
            self.all_players = pygame.sprite.Group()
            self.warrior = Warrior(self)
            self.shooter = Shooter(self)
            self.all_players.add(self.warrior, self.shooter)
            self.pressed = {}
    
        def check_collision(self, sprite, group):
            return pygame.sprite.spritecollide(sprite, group, False, pygame.sprite.collide_mask)


    La classe Player :

    import pygame
    from projectile import Lance, Laser
    
    class Player(pygame.sprite.Sprite):
    
        def __init__(self, game):
            super().__init__()
            self.game = game
            self.health = 100
            self.max_health = 100
            self.attack = 10
            self.velocity = 2
            self.all_projectile = pygame.sprite.Group()
    
        def damage(self, amount):
            if self.health - amount > amount:
                self.health -= amount
    
    
    class Warrior(Player, pygame.sprite.Sprite):
    
        def __init__(self, warrior):
            super().__init__(self)
            self.player = warrior
            self.all_projectile = pygame.sprite.Group()
            self.image = pygame.image.load('game/warrior.png')
            self.image = pygame.transform.scale(self.image, (100, 100))
            self.rect = self.image.get_rect()
            self.rect.x = 15
            self.rect.y = 355
    
        def move_right(self):
            if not self.game.check_collision(self, self.game.shooter):
                self.rect.x += self.velocity
    
        def move_left(self):
            self.rect.x -= self.velocity
    
    
    
        def launch_lance(self):
            self.all_projectile.add(Lance(self))
    
        def update_health_bar(self, surface):
    
            pygame.draw.rect(surface, (60, 63, 60), [self.rect.x-10, self.rect.y - 10, self.max_health, 5])
            pygame.draw.rect(surface,(11, 210, 46),  [self.rect.x-10, self.rect.y-10, self.health, 5])
    
    
    
    class Shooter(Player, pygame.sprite.Sprite):
    
        def __init__(self, shooter):
            super().__init__(self)
            self.player = shooter
            self.all_projectile = pygame.sprite.Group()
            self.image = pygame.image.load('game/shooter.png')
            self.image = pygame.transform.scale(self.image, (100, 100))
            self.rect = self.image.get_rect()
            self.rect.x = 500
            self.rect.y = 362
    
        def launch_laser(self):
            self.all_projectile.add(Laser(self))
    
        def update_health_bar(self, surface):
    
            pygame.draw.rect(surface, (60, 63, 60), [self.rect.x+15, self.rect.y - 10, self.max_health, 5])
            pygame.draw.rect(surface,(11, 210, 46),  [self.rect.x+15, self.rect.y-10, self.health, 5])
    
        def move_right(self):
            self.rect.x += self.velocity
    
        def move_left(self):
            if not self.game.check_collision(self, self.game.warrior):
                self.rect.x -= self.velocity

    La classe Projectile :

    import pygame
    
    class Projectile(pygame.sprite.Sprite):
    
        def __init__(self):
            super().__init__()
            self.velocity = 5
    
    
    
        def remove(self):
            self.player.all_projectile.remove(self)
    
        def move(self):
             self.rect.x += self.velocity
             for player in self.player.game.check_collision(self, self.player.game.all_players):
                 self.remove()
                 player.damage(5)
    
    
             if self.rect.x > 1080:
                 self.remove()
                 print("Projectile supprimé")
    
    class Lance(Projectile, pygame.sprite.Sprite):
    
        def __init__(self, warrior):
            super().__init__()
            self.image = pygame.image.load('game/lance.png')
            self.image = pygame.transform.scale(self.image,(100, 100))
            self.rect = self.image.get_rect()
            self.player = warrior
            self.rect.x = warrior.rect.x + 120
            self.rect.y = warrior.rect.y + 80
            self.origin_image = self.image
    
    class Laser(Projectile, pygame.sprite.Sprite):
    
        def __init__(self, shooter):
            super().__init__()
            self.image = pygame.image.load('game/laser.png')
            self.image = pygame.transform.scale(self.image,(100, 100))
            self.rect = self.image.get_rect()
            self.player = shooter
            self.rect.x = shooter.rect.x + 120
            self.rect.y = shooter.rect.y + 80
            self.origin_image = self.image
    
    

    Merci d'avance pour votre aide !




    -
    Edité par Heptapod 28 juin 2020 à 21:50:18

    • Partager sur Facebook
    • Partager sur Twitter
      28 juin 2020 à 21:38:23

      j'avoue ne pas comprendre pourquoi ...
      • Partager sur Facebook
      • Partager sur Twitter

      Python c'est bon, mangez-en. 

        28 juin 2020 à 22:25:25

        Bonjour.

        En changeant le code comme ceci :

        class Shooter(Player, pygame.sprite.Sprite):
        
            _game = None
         
            def __init__(self, shooter):
                super().__init__(shooter)
                self.player = shooter
                self.all_projectile = pygame.sprite.Group()
                self.image = pygame.image.load('game/shooter.png')
                self.image = pygame.transform.scale(self.image, (100, 100))
                self.rect = self.image.get_rect()
                self.rect.x = 500
                self.rect.y = 362
        
            @property
            def game(self):
                return self._game
        
            @game.setter
            def game(self, value):
                self._game = value
                print(str(value))

        On peut s'apercevoir que :

        pygame 1.9.6
        Hello from the pygame community. https://www.pygame.org/contribute.html
        <Shooter sprite(in 0 groups)>

        En fait, self.game est de type Shooter. Donc self.game ne possède pas de méthode .check_collision.

        Pourquoi ? Voici la ligne 54 de player.py :

        super().__init__(self)

        Elle se simplifie en :

        Player.__init__(self, self)

        Or Player.__init__ a un effet intéressant :

        self.game = game

        Et game est ici le second argument de Player.__init__, or on sait que ce second argument est en fait self, qui contient un objet de type Shooter. Voilà comment régler cela :

        class Shooter(Player, pygame.sprite.Sprite):
         
            def __init__(self, game): # On passe un objet de type Game donc ce nom est mieux
                super().__init__(game)
                #self.player = shooter Honnêtement je ne sais pas ce que tu veux faire ici

        à noter que d'autres erreurs t'attendent encore, donc n'hésite pas

        • Partager sur Facebook
        • Partager sur Twitter

        typage structurel ftw

          29 juin 2020 à 2:50:19

          Bonjour digammaF, 

          Merci beaucoup pour votre réponse. J'ai réussi à résoudre mes nombreuses erreurs grâce à un Discord. Voici mon code désormais :

          Le code principale:

          import pygame
          from game import Game
          pygame.init()
          
          
          pygame.display.set_caption("Destroy him")
          screen = pygame.display.set_mode((625,556))
          
          background = pygame.image.load('game/bg1.jpg')
          
          game = Game()
          
          
          
          running = True
          
          while running:
          
              screen.blit(background,(0,0))
          
              screen.blit(game.warrior.image, game.warrior.rect)
              screen.blit(game.shooter.image, game.shooter.rect)
          
              game.warrior.update_health_bar(screen)
              game.shooter.update_health_bar(screen)
          
              for projectile in game.warrior.all_projectile:
                projectile.move()
          
              for projectile in game.shooter.all_projectile:
                projectile.move()
          
          
          
              game.warrior.all_projectile.draw(screen)
              game.shooter.all_projectile.draw(screen)
          
              if game.pressed.get(pygame.K_RIGHT) and game.shooter.rect.x + game.shooter.rect.width < 585:
                  game.shooter.move_right()
              elif game.pressed.get(pygame.K_LEFT) and game.shooter.rect.x > 0:
                  game.shooter.move_left()
          
              if game.pressed.get(pygame.K_f) and game.warrior.rect.x + game.warrior.rect.width < screen.get_width():
                  game.warrior.move_right()
              elif game.pressed.get(pygame.K_s) and game.warrior.rect.x > 0:
                  game.warrior.move_left()
          
          
              pygame.display.flip()
          
              for event in pygame.event.get():
                  if event.type == pygame.QUIT:
                     running = False
                     pygame.quit()
          
                  elif event.type == pygame.KEYDOWN:
                      game.pressed[event.key] = True
          
                      if event.key == pygame.K_SPACE:
                          game.warrior.launch_lance(game)
          
                      if event.key == pygame.K_RETURN:
                          game.shooter.launch_laser(game)
          
                  elif event.type == pygame.KEYUP:
                      game.pressed[event.key] = False

          La classe Game:

          import pygame
          from player import Warrior, Shooter
          
          class Game(pygame.sprite.Sprite):
          
              def __init__(self):
                  super().__init__()
                  self.all_players = pygame.sprite.Group()
                  self.warrior = Warrior(self)
                  print(self.warrior.rect)
                  self.shooter = Shooter(self)
                  self.all_players.add(self.warrior, self.shooter)
                  self.pressed = {}

          La classe Player:

          import pygame
          from projectile import Lance, Laser
          
          
          class Player(pygame.sprite.Sprite):
          
              def __init__(self, game):
                  super().__init__()
                  self.game = game
                  self.health = 100
                  self.max_health = 100
                  self.attack = 10
                  self.velocity = 2
                  self.all_projectile = pygame.sprite.Group()
          
              def damage(self, amount):
                  if self.health > 0:
                      self.health -= amount
          
          
          class Warrior(Player):
          
              def __init__(self, game):
                  super().__init__(game)
                  self.all_projectile = pygame.sprite.Group()
                  self.image = pygame.image.load('game/warrior.png')
                  self.image = pygame.transform.scale(self.image, (100, 100))
                  self.rect = self.image.get_rect()
                  self.rect.x = 15
                  self.rect.y = 355
          
              def move_right(self):
                  if not pygame.sprite.collide_rect(self, self.game.shooter):
                      self.rect.x += self.velocity
          
              def move_left(self):
                  self.rect.x -= self.velocity
          
              def launch_lance(self, game):
                  self.all_projectile.add(Lance(self, game))
          
              def update_health_bar(self, surface):
          
                  pygame.draw.rect(surface, (60, 63, 60), [self.rect.x-10, self.rect.y - 10, self.max_health, 5])
                  pygame.draw.rect(surface,(11, 210, 46),  [self.rect.x-10, self.rect.y-10, self.health, 5])
          
          
          
          class Shooter(Player):
          
              def __init__(self, game):
                  super().__init__(game)
                  self.all_projectile = pygame.sprite.Group()
                  self.image = pygame.image.load('game/shooter.png')
                  self.image = pygame.transform.scale(self.image, (100, 100))
                  self.rect = self.image.get_rect()
                  self.rect.x = 485
                  self.rect.y = 362
          
              def launch_laser(self, game):
                  self.all_projectile.add(Laser(self, game))
          
              def update_health_bar(self, surface):
          
                  pygame.draw.rect(surface, (60, 63, 60), [self.rect.x+15, self.rect.y - 17, self.max_health, 5])
                  pygame.draw.rect(surface,(11, 210, 46),  [self.rect.x+15, self.rect.y-17, self.health, 5])
          
              def move_right(self):
                  self.rect.x += self.velocity
          
              def move_left(self):
                  if not pygame.sprite.collide_rect(self, self.game.warrior):
                      self.rect.x -= self.velocity

          Et enfin la classe Projectile:

          import pygame
          
          
          class Projectile(pygame.sprite.Sprite):
          
              def __init__(self):
                  super().__init__()
          
          
              def remove(self):
                  self.player.all_projectile.remove(self)
          
          
          
          class Lance(Projectile, pygame.sprite.Sprite):
          
              def __init__(self, warrior, game):
                  super().__init__()
                  self.image = pygame.image.load('game/lance.png')
                  self.image = pygame.transform.scale(self.image, (75, 75))
                  self.game =game
          
                  self.rect = self.image.get_rect()
                  self.player = warrior
                  self.rect.x = warrior.rect.x + 75
                  self.rect.y = warrior.rect.y + 15
                  self.origin_image = self.image
                  self.velocity = 1.5
          
              def move(self):
                  self.rect.x += self.velocity
                  if pygame.sprite.collide_rect(self, self.game.shooter):
                      self.remove()
                      self.game.shooter.damage(5)
          
                  if self.rect.x > 1080:
                      self.remove()
                      print("Projectile supprimé")
          
          
          class Laser(Projectile, pygame.sprite.Sprite):
          
              def __init__(self, shooter, game):
                  super().__init__()
          
                  self.image = pygame.image.load('game/laser.png')
                  self.image = pygame.transform.scale(self.image, (75, 75))
                  self.game = game
                  self.rect = self.image.get_rect()
                  self.player = shooter
                  self.rect.x = shooter.rect.x - 55
                  self.rect.y = shooter.rect.y + 20
                  self.origin_image = self.image
                  self.velocity = 1
          
              def move(self):
                  self.rect.x -= self.velocity
                  if pygame.sprite.collide_rect(self, self.game.warrior):
                      self.remove()
                      self.game.warrior.damage(5)
          

          Voila ! Si vous voyez des améliorations pour qu'il soit allégé ou autre chose, je suis preneur !:D

          • Partager sur Facebook
          • Partager sur Twitter

          AttributeError : object has no attribute [...]

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown