Search code examples
pythongridpygame

How do I change the color of a single rectangle in a grid?


I've already programmed a grid, but now I want to change the color of a single rectangle in the grid.

x = 5
y = 5

height = 30
width = 50
size = 20
color = (255,255,255)
new_color = (255,255,0)

screen.fill((0,0,0))

def draw_grid():
    for y in range(height):
        for x in range(width):
            rect = pygame.Rect(x * (size + 1),y * (size + 1),size,size)
            pygame.draw.rect(screen,color,rect)
            x += 20
            rects.append((rect,color))
        y += 20

rects = []
colored_rects = []

while 1:

    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()

    draw_grid()

    if pygame.mouse.get_pressed()[0]:
        mouse_pos = pygame.mouse.get_pos()
        for i,(rect,color) in enumerate(rects):
            if rect.collidepoint(mouse_pos):
                rects[i] = (rect,new_color)
                colored_rects.append((rect,new_color))


    for rect,color in rects:
        pygame.draw.rect(screen,color,rect)
    for rect,new_color in colored_rects:
        pygame.draw.rect(screen,new_color,rect)

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

Now I only want to change one rectangle when I click on it, but later they must change automatically (for example when there are three rectangles touching in the same color, they all must become white). I've updated a little bit, but there are still some problems. For example: You have to click on the rectangle till it changes color, and it takes to much time te change color.


Solution

  • One solution would be to store the rects together with their color in tuples. If the mouse button is pressed, you iterate over the rectangles list, if a rectangle collides with the mouse, you create a tuple with the rect and the new color and replace the tuple at the current index.

    import sys
    import pygame as pg
    
    
    def main():
        screen = pg.display.set_mode((640, 480))
        clock = pg.time.Clock()
    
        height = 30
        width = 50
        size = 20
        color = (255, 255, 255)
        new_color = (255, 255, 0)
    
        rectangles = []
        for y in range(height):
            for x in range(width):
                rect = pg.Rect(x * (size+1), y * (size+1), size, size)
                # The grid will be a list of (rect, color) tuples.
                rectangles.append((rect, color))
    
        done = False
    
        while not done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
    
            if pg.mouse.get_pressed()[0]:
                mouse_pos = pg.mouse.get_pos()
                # Enumerate creates tuples of a number (the index)
                # and the rect-color tuple, so it looks like:
                # (0, (<rect(0, 0, 20, 20)>, (255, 255, 255)))
                # You can unpack them directly in the head of the loop.
                for index, (rect, color) in enumerate(rectangles):
                    if rect.collidepoint(mouse_pos):
                        # Create a tuple with the new color and assign it.
                        rectangles[index] = (rect, new_color)
    
            screen.fill((30, 30, 30))
    
            # Now draw the rects. You can unpack the tuples
            # again directly in the head of the for loop.
            for rect, color in rectangles:
                pg.draw.rect(screen, color, rect)
    
            pg.display.flip()
            clock.tick(30)
    
    
    if __name__ == '__main__':
        pg.init()
        main()
        pg.quit()
        sys.exit()