1

I have a group of rects, they display in a row. I want them to change their colour when they have been clicked, until they are clicked again

I have this code so far to create the sprites:

class DrawableRect(pygame.sprite.Sprite):
    def __init__(self,color,width,height,value=0):
        super().__init__()
        self.image = pygame.Surface([width, height])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.value = value
        self.x = 0
        self.y = 0
    def change_value(self,color,value):
        self.image.fill(color)
        self.value=value

def DrawRects(start_x, start_y, rect_spacing, colour_list):
    current_x_pos = start_x
    for rect_num in range(0,8):
        rect = DrawableRect(colour_list[rect_num], boxW, boxH)
        rect.rect.x = current_x_pos
        rect.rect.y = start_y
        current_x_pos = current_x_pos + rect.rect.width + rect_spacing
        rects.add(rect)
    rects.draw(screen)

The idea of the app is for each rectangle to represent a bit, and when pressed it alternates between 0 and 1, the makeup of each bit displays the decimal equivalent somewhere.

I read that groups are unordered therefore indexing wouldn't work, is that true?

  • check out this answer: https://stackoverflow.com/questions/49544599/pygame-text-button-gone-wrong/49547093#49547093 – gnawydna Dec 08 '18 at 19:28
  • @silicon That helps a lot! Now I created a function in my DrawableRect class called `change_state` and basically it will reverse its own state (swap between 2 colours), how can I access the colour property of that rect? – GaaraOfTheSand Dec 08 '18 at 19:40
  • @silicon I am thinking of doing: `for box in rects: if box.check() == True: box.change_state(box.color)` But I can't find a way to get the colour value of the particular rect from the sprite group. – GaaraOfTheSand Dec 08 '18 at 19:48
  • you don't have to use sprites – gnawydna Dec 09 '18 at 17:00
  • you can just use lists and make the class an `object` – gnawydna Dec 09 '18 at 17:01

1 Answers1

1

Here's an example I've modified to suit your purposes. I have a bunch of sprites (coloured rectangles) in a sprite group and I change* the colour of any sprite that collides with the mouse pointer when a mouse button is pressed.

Here it is in action

Here's the code, you're probably most interested in the change_color() method and the MOUSEBUTTONUP event handling code.

import random
import pygame

screen_width, screen_height = 640, 480
def get_random_position():
    """return a random (x,y) position in the screen"""
    return (random.randint(0, screen_width - 1),  #randint includes both endpoints.
            random.randint(0, screen_height - 1)) 
color_list = ["red", "orange", "yellow", "green", "cyan", "blue", "blueviolet"]
colors = [pygame.color.Color(c) for c in color_list]

class PowerUp(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        width, height = 64, 32
        self.image = pygame.Surface([width, height])
        self.clicked = False  # track whether we've been clicked or not
        # initialise color
        self.color = random.choice(colors)
        self.image.fill(self.color)
        # Fetch the rectangle object that has the dimensions of the image
        self.rect = self.image.get_rect()
        # then move to a random position
        self.update()

    def update(self):
        #move to a random position
        self.rect.center = get_random_position()

    def random_color(self):
        # randomise color
        self.clicked = not self.clicked
        if self.clicked:
            color = random.choice(colors)
        else:
            color = self.color
        self.image.fill(color)

if __name__ == "__main__":
    pygame.init()
    screen = pygame.display.set_mode((screen_width, screen_height))
    pygame.display.set_caption('Sprite Color Switch Demo')
    clock = pygame.time.Clock() #for limiting FPS
    FPS = 60
    exit_demo = False

    pygame.key.set_repeat(300, 200)

    #create a sprite group to track the power ups.
    power_ups = pygame.sprite.Group()
    for _ in range(10):
        power_ups.add(PowerUp()) # create a new power up and add it to the group.

    # main loop
    while not exit_demo:
        for event in pygame.event.get():            
            if event.type == pygame.QUIT:
                exit_demo = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    exit_demo = True
                elif event.key == pygame.K_SPACE:
                    power_ups.update()
            elif event.type == pygame.MOUSEBUTTONUP:
                # check for collision
                for p in power_ups:
                    if p.rect.collidepoint(event.pos): # maybe use event?
                        p.random_color()

        screen.fill(pygame.Color("black")) # use black background
        power_ups.draw(screen)
        pygame.display.update()
        clock.tick(FPS)
    pygame.quit()
    quit()

Let me know if you have any questions. Obviously this doesn't do row alignment of the sprites, I think you have a handle on that. I would suggest that you have all of your screen drawing operations in one place so your code can be clearer.

*The new colour is randomised from a short list, so there's a 14% chance it won't change from the starting colour.

import random
  • 3,054
  • 1
  • 17
  • 22