Search code examples
pythonpygamepython-class

Attribute Error: Object has no attribute '_Sprite__g' , while creating alien invasion


I was creating Alien invasion and I encountered this error of " object has no attribute '_sprite__g', please help me

class Game():
def __init__(self, screen, screen_height, screen_width):
    self.dir = os.path.dirname(__file__)
    
    self.display_message(screen,"Enter name", 50, WHITE, 600,500)
    pygame.display.flip()
    self.name = input("Enter your name")
    self.player_unshield_image = self.image('Traveller.png',75,75)
    self.player_shield_image = self.image('Zhongli.png',75,75)
    
    self.green_slave = self.image('Sara.png', 30,30)
    self.blue_slave = self.image('Yae.png',30,30)
    self.grey_slave =self.image('Itto.png',50,50)
    self.purple_slave = self.image('Raiden.png',120,120)
    
    self.fireball =self.image('Bullet.png',20,40)
    self.mango =self.image('YellowBullet.png',30,80)
    self.sun = self.image('OrangeBullet.png', 20,90)
    self.bullet_dict ={None:self.fireball, 'WideBullet':self.mango, 'PierceBullet':self.sun}

    self.powerup_wide =self.image('THICC.png',30,30)
    self.powerup_pierce =self.image('Pierce.png',30,30)
    self.powerup_shield =self.image('Noelle.png',30,30)
    self.powerup_add_score = self.image('Extra.png',30,30)
    
    self.high_score = 0

    self.shoot = self.sound('Pew.wav')
    self.explode =self.sound('BOOM_BOOM_BAKUDAN.wav')

    self.reset()

def reset(self):
    self.normal =(2,1, self.green_slave)
    self.tank =(1,2,self.blue_slave)
    self.rock =(5,3, self.grey_slave)
    self.boss =(7,10, self.purple_slave)

    self.all_sprites = pygame.sprite.Group()
    self.Slaves = pygame.sprite.Group()
    self.Ammo = pygame.sprite.Group()
    self.Powerup =pygame.sprite.Group()

    self.game_active =False
    self.Score = 0
    self.ammo_powerup =None
    self.Max_level =10
    self.level =0
    self.level_text_timer = 0
    self.max_ammo = 6
    self.ammo_num =self.max_ammo
    self.ammo_reload_timer = 0
    self.ammo_text =WHITE 
    self.game_played =False

    self.clock = pygame.time.Clock()
    self.clock.tick(FPS)
    self.player =Player(self.player_unshield_image, self.player_shield_image)
    self.all_sprites.add(self.player)

    for i in range(2) :
        powerup = Powerups(self.powerup_shield, self.powerup_pierce, self.powerup_add_score, self.powerup_wide)
        self.all_sprites.add(powerup)
        self.Powerup.add(powerup)
        

def image(self, image_name, width, height):
    image_dir =os.path.join(self.dir, 'Images')
    image = pygame.image.load(os.path.join(image_dir, image_name)).convert()
    scaled_image =pygame.transform.scale(image,(width,height))
    return scaled_image

def sound(self, sound_name):
    sound_dir=os.path.join(self.dir, 'Sounds')
    return pygame.mixer.Sound(os.path.join(sound_dir, sound_name))

def create_slaves(self, width, height, offset_a, offset_b, distance, slave_info):
    speed =slave_info[0]
    health =slave_info[1]
    slave_image =slave_info[2]
    for x in range (width):
        for y in range(height):
            d= Slaves(offset_a +x*distance, offset_b +y*distance, speed, health, slave_image)
            self.Slaves.add(d)
            self.all_sprites.add(d)

def display_message(self, surf, message, size, color, j, k):
    font = pygame.font.SysFont("Arial", size)
    message_surface = font.render(message, True, color)
    message_rect = message_surface.get_rect()
    message_rect.midtop = (j, k)
    surf.blit(message_surface, message_rect)

