【问题标题】:PYGAME : How to collide 2 groups of sprites of 2 classes and "AttributeError: type object 'Player' has no attribute 'rect'" [duplicate]PYGAME:如何碰撞 2 个类的 2 组精灵和“AttributeError:类型对象'Player'没有属性'rect'”[重复]
【发布时间】:2020-04-20 20:31:21
【问题描述】:

我想碰撞 cible 和弹丸,当它们碰撞时,它们消失了。要知道是否检测到碰撞,我打印了一个。如果您知道使两个碰撞对象消失的命令,那就太酷了:)

There is also an error :"AttributeError: type object 'Player' has no attribute 'rect'"

这是我的代码:

#                     --- Import des bibliothèques utilisées (dont pygame) ---
import pygame
from pygame import*
from pygame.locals import *
pygame.init()
from random import *


#                                      --- Classe du jeu ---

class Jeux:

    def __init__(self):
        # generer notre joueur
        self.all_players = pygame.sprite.Group()
        self.player = Player()
        self.all_players.add(self.player)
        # groupe de cible
        self.all_cibles = pygame.sprite.Group()
        self.all_projectiles = pygame.sprite.Group()
        self.pressed = {}

        collisions = pygame.sprite.spritecollide(Cible, Projectile, False)
        if collisions:
            print('collision')

#                                     --- Classe du joueur ---

