1

I am making an application that demonstrates sorting algorithms in pygame. I have "Elements" that need to be drawn on the screen 1 by 1 so the user can see what is going on. I have tried doing this, but what happens is that all the elements get drawn on the screen at the same time. This all happens in initialize_elements(). What is supposed to happen is that a new element is created, is then drawn to the screen, and then the display is updated so the user can see the individual element created 1 by 1. Instead, all the elements appear on the screen at the same time. I have tried using pygame.time.delay(100) but that didn't work. I don't know how to stop this from happening.

Here is my code:

import pygame
import random

class Element:

    def __init__(self, left_in, width_in, screen_height, screen):
        self.top = 0
        self.left = left_in
        self.height = random.randrange(screen_height / 4, screen_height * 0.75)
        self.color = (0,0,255)
        self.border = 5
        self.surface = pygame.Surface([width_in, self.height])
        self.surface.fill((self.color))
        self.draw(screen, self.color, left_in, 0)

    def draw(self, screen, color, x, y):
        screen.blit(self.surface, (self.left, self.top))


screen_width = 1400
screen_height = 900
screen = pygame.display.set_mode((screen_width, screen_height))

num_elements = 20 # Will be determined at start screen

def main():
    pygame.init()
    
    clock = pygame.time.Clock()
    FPS = 30
    
    elements = []
    
    pygame.display.set_caption("Sorting Visualization")

    screen.fill((255, 255, 255))

    def initialize_elements(desired_width):
        i = 0
        while i < num_elements:
            if i == 0:
                elements.append(Element(screen_width / 5, desired_width, screen_height, screen))
            else:
                elements.append(Element(elements[i - 1].left + desired_width, desired_width, 
                                        screen_height, screen))
            i += 1
            pygame.display.update()

    # Initializing Elements
    desired_width = (screen_width - (2/5)*screen_width) / num_elements
    initialize_elements(desired_width)
    
    while(True):
        clock.tick(FPS)
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        pygame.display.update()
            
        
main()
  • Have you considered creating a list of `Element`s before the main loop starts, then just calling Element.draw() at the correct time? I think part of your problem is the Element class wants to draw directly to the screen as part of `Element.__init__()` – Kingsley Oct 20 '20 at 04:11

2 Answers2

3

You need to handles the events by pygame.event.pump(), before the update of the display becomes visible in the window.

See pygame.event.pump():

For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.

If you want to display the lines and delay the game, then you've to update the display and handle the events.

while i < num_elements:
    if i == 0:
        elements.append(Element(screen_width / 5, desired_width, screen_height, screen))
    else:
        elements.append(Element(elements[i - 1].left + desired_width, desired_width, 
                                        screen_height, screen))
    i += 1

    pygame.display.flip()
    pygame.time.delay(delay * 100) # 100 milliseconds = 0.1 second
    pygame.event.pump()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
0

You can call sleep in the loop that draws the lines.

Try this code:

def initialize_elements(desired_width):
    i = 0
    while i < num_elements:
        if i == 0:
            elements.append(Element(screen_width / 5, desired_width, screen_height, screen))
        else:
            elements.append(Element(elements[i - 1].left + desired_width, desired_width, 
                                    screen_height, screen))
        i += 1
        pygame.display.update()
        time.sleep(.2)   # add this line
Mike67
  • 11,175
  • 2
  • 7
  • 15