Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this code produce shapes with random colors?

I'm working from the book "Program Arcade Games With Python And Pygame" and working through the 'lab' at the end of Chapter 12: Introduction to Classes.

This code I've written for it randomises the coordinates size and movement direction for each shape created in 'my_list' by calling its constructor but not the colour, all the shapes created have the same colour, why is this?



import pygame
import random

# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

class Rectangle():
    x = 0
    y = 0
    width = 10
    height = 10
    change_x = 2
    change_y = 2
    color = [0, 0, 0]

    def __init__(self):
        self.x = random.randrange(0, 700)
        self.y = random.randrange(0, 500)
        self.change_x = random.randrange(-3., 3)
        self.change_y = random.randrange(-3., 3)
        self.width = random.randrange(20, 70)
        self.height = random.randrange(20, 70)
        for i in range(3):
            self.color[i] = random.randrange(0, 256)


    def draw(self, screen):
        pygame.draw.rect(screen, self.color, [self.x, self.y, self.width, self.height], 0)

    def move(self):
        if self.x < 0:
            self.change_x *= -1
        if self.x > 700-self.width:
            self.change_x *= -1
        if self.y < 0:
            self.change_y *= -1
        if self.y > 500-self.height:
            self.change_y *= -1
        self.x += self.change_x
        self.y += self.change_y

class Ellipse(Rectangle):
    def draw(self, screen):
        pygame.draw.ellipse(screen, self.color, [self.x, self.y, self.width, self.height], 0)



pygame.init()

# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)

pygame.display.set_caption("My Game")

# Loop until the user clicks the close button.
done = False

# Used to manage how fast the screen updates
clock = pygame.time.Clock()

my_list = []

for i in range(10):
    my_list.append(Rectangle())

for i in range(10):
    my_list.append(Ellipse())


# -------- Main Program Loop -----------
while not done:
    # --- Main event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

    # --- Game logic should go here

    # --- Screen-clearing code goes here

    # Here, we clear the screen to white. Don't put other drawing commands
    # above this, or they will be erased with this command.

    # If you want a background image, replace this clear with blit'ing the
    # background image.
    screen.fill(WHITE)

    # --- Drawing code should go here
    for shape in my_list:
        shape.draw(screen)
        shape.move()
    # --- Go ahead and update the screen with what we've drawn.
    pygame.display.flip()

    # --- Limit to 60 frames per second
    clock.tick(60)

# Close the window and quit.
pygame.quit()```
like image 547
Tom Edwards Avatar asked Aug 21 '19 20:08

Tom Edwards


Video Answer


1 Answers

The instance attribute self.color is never created. The existing variable color is a class attribute. Read about the difference of Class and Instance Variables. A class attribute exists only once and (of course) has the same value in each instance when it is read. An instance variable exists per instance of the class and can have a different value in each instance.

Create the list of color channels by:

class Rectangle():

    def __init__(self):

        # [...]

        self.color = [0, 0, 0]
        for i in range(3):
            self.color[i] = random.randrange(0, 256)

respectively

class Rectangle():

    def __init__(self):

        # [...]

        self.color = [random.randrange(0, 256) for _ in range(3)]
like image 193
Rabbid76 Avatar answered Oct 17 '22 18:10

Rabbid76