I understand it is not possible to have multiple windows in Pygame: Multiple Displays in Pygame
However is it possible to have multiple display objects, only one of which is actually displayed to the user?
For example, suppose I have the following code, which displays 2 green circles and 2 red triangles:
import pygame
WIDTH, HEIGHT = 800, 600
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
FPS = 60
BLACK = (0, 0, 0)
GREEN = (0, 128, 0)
RED = (255, 0, 0)
def draw_window():
# Set display background
WIN.fill(BLACK)
# Draw shapes
pygame.draw.circle(surface=WIN, center=(400, 300), radius=20, color=GREEN)
pygame.draw.polygon(surface=WIN, points=((410, 270), (460, 320), (390, 290)), color=RED)
pygame.draw.circle(surface=WIN, center=(200, 150), radius=30, color=GREEN)
pygame.draw.polygon(surface=WIN, points=((180, 190), (200, 140), (190, 270)), color=RED)
# Update display
pygame.display.update()
def main():
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
draw_window()
If I want to export the pixel data to a numpy array, and count the occurrences of each colour, I can do so with pygame.surfarray.pixels2d and np.unique:
data = pygame.surfarray.pixels2d(WIN)
unique, counts = np.unique(data, return_counts=True)
print(dict(zip(unique, counts)))
Which returns the pixel count of each colour:
{0: 474303, 32768: 3380, 16711680: 2317}
However suppose I want to count the number of pixels of each of the 4 shapes (rather than each of the colours displayed to the user), I could simply assign each shape a unique colour, for example in the code below, which would give me what I need (i.e. pixel count for each of the 4 shapes). But in doing so, I've displayed the 'wrong' colours to the user (i.e. they should seeing green and red only, not green red, yellow and blue).
Is it possible to create separate 'hidden' versions of the drawing (e.g. with different colours for the purpose of analysis), which are kept separate from the user's display? I understand I can't have multiple windows in Pygame, but I'm wondering if it's still possible to create multiple display objects - only one of which is actually shown to the user?
I imagine a workaround might be to draw each 'hidden' version for a single frame only (i.e. while I export to a numpy array), however this does not seem like a very elegant solution. The user might notice a sudden 'flash' while the hidden drawing is displayed temporarily, which would be a poor user experience.
Is there a better way to do this?
import pygame
import numpy as np
WIDTH, HEIGHT = 800, 600
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
FPS = 60
BLACK = (0, 0, 0)
GREEN = (0, 128, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)
def draw_window():
# Set display background
WIN.fill(BLACK)
# Draw shapes
pygame.draw.circle(surface=WIN, center=(400, 300), radius=20, color=GREEN)
pygame.draw.polygon(surface=WIN, points=((410, 270), (460, 320), (390, 290)), color=RED)
pygame.draw.circle(surface=WIN, center=(200, 150), radius=30, color=YELLOW)
pygame.draw.polygon(surface=WIN, points=((180, 190), (200, 140), (190, 270)), color=BLUE)
# Update display
pygame.display.update()
def main():
clock = pygame.time.Clock()
run = True
count_colours = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
draw_window()
while count_colours: # Run once only
data = pygame.surfarray.pixels2d(WIN)
unique, counts = np.unique(data, return_counts=True)
print(dict(zip(unique, counts)))
count_colours = False
if __name__ == "__main__":
main()
Output:
{0: 474303, 255: 1256, 32768: 867, 16711680: 1061, 16776960: 2513}