I haven't found any similar questions and I'm struggling to understand what my code is doing right now.
I'm writing a small puzzle game with Pygame, which is also my first foray into object-oriented programming. Pygame provides Rect objects to define a portion of the screen (with attributes like x, y, width, height, and so on). Since my game is text-heavy, I created an object Region to group a Rect object with a font object and some color information for when I need to blit to screen:
def __init__(self, rect, bg_color, font, font_color):
self.rect = rect
self.bg_color = bg_color
self.font = font
self.font_color = font_color
I then created a Layout class that would hold a collection of Region objects, along with a centralized color palette and some methods for redrawing screen elements. Since this game only has one "board," I only need one Layout object, so I made the Region objects class attributes:
...
progress_box: region(pygame.Rect(5, 340, 275, 10),
colors["white"],
pygame.font.SysFont('arialblack', 12),
colors["black"])
(Snipped out the other Region objects for readability.)
Later in the code, I have a function that draws a progress bar in progress_box like so:
def display_progress(score, viz, max_score):
progress = round(score/max_score, 4)
progress_bar = region(viz.boxes["progress_box"].rect, "gold", None, None)
progress_bar.rect.width = int(progress * progress_box.rect.width)
viz.box_blit(progress_bar) ##viz is my layout object
What should happen, as I understand it, is that progress_bar copies the rect attribute from progress_box object, but then I reset the width attribute to a percentage of the progress_box.rect width. I'm not assigning anything to progress_box itself, and progress_bar is a Region object not connected to the Layout class, so I assumed that progress_box.rect.width would remain constant over every loop.
Instead, whatever value I assign to progress_bar.rect.width is also assigned to progress_box.rect.width. That means, of course, that on the first pass through the loop, both those values are set to 0 because the player's score is 0, and after that they can never change.
The function works as intended if I change progress_bar.rect.width = int(progress * progress_box.rect.width) to progress_bar.rect.width = int(progress * 275), but that doesn't explain to me why the variable is changing when I don't assign anything directly to it. I understand that these attributes are only initialized once, so any change to a class attribute will persist through every loop -- I'm just not sure why it's changing in the first place.