Home > Enterprise >  It gives me an error that my object has no attribute even though I assigned it
It gives me an error that my object has no attribute even though I assigned it

Time:07-25

I'm working in pygame & python and trying to make a zombie shooting game. It all worked smoothly until I tried to add the collision system. If you also know how to add a collision system for this game please leave a comment with a full code.

The error:

type object 'bullet' has no attribute 'rect'
  File "C:\Users\*\Desktop\Zombie!\main.py", line 172, in game
    collide = pygame.sprite.spritecollide(bullet, enemiesList, False)
  File "C:\Users\*\Desktop\Zombie!\main.py", line 44, in menu
    game()
  File "C:\Users\*\Desktop\Zombie!\main.py", line 211, in <module>
    menu()

The code:

import pygame, sys, math, random, time

pygame.init()

#var
screen = pygame.display.set_mode([800, 500])
font = pygame.font.SysFont(None, 20)

playerX = 200
playerY = 200
player = pygame.Rect((playerX, playerY), (10,10))
bullets = pygame.sprite.Group()
clock = pygame.time.Clock()
previous_time = pygame.time.get_ticks()
waveCount = 1

#Remaining enemy count
enemiesList = pygame.sprite.Group()
normalEnemy = 0
speedyEnemy = 0
tankEnemy = 0

def draw_text(text, font, color, surface, x, y):
    textobj = font.render(text, 1, color)
    textrect = textobj.get_rect()
    textrect.topleft = (x, y)
    surface.blit(textobj, textrect)

click = False

def menu():
     while True:
        global click
        screen.fill((0,0,0))
        draw_text('main menu', font, (255, 255, 255), screen, 20, 20)
 
        mx, my = pygame.mouse.get_pos()
 
        button_1 = pygame.Rect(50, 100, 200, 50)
        button_2 = pygame.Rect(50, 200, 200, 50)
        if button_1.collidepoint((mx, my)):
            if click:
                game()
        if button_2.collidepoint((mx, my)):
            if click:
                options()
        pygame.draw.rect(screen, (255, 0, 0), button_1)
        pygame.draw.rect(screen, (255, 0, 0), button_2)
 
        click = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    click = True
 
        pygame.display.update()
        clock.tick(60)

def game():
    run = True
    class bullet(pygame.sprite.Sprite):
        def __init__(self, x, y, mx, my):
            pygame.sprite.Sprite.__init__(self)
            self.x = x
            self.y = y
            self.mx = mx
            self.my = my
            self.speed = 10
            self.angle = math.atan2(my-self.y, mx-self.x)
            self.x_vel = math.cos(self.angle) * self.speed
            self.y_vel = math.sin(self.angle) * self.speed
            self.radius = 4
            self.mask = pygame.mask.Mask((self.radius, self.radius), True)
            self.rect = pygame.Rect(self.x, self.y, self.radius, self.radius)

        def update(self):
            self.x  = int(self.x_vel)
            self.y  = int(self.y_vel)

            pygame.draw.circle(screen, (0, 255, 255), (self.x   5, self.y   5), self.radius)
            if self.x > 800 or self.x < 0 or self.y > 500 or self.y < 0:
                #Remove Bullet Class from list(bullets)
                self.kill()

    class enemy(pygame.sprite.Sprite):
        def __init__(self, enemyType, x, y):
            pygame.sprite.Sprite.__init__(self)
            self.x = x
            self.y = y
            if enemyType == "normal":
                self.speed = 1
                self.hp = 1
                self.color = (255, 28, 28)
                self.radius = 10
            if enemyType == "speedy":
                self.speed = 3
                self.hp = 1
            if enemyType == "tank":
                self.speed = 3
                self.hp = 3
            self.mask = pygame.mask.Mask((self.radius, self.radius), True)
            self.rect = pygame.Rect(self.x, self.y, self.radius, self.radius)
            
        def update(self):
            global playerX, playerY, enemiesList, bullets
            # Find direction vector (dx, dy) between enemy and player.
            dx, dy = playerX - self.x, playerY - self.y
            dist = math.hypot(dx, dy)
            dx, dy = dx / dist, dy / dist  # Normalize.
            # Move along this normalized vector towards the player at current speed.
            self.x  = dx * self.speed
            self.y  = dy * self.speed

            pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius)

    
    #Wave system
    def waves(waveNumber):
        global normalEnemy,speedyEnemy, tankEnemy, enemiesList, waveCount
        if waveNumber == 1:
            normalEnemy = 5
            speedyEnemy = 0
            tankEnemy = 0
            for i in range(5):
                enemiesList.add(enemy("normal", random.randint(0, 800), random.randint(0, 600)))

        if waveNumber == 2:
            normalEnemy = 7
            speedyEnemy = 0
            tankEnemy = 0
            
    while run:
        clock.tick(60)
        screen.fill([255, 255, 255])
        mx, my= pygame.mouse.get_pos()

        #movements
        def movement():
            global playerX, playerY, previous_time
            key = pygame.key.get_pressed()
            mouse = pygame.mouse.get_pressed()
            if key[pygame.K_w]:
                playerY -= 5
            if key[pygame.K_s]:
                playerY  = 5
            if key[pygame.K_d]:
                playerX  = 5
            if key[pygame.K_a]:
                playerX -= 5
            if mouse[0]:
                current_time = pygame.time.get_ticks()
                if current_time - previous_time > 500:
                    previous_time = current_time
                    bullets.add(bullet(playerX, playerY, mx, my))
            for bullets_ in bullets:
                bullets_.update()
            
            for enemies_ in enemiesList:
                enemies_.update()

        if normalEnemy == 0 and speedyEnemy == 0 and tankEnemy == 0:
            waves(waveCount)

        collide = pygame.sprite.spritecollide(bullet, enemiesList, False)
        
        def draw():
            global player, waveCount
            player = pygame.Rect((playerX, playerY), (10,10))
            pygame.draw.rect(screen, (0, 255, 0), player)

            draw_text('wave:'   str(waveCount), font, (0, 0, 0), screen, 20, 20)


        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    run = False

        movement()
        draw()
        pygame.display.flip()

def options():
    running = True
    while running:
        screen.fill((0,0,0))
 
        draw_text('options', font, (255, 255, 255), screen, 20, 20)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
        
        pygame.display.update()
        clock.tick(60)
 
menu()

I am pretty sure I assigned self.rect at the bullet class, I checked the indents and the spelling but I can't to seem to find the error.

CodePudding user response:

pygame.sprite.spritecollide - assumes that first parameter is an instance of a class which has 'rect' attribute. But you put the class itself there.

I believe the code must looks like this:

for bullets_ in bullets:
    collide = pygame.sprite.spritecollide(bullets_, enemiesList, False)

CodePudding user response:

Look at the error: type error bullet ... . Somewhere, you're using the bullet class name instead of using an instance of that class.

CodePudding user response:

You have a Group bullets and a Group enemiesList. Use pygame.sprite.groupcollide() to detect collisions between Sprites in Groups:

collide = pygame.sprite.groupcollide(bullets, enemiesList, False, False)
  • Related