def instructions(self):
    print('''Welcome to space invaders!
    Use Arrow keys to shoot, collect the coming powerups to gain special buffs
    figure out the point distribution yourself
    powerups include:
    pierce bullet, wide bullet, extra score addition
    the game has 10 levels, there are no extra lives
    last but most important, the game is over when you lose
    good luck!(probably)''')

def get_events(self, button):
    for event in pygame.event.get():
        if event.type == QUIT:
            with open(os.path.join(self.dir, 'high_scores.txt'), 'a+') as score_file:
                score_file.write(self.name + "," + str(self.high_score)+ "," + (self.level)+ "\n")
            return False
        elif event.type == KEYDOWN:
            if event.key == K_SPACE and self.ammo_num > 0:
                img =self.bullet_dict[self.ammo_powerup]
                ammo = Ammo(self.player.rect.center, self.player.rect.top, self.ammo_powerup, img)
                self.ammo_powerup = None
                self.all_sprites.add(ammo)
                self.Ammo.add(ammo)
                self.ammo_num -=1
                self.shoot.play()
            else:
                pass
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y =pygame.mouse.get_pos()
            self.check(button, mouse_x, mouse_y)
    return True

def check(self, button, x, y):
    clicked = button.rect.collidepoint(x,y)
    if clicked and not self.game_active:
        self.all_sprites.empty()
        self.Slaves.empty()
        self.Ammo.empty
        self.reset()
        self.game_active = True
        pygame.mouse.set_visible = False
        
def start(self):
    self.all_sprites.update()
    if len(self.Slaves) ==0:
        self.Ammo.empty()
        self.level +=1
        self.level_text_timer = 0
        if self.level ==1:
            self.create_slaves(10,5, 300, 40, 60, self.normal)
            self.game_played =True
        elif self.level ==2:
            self.create_slaves(10,4,300,45,60,self.normal)
            self.create_slaves(20,5, 400, 55,70, self.normal)
        elif self.level ==3:
            self.create_slaves(12,3,300,45,60, self.normal)
            self.create_slaves(20,5,400,55,70, self.normal)
            self.create_slaves(15,5,350,45,65, self.tank)
            self.max_ammo = 5
        elif self.level ==4 :
            self.create_slaves(13,4,300,45,65, self.normal)
            self.create_slaves(20,5,400,55,70, self.tank)
            self.create_slaves(15,5,400, 55,80, self.rock)
        elif self.level == 5:
            self.create_slaves(14,4,300,45,60, self.normal)
            self.create_slaves(11,3,250,35,60, self.normal)
            self.create_slaves(15,4,350,40,55, self.rock)
            self.create_slaves(13,5,400,35,65,self.rock)
        elif self.level == 6:
            self.create_slaves(12,4,300,45,60, self.normal)
            self.create_slaves(15,3,300,45,60, self.tank)
            self.create_slaves(15,4,350,35,50, self.rock)
            self.create_slaves(14,5,350,35,50, self.normal)
        elif self.level ==7:
            self.create_slaves(13,3,350,50,45, self.normal)
            self.create_slaves(15,3,300,45,60, self.tank)
            self.create_slaves(15,4,350,35,50, self.rock)
            self.create_slaves(17,4,400,45,50, self.rock)
        elif self.level ==8:
            self.create_slaves(12,4,300,45,60, self.normal)
            self.create_slaves(15,3,300,45,60, self.tank)
            self.create_slaves(15,4,350,35,50, self.rock)
            self.create_slaves(14,5,350,35,50, self.tank)
            self.create_slaves(12,3,300,45,55, self.normal)
        elif self.level == 9:
            self.create_slaves(16,3,300,45,60, self.tank)
            self.create_slaves(15,3,300,45,60, self.tank)
            self.create_slaves(15,4,350,35,50, self.rock)
            self.create_slaves(14,5,350,35,50, self.normal)
            self.create_slaves(16,7, 350,60,70, self.boss)
            self.max_ammo = 8
        elif self.level ==10:
            self.game_active =False
        self.ammo_num = self.max_ammo

    for slave in self.Slaves:
        attacks = pygame.sprite.collide_rect(self.player, slave)
        if attacks:
            slave.kill()
            if self.player.shielded:
                self.explode.play()
                self.player.unshield()
                self.Score += slave.worth

                if self.Score >self.high_score:
                    self.high_score = self.Score
            else:
                self.game_active =False
        if slave.rect.bottom > Height:
            self.game_active =False
        
        for ammo in self.Ammo:
            ammo_hit = pygame.sprite.collide_rect(ammo, slave)
            if ammo_hit:
                ammo_health_decrease = slave.slave_hp
                slave.slave_hp -= ammo.ammo_health
                ammo.ammo_health = ammo_health_decrease

                if ammo.ammo_health <= 0 :
                    ammo.kill()
                    
        for slave in self.Slaves:
            if slave.slave_hp <= 0:
                slave.kill()
                self. explode.play()
                self.Score +=slave.worth
                if self.Score > self.high_score:
                    self.high_score = self.Score
    
    for pu in  self.Powerup:
        hits_pu = pygame.sprite.spritecollide(pu, self.Ammo, False, False)

        if hits_pu:
            if pu.Powerup == 'shield':
                self.player.shield()
            elif 'ammo' in pu.powerup:
                self.ammo_powerup = pu.powerup
            elif pu.powerup == 'Score':
                self.Score += 5
                if self.Score >self.high_score:
                    self.high_score = self.Score
            pu.include_shield = not self.player.shielded
            pu.randomize()

    if self.ammo_num < self.max_ammo:
        self.ammo_reload_timer +=1
        if self.ammo_reload_timer >= 40 :
            self.ammo_num += 1
            self.ammo_reload_timer = 0
    
    if self.level >= self.Max_level:
        self.game_active = False

def display(self, screen, button):
    screen.fill(BLACK)

    if not self.game_active:
        if self.game_played:
            self.end_game(screen)
        button.draw_button()
        pygame.mouse.set_visible(True)
    else:
        self.display_message(screen, "Score:" + str(self.Score), 28, BLUE, 110,110 )
        self.display_message(screen, "High Score:" + str(self.high_score), 30, ORANGE, 120,120)
        self.display_message(screen, "Level:" + str(self.level), 25, MAGENTA, 100,100)
        if self.ammo_powerup == None:
            self.ammo_text_color = WHITE
        elif self.ammo_powerup == 'WideBullet':
            self.ammo_text_color = ORANGE 
        elif self.ammo_powerup == 'PierceBullet':
            self.ammo_text_color = RED 
        self.display_message(screen, str(self.ammo_num) + "/" + str(self.ammo_reload_timer), 20, GRAY, 500,500)
        self.level_text_timer += 1
        if self.level_text_timer < 600 :
            self.display_message(screen, 'Level:' + str(self.level), 25, WHITE, 500,500 )
            self.level_text_timer += 1

    pygame.display.flip()

def end_game(self, screen):
    screen.fill(BLACK)
    self.display_message(screen, "YOU DIED!", 58, MAGENTA, 650,700)
    self.display_message(screen, "Final Score:" + str(self.Score), 30, ORANGE, 450,500)
    self.display_message(screen, "High Score:" + str(self.high_score), 40, CYAN, 500,550)
    self.display_message(screen, "Higest Floor Reached:" + str(self.level) + "/" +str(self.Max_level), 30, WHITE, 500,500)

here is the Screenshot of the error:

This is the picture of the error

Any suggestions are helpful, please help

The Error is present in "def create_Slaves()" and on the line, self.Slaves.add(d)


Solution

  • Please try this in your init function

    class Game(pygame.sprite.Sprite):
        def __init__((self, screen, screen_height, screen_width):
            super(Sprite, self).__init__()
    

    Maybe your only problem is that you have to call it from the parent function