class Player(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.attack = 10
        self.velocity = 7
        """self.all_players = pygame.sprite.Group()
        self.all_projectiles = pygame.sprite.Group()"""
        self.all_cibles = pygame.sprite.Group()
        self.image = pygame.image.load("F:/ISN/game/ressource/vaisseau1.png")
        self.rect = self.image.get_rect()
        self.rect.x = 0
        self.rect.y = 600

    def launch_projectile(self):
        self.all_projectiles.add(Projectile(self))

    def launch_cible(self):
        self.all_cibles.add(Cible(self))

# fonction pour aller a droite
    def move_right(self):
        self.rect.x += self.velocity

# fonction pour aller a gauche
    def move_left(self):
        self.rect.x -= self.velocity


#                                 --- Classe du projectile ---

class Projectile(pygame.sprite.Sprite):
    def __init__(self, player, game):
        super().__init__()
        self.velocity = 7
        self.player = player
        self.projectile = projectile
        self.image = pygame.image.load("F:/ISN/game/ressource/projectile-png-2.png")
        self.image = pygame.transform.scale(self.image, (10, 20))
        self.rect = self.image.get_rect()
        self.all_projectiles.add(self.projectile)
        self.rect.x = player.rect.x + 59
        self.rect.y = player.rect.y

    # fonction servant à détruire le projectile quand il est hors de la fenêtre
    def remove_projectile(self):
        self.player.all_projectiles.remove(self)

    def move(self):
        self.rect.y -= self.velocity

    # vérifier si notre projectile n'est plus présent sur l'écran
        if self.rect.y < 0:
            # supprimer le projectile
            self.remove_projectile()


#                                 --- Classe de la cible ---

class Cible(pygame.sprite.Sprite):
    def __init__(self, game, player):
        super().__init__()
        self.game = game
        self.cible = cible
        self.image = pygame.image.load("F:/ISN/game/ressource/catalan.png")
        self.image = pygame.transform.scale(self.image, (40, 40))
        self.rect = self.image.get_rect()
        self.all_cibles.add(self.cible)
        self.rect.x = randint(50, 1000)
        self.rect.y = randint(0, 400)

    def remove_cible(self):
        self.player.all_cibles.remove(self)

    if pygame.sprite.spritecollide(Player, Projectile, False):
        print('Collide')



#                      --- Gestion des touches et de la fenêtre de jeu ---

clock = pygame.time.Clock()

# generer la fenetre du jeu
pygame.display.set_caption("SPACE INVADERS V2")
screen = pygame.display.set_mode((1080, 720))

# importer charger l'arriere plan
background = pygame.image.load("F:/ISN/game/ressource/BACKGROUND.jpg")

# charger notre jeu
game = Jeux()


running = True
# boucle tant que cette condition est vrai
while running:

    # appliquer l'arriere plan de notre jeu
    screen.blit(background, (0, 0))

    # appliquer l'image de notre joueur sur la fenetre de jeu
    screen.blit(game.player.image, game.player.rect)

    # afficher la cible 
    game.player.all_cibles.draw(screen)

    # recuperer les projectiles du joueur
    for projectile in game.player.all_projectiles:
        projectile.move()

    # appliquer l'ensemble des images de mon groupe de projectiles
    game.player.all_projectiles.draw(screen)

    # mouvements du joueur
    if game.pressed.get(pygame.K_RIGHT) and game.player.rect.x + game.player.rect.width < screen.get_width():
        game.player.move_right()
    elif game.pressed.get(pygame.K_LEFT) and game.player.rect.x > 0:
        game.player.move_left()

    # mettre a jour l'ecran
    pygame.display.flip()

    # si le joueur ferme cette fenetre
    for event in pygame.event.get():
        # que l'evenement est fermeture de fenetre
        if event.type == pygame.QUIT:
            running = False
            pygame.quit()
            print("Fermeture du jeu")
        # detecter si un joueur lache une touche du clavier
        elif event.type == pygame.KEYDOWN:
           game.pressed[event.key] = True
           if event.key == pygame.K_SPACE:
               game.player.launch_projectile()
           elif event.key == pygame.K_DOWN:
               game.player.launch_cible()
        elif event.type == pygame.KEYUP:
            game.pressed[event.key] = False

我不知道怎么办,请帮帮我

【问题讨论】:

  • 在您的代码中,您访问的是Player.rect(大写字母P的玩家)而不是player.rect。换句话说,在某处,您正试图访问 class Player.rect 属性,而不是 Player instance 的属性
  • 我想我解决了这个问题,但现在它说:``` AttributeError: type object 'Cible' has no attribute 'rect'```
  • 同样的事情,但现在是Cible

标签: python class pygame collision


【解决方案1】:

pygame.sprite.spritecollide() 的第一个参数必须是 pygame.sprite.Sprite 的实例,第二个参数必须是 pygame.sprite.Group 的实例。
因此pygame.sprite.spritecollide(Cible, Projectile, False) 没有任何意义,因为CibleProjectile 是类。

self.all_ciblesself.all_projectilespygame.sprite.Group 的实例。可以通过pygame.sprite.groupcollide() 评估组的冲突。例如:

collisions = pygame.sprite.groupcollide(
    self.all_projectiles, self.all_cibles, False, False)

通过将True 分别传递给dokill1dokill2 参数,Sprites 可以从所有Groups 中删除,从而被销毁。
例如,将False 传递给dokill1,将True 传递给dokill2,这样弹丸就会破坏电缆:

collisions = pygame.sprite.groupcollide(
    self.all_projectiles, self.all_cibles, False, True)      

如果要进行碰撞测试,则必须在主应用程序循环中进行。例如:

running = True
# boucle tant que cette condition est vrai
while running:
    # [...]

    collisions = pygame.sprite.groupcollide(game.all_projectiles, game.all_cibles, False, True)
    if collisions:
        print('collision')

    if pygame.sprite.spritecollide(game.player, game.all_projectiles, False):
        print('Collide')

完整的代码可能如下所示:

#                     --- Import des bibliothèques utilisées (dont pygame) ---
import pygame
from pygame import*
from pygame.locals import *
pygame.init()
from random import *

#                                      --- Classe du jeu ---
class Jeux:

    def __init__(self):
        # generer notre joueur
        self.all_players = pygame.sprite.Group()
        self.player = Player()
        self.all_players.add(self.player)
        # groupe de cible
        self.all_cibles = pygame.sprite.Group()
        self.all_projectiles = pygame.sprite.Group()
        self.pressed = {}

#                                     --- Classe du joueur ---
class Player(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.attack = 10
        self.velocity = 7
        """self.all_players = pygame.sprite.Group()
        self.all_projectiles = pygame.sprite.Group()"""
        self.image = pygame.image.load("F:/ISN/game/ressource/vaisseau1.png")
        self.rect = self.image.get_rect()
        self.rect.x = 0
        self.rect.y = 600

    def launch_projectile(self):
        game.all_projectiles.add(Projectile(self, game))

    def launch_cible(self):
        game.all_cibles.add(Cible(self, game))

# fonction pour aller a droite
    def move_right(self):
        self.rect.x += self.velocity

# fonction pour aller a gauche
    def move_left(self):
        self.rect.x -= self.velocity


#                                 --- Classe du projectile ---
class Projectile(pygame.sprite.Sprite):
    def __init__(self, player, game):
        super().__init__()
        self.velocity = 7
        self.game = game
        self.player = player
        self.image = pygame.image.load("F:/ISN/game/ressource/projectile-png-2.png")
        self.image = pygame.transform.scale(self.image, (10, 20))
        self.rect = self.image.get_rect()
        self.game.all_projectiles.add(self)
        self.rect.x = player.rect.x + 59
        self.rect.y = player.rect.y

    # fonction servant à détruire le projectile quand il est hors de la fenêtre
    def remove_projectile(self):
        self.game.all_projectiles.remove(self)

    def move(self):
        self.rect.y -= self.velocity

    # vérifier si notre projectile n'est plus présent sur l'écran
        if self.rect.y < 0:
            # supprimer le projectile
            self.remove_projectile()


#                                 --- Classe de la cible ---
class Cible(pygame.sprite.Sprite):
    def __init__(self, player, game):
        super().__init__()
        self.game = game
        self.image = pygame.image.load("F:/ISN/game/ressource/catalan.png")
        self.image = pygame.transform.scale(self.image, (40, 40))
        self.rect = self.image.get_rect()
        self.game.all_cibles.add(self)
        self.rect.x = randint(50, 1000)
        self.rect.y = randint(0, 400)

    def remove_cible(self):
        self.game.all_cibles.remove(self)


#                      --- Gestion des touches et de la fenêtre de jeu ---
clock = pygame.time.Clock()

# generer la fenetre du jeu
pygame.display.set_caption("SPACE INVADERS V2")
screen = pygame.display.set_mode((1080, 720))

# importer charger l'arriere plan
background = pygame.image.load("F:/ISN/game/ressource/BACKGROUND.jpg")

# charger notre jeu
game = Jeux()


running = True
# boucle tant que cette condition est vrai
while running:

    # appliquer l'arriere plan de notre jeu
    screen.blit(background, (0, 0))

    # appliquer l'image de notre joueur sur la fenetre de jeu
    screen.blit(game.player.image, game.player.rect)

    # afficher la cible 
    game.all_cibles.draw(screen)

    # recuperer les projectiles du joueur
    for projectile in game.all_projectiles:
        projectile.move()

    # appliquer l'ensemble des images de mon groupe de projectiles
    game.all_projectiles.draw(screen)

    # mouvements du joueur
    if game.pressed.get(pygame.K_RIGHT) and game.player.rect.x + game.player.rect.width < screen.get_width():
        game.player.move_right()
    elif game.pressed.get(pygame.K_LEFT) and game.player.rect.x > 0:
        game.player.move_left()

    # mettre a jour l'ecran
    pygame.display.flip()

    # si le joueur ferme cette fenetre
    for event in pygame.event.get():
        # que l'evenement est fermeture de fenetre
        if event.type == pygame.QUIT:
            running = False
            pygame.quit()
            print("Fermeture du jeu")
        # detecter si un joueur lache une touche du clavier
        elif event.type == pygame.KEYDOWN:
           game.pressed[event.key] = True
           if event.key == pygame.K_SPACE:
               game.player.launch_projectile()
           elif event.key == pygame.K_DOWN:
               game.player.launch_cible()
        elif event.type == pygame.KEYUP:
            game.pressed[event.key] = False

    collisions = pygame.sprite.groupcollide(game.all_projectiles, game.all_cibles, False, True)
    if collisions:
        print('collision')

    if pygame.sprite.spritecollide(game.player, game.all_projectiles, False):
        print('Collide')

【讨论】:

    猜你喜欢
    • 2018-10-26
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多