0

In the previous weeks, I have been working on a Tic Tac Toe game that uses pygame and moviepy. moviepy is used for the intro screen video for the user to click on and reveal the tic tac toe board, however movie py does not react to a mouseclick.

Here is the relevant code:

def introscreen():
while True:
    vid.preview()
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            vid.close()
            maingame()

Yet, the video keeps on repeating and does not react to a MOUSEBUTTONDOWN.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Im not familiar with moviePy, does it use pygame? or opencv? that could be why mousebuttondown is doing anything – The Big Kahuna Sep 05 '22 at 08:20
  • as I know `vid.preview()` runs in separated window and it blocks rest of code - so it can't run your `event`-loop. If you put `print('text') `after `preview()` then you will NOT see it. Besides `event` works only inside PyGame's window and they can't catch clicks in other windows - and as I know `pymovie` use `opencv` to display video – furas Sep 05 '22 at 10:08
  • long time ago `pygame` had module to display video but probably they removed it as not stabe. Maybe you should use `opencv` to read frame by frame (as image) and display image directly in PyGame's window. And this will need to run in loop together with `event` and it could work – furas Sep 05 '22 at 10:12
  • 1
    This [answer](https://stackoverflow.com/a/69054207/2280890) shows how to use [OpenCV](https://opencv.org/) to display the frames of your video as @furas suggests. You'll be able to handle events during playback. – import random Sep 05 '22 at 10:53

1 Answers1

1

.preview() blocks code and it can't run code which checks event.

But if it would run it then other problem could be that event checks mouse click only inside pygame window but preview uses OpenCV to display own window (probably created with PyQt)

You may use directly OpenCV to read video frame-by-frame, resize it, convert to PyGame's surface, and display it in PyGame's window - and then you can use event to stop/close it.

I keep some some code in comments because it can be useful to create more complex video - ie. you can display some elements directly on video.

import pygame
import cv2

video = cv2.VideoCapture("BigBuckBunny.mp4")

#w = video.get(cv2.CAP_PROP_FRAME_WIDTH)
#h = video.get(cv2.CAP_PROP_FRAME_HEIGHT)

fps = video.get(cv2.CAP_PROP_FPS)    # video's speed (Frames Per Second)

pygame.init()
screen = pygame.display.set_mode((800,600))

clock = pygame.time.Clock()

running = True

while running:

    for event in pygame.event.get():
        if event.type == pygame.MOUSEBUTTONDOWN:
            running = False

    # read single frame from video (as `numpy.array`)            
    ret, frame = video.read()

    if ret: # check `return status` because it may have problem to read frame
        #print(frame.shape)
        
        # cv2 keeps image as `BGR` and it needs to convert to `RGB`
        #frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        
        # it gives first `height`, next `width`
        #h, w = frame.shape[:2]
        
        # it needs first `width`, next `height`
        #image = pygame.image.frombuffer(frame, (w, h), "RGB")

        # resize to pygame's window 
        frame = cv2.resize(frame, (800, 600))

        # convert frame to PyGame surface
        # cv2 keeps image as `BGR` and it needs to convert to `RGB`
        image = pygame.image.frombuffer(frame, (800, 600), "BGR")

        # display it in PyGame's window
        screen.blit(image, (0,0))
     
    # slow down to correct speed
    clock.tick(fps)
    
    pygame.display.flip()
        
# --- end ---

pygame.quit()
#exit()

Tested with video Big Buck Bunny

furas
  • 134,197
  • 12
  • 106
  • 148