1

I am trying to blit multiple images of a moving car, using a for loop over the filenames of the images. However, it would just draw the screen but not actually show/blit the images. I am using python3.6 .

Here is my code.

import pandas as pd
import pygame

# BLACK = (  0,   0,   0)
# WHITE = (255, 255, 255)
# BLUE =  (  0,   0, 255)
# GREEN = (  0, 255,   0)
# RED =   (255,   0,   0)

df = pd.read_csv('./result.csv')

preds = df['Predicted Angles']
true = df['Actual Angles']
filenames = df['File']

pygame.init()
size = (640, 320)
pygame.display.set_caption("Data viewer")
screen = pygame.display.set_mode(size, pygame.DOUBLEBUF)
myfont = pygame.font.SysFont("monospace", 15)

for i in range(len(list(filenames))):
    img = pygame.image.load(filenames.iloc[i])
    screen.blit(img, (0, 0))
    pygame.display.flip()

View of the results.csv

1 Answers1

0

First load all images and put them into a list or other data structure, then assign the current image to a variable and change it after the desired time interval (you can use one of these timers).

I'm just using some colored pygame.Surfaces in the example below and change the current image/surface with the help of a custom event and the pygame.time.set_timer function which adds the event to the event queue when the specified time has passed.

import pygame as pg


pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')

images = []
# Three differently colored surfaces for demonstration purposes.
for color in ((0, 100, 200), (200, 100, 50), (100, 200, 0)):
    surface = pg.Surface((200, 100))
    surface.fill(color)
    images.append(surface)

index = 0
image = images[index]
# Define a new event type.
CHANGE_IMAGE_EVENT = pg.USEREVENT + 1
# Add the event to the event queue every 1000 ms.
pg.time.set_timer(CHANGE_IMAGE_EVENT, 1000)

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        elif event.type == CHANGE_IMAGE_EVENT:
            # Increment the index, use modulo len(images)
            # to keep it in the correct range and change
            # the image.
            index += 1
            index %= len(images)
            image = images[index]  # Alternatively load the next image here.

    screen.fill(BG_COLOR)
    # Blit the current image.
    screen.blit(image, (200, 200))
    pg.display.flip()
    clock.tick(30)

pg.quit()
skrx
  • 19,980
  • 5
  • 34
  • 48
  • Could you please explain why exactly was event.type needed? Isn't blit already there to refresh images? – nocturnal_study May 23 '18 at 13:40
  • In a usual game, you handle the events in the queue, run the game logic, clear the screen, then blit the images/surfaces and finally call `pygame.display.flip` to update the computer display. You do all of that once per frame and usually try to achieve 30 - 60 frames per second, so that the game's responsiveness is acceptable. In your example, you just blit all images as fast as possible in the `for` loop without a delay, so the user can probably only see some flickering images before the game closes. – skrx May 23 '18 at 14:25
  • Actually, if you just want to blit one image after the other without any user interaction and then quit, you can keep using the `for` loop and just call [`pygame.time.wait`](https://www.pygame.org/docs/ref/time.html#pygame.time.wait) once per iteration to slow the program down. However, the window will be unresponsive during that time and can also freeze if you don't handle the events (you should at least call [`pygame.event.pump`](https://www.pygame.org/docs/ref/event.html#pygame.event.pump) every frame). – skrx May 23 '18 at 14:25
  • Yes that is what I am trying to do. Because I have about 5000 images to show as and storing the images in a list beforehand is going to cause a lot of delay before the images/video start playing. So I am trying to not do away from the for loop and keep blitting as I read the images. – nocturnal_study May 23 '18 at 14:34
  • I think it would still be better to use the common main `while` loop and a timer. Just load the next image after the specified time interval, blit it and call `pygame.display.flip`. If you're not drawing anything else onto the screen, you can do that only once when the image gets changed instead of once per frame. – skrx May 23 '18 at 14:50
  • I got the program working with the pump and wait as you suggested. Thanks a lot for that! :D – nocturnal_study May 23 '18 at 16:01