Title: How to access or influence variables of other classes when you can't access their instances
Tags: python,pygame

Question: I am building a game which has a level where bombs are thrown onto the player. I am having a bit of trouble in that. Ideally, the game should check whether the player is within the blast_radius of the bomb when the blast_time goes off (gets <= 0), and if yes, it should decrease a life from the player's lives.
This needs a function which checks for (blast_time <= 0) and then looks if the player is within the blast radius of the bomb. If yes, then it just reduces a life from the player (self.lives -= 1).
The problem I'm having is

If I try to add the player_bomb_collision function into the Game class, I'm not able to access the blast_time for each bomb sprite (in the sprite Group). I can't directly access it using the instance because a new instance with the same name is created after "bomb_spawn_cooldown" goes off (<= 0). Thus reseting the "blast_time". And I can't implement a cooldown function in the game class since I need every bomb to have & follow their own cooldown.

And if I add the player_bomb_collision function into the Bomb class, I can't tell the Game class to decrease a life. Since I don't have access to the "lives" variable (Yes i can take the lives var as a function argument but I can't return it because of how pygame works). Also, I can't create a new "lives" variable in the Bomb class because it would just reset the lives when a new Bomb instance is created.


In both cases I am unable to access or influence variables in other classes due to the timer creating new instances, overwriting the same variable as the previous instance.
The below code is the very core code related to the problem (or so i hope).I removed other functions unrelated to the problems such as movements or spawning control, positioning, etc
import pygame
pygame.init()

screen = pygame.display.set_mode((screen_width, screen_height))
clock = pygame.time.Clock()
screen_width = 1080
screen_height = 960

class Game():
import pygame
pygame.init()

screen = pygame.display.set_mode((screen_width, screen_height))
clock = pygame.time.Clock()
screen_width = 1080
screen_height = 960

# Game Class

class Game():
    def __init__(self):
        # Player Setup
        player_sprite = Player(screen, pos = (500,500))
        self.player = pygame.sprite.GroupSingle(player_sprite)

        #Bomb Setup
        self.bomb = pygame.sprite.Group()
        self.createBomb()
        self.bomb_spawn_cooldown = 20

        # Score & Lives
        self.lives = 5

    def createBomb(self):
        if self.bomb_spawn_cooldown <= 0:
            self.bomb_sprite = Bomb(screen)
            self.bomb.add(self.bomb_sprite)
            self.bomb_spawn_cooldown = 80

        self.bomb_spawn_cooldown -= 1

    def run(self):
        # self.player_bomb_collision()

        self.bomb.update()
        self.bomb.draw(screen)

        self.player.update()
        self.player.draw(screen)


def gameloop():
    exitgame = False
    FPS = 60
    game = Game()

    while not exitgame:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

        screen.fill('Black')
        game.run()

        pygame.display.flip()
        clock.tick(FPS)

if __name__ == "__main__":
    gameloop()

# Bomb Class
import pygame

class Bomb(pygame.sprite.Sprite):
    def __init__(self, display_surface, blast_time = 200, size = (25,25), radius = 25):
        super().__init__()
        self.display_surface = display_surface

        self.image = pygame.Surface(size)
        self.image.fill('red')
        self.rect = self.image.get_rect(center = (520,520))

        self.blast_time_remaining = blast_time
                self.blast_radius = radius


    def blast(self):
        if self.blast_time_remaining <= 0:
            print('blast!')
            self.kill()

        self.blast_time_remaining -= 1

    def update(self):
        self.blast()

def blast(self, player_sprite):
        if self.blast_time_remaining == 0:

            self.image.fill('red')
            hitbox = (self.rect.x - self.blast_radius, self.rect.y - self.blast_radius, self.rect.size[0] + (self.blast_radius*2), self.rect.size[1] + (self.blast_radius*2))
            self.hitbox_rect = pygame.draw.rect(self.display_surface, 'orange', hitbox , 1)

            if pygame.Rect.colliderect(player_sprite.sprite.rect, self.hitbox_rect):
                print('Took a Bomb to the face')
                # self.lives -= 1
                # self.is_damaged = True
                # print(self.lives)
                
            self.kill()

        self.blast_time_remaining -= 1

Above is the basic idea of what the function should do (note- this function is implemented in the Bomb class).
What I am 90% sure of is that I cannot access/influence class variables without their respective instances. I have tried returning the variables but it did not work because of how inherting classes & pygame works. Only methods i can think of creating a global variable and importing it again & again (Neither do I like this method nor am I gonna do it).
Thats about it. Please if you know anyway to solve this problem or there's anything to tell me, please do so. Thanks

Answer: An update to the question, I have figured out how to get around it and honestly it was much simpler than I thought. Thank you VantaTree#2609 (on discord) for pointing that out.
I had to do a couple of things to solve it.

First, I moved all the implementation of players' lives, damage, cooldown, etc to the player class (I don't know why they were in the Game class to begin with).
Then, I moved all obstacle collisions into their respective classes (yes there are more than just Bombs, but i was only having problem with implementing the Bomb mechanic).
Afterwards I sent the self.player_sprite (the player class instance) as an argument in the obstacle classes (Bomb in this case) and sent the self.player (spritegroup) as an argument in their respective update methods. Example - self.bomb.update(self.player)

And voila, It worked. Please let me know if this was confusing or you need to see the final code.