prue
prue

Reputation: 13

Draw lines with time delay pygame

I want to draw multiple lines with a time delay. I'm using for loop to for the x and y coordinates.I'm searching for a solution to draw those lines with a time delay between them(eg 1 second). Here is my code:

import pygame,sys
pygame.init()

screen = pygame.display.set_mode((1600, 900)) 
RED = (230, 30, 30)

background_image = pygame.image.load("image.jpg")
background_image = pygame.transform.scale(background_image, (1600,900))

clock = pygame.time.Clock()

# Main loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
                sys.exit()
        # Fill the background
         screen.blit(background_image, [0, 0])
         x= [60,70,80]
         y= [500,600,700]
         for x,y in zip(x,y):
                pygame.draw.line(background_image, RED,(x,y),(900,1280), 10)
                pygame.display.update()
                pygame.time.delay(10)
# Update the screen
        pygame.display.flip()

`

Upvotes: 1

Views: 1095

Answers (2)

skrx
skrx

Reputation: 20438

You have to draw the lines on the screen instead of the background_image. 500 milliseconds are a half second (10 ms is a bit fast). Also, don't use the same variable names for the lists and the coords.

import sys
import pygame


pygame.init()

screen = pygame.display.set_mode((1024, 768)) 
RED = (150, 30, 30)

# Replaced the image with a Surface to test the code.
background_image = pygame.Surface((1024, 768))  
background_image.fill((50, 90, 140))

clock = pygame.time.Clock()
xs = [60, 70, 80, 90]
ys = [500, 600, 700, 800]

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

    screen.blit(background_image, [0, 0])

    for x, y in zip(xs, ys):
        # Draw the lines on the screen not the background.
        pygame.draw.line(screen, RED, (x, y), (400, 480), 10)
        pygame.display.update()
        pygame.time.delay(500)

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

This version is still problematic, because you stop the execution of the rest of the main loop when the for loop runs. That means you can't quit or handle other events during that time.

I've got a more complex example for you with a timer variable. You subtract the delta time (the time that passed since the last tick) from it and when it's below 0 you add another coordinate to a list which you use for the drawing.

import sys
import pygame


pygame.init()

screen = pygame.display.set_mode((1024, 768))
RED = (120, 30, 30)

background_image = pygame.Surface((1024, 768))
background_image.fill((50, 90, 140))

clock = pygame.time.Clock()

xs = [60, 70, 80, 90]
ys = [400, 500, 600, 700]
xys = zip(xs, ys)
startpoints = []  # This holds the current startpoints.

dt = 0
timer = 500  # A countdown timer.

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

    timer -= dt  # Decrease timer.
    if timer <= 0:  # If timer < 0 append the next xy coords.
        try:
            # `next` just gives you the next item in the xys zip iterator.
            startpoints.append(next(xys))
        # When the zip iterator is exhausted, clear the
        # startpoints list and create a new zip iterator.
        except StopIteration:
            startpoints.clear()
            xys = zip(xs, ys)
        timer = 500  # Reset the timer.

    screen.blit(background_image, [0, 0])
    for x, y in startpoints:  # Loop over the available startpoints.
        pygame.draw.line(screen, RED, (x, y), (400, 480), 10)

    pygame.display.flip()
    dt = clock.tick(30)

Or you could do kind of the same with a custom event and pygame.time.set_timer:

add_coord_event = pygame.USEREVENT + 1
pygame.time.set_timer(add_coord_event, 500)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == add_coord_event:
            try:
                startpoints.append(next(xys))
            # When the zip iterator is exhausted, clear the
            # startpoints list and create a new zip iterator.
            except StopIteration:
                startpoints.clear()
                xys = zip(xs, ys)

Edit: Or better just create the startpoint list before the while loop and use i to slice it. Then you don't have to move the items from the iterator to the list.

xs = [60, 70, 80, 90]
ys = [400, 500, 600, 700]
startpoints = list(zip(xs, ys))
i = 0  # Current index, used to slice startpoints.

clock = pygame.time.Clock()
increase_index_event = pygame.USEREVENT + 1
pygame.time.set_timer(increase_index_event, 500)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == increase_index_event:
            i += 1
            i %= len(startpoints) + 1  # Keep i in the correct range.

    screen.blit(background_image, [0, 0])
    for x, y in startpoints[:i]:
        pygame.draw.line(screen, RED, (x, y), (500, 580), 10)

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

Upvotes: 2

Pyrolle
Pyrolle

Reputation: 51

You could either use time.wait() but that will just freeze your program for a bit or you could have a variable that holds what time the line should be draw. Basically when you draw the first line have nextLine = time.clock()+1 and have an if in your loop saying if time.clock > nextLine: then draw the next line.

Upvotes: 0

Related Questions