Here's an approach for using a Movie object, but having it play through once without looping. renpy.movie_cutscene, of course, will play through just once, but it plays full screen. Using the Movie Displayable this way gives you options that renpy.movie_cutscene doesn't - like having the video only occupy a portion of the screen, be used as a character image, etc., etc.
First, Movie takes a play_callback parameter. (See https://www.renpy.org/doc/html/movie.html#Movie). The Ren'py docs say:
This is part 1 of the trick - note the loop=True. If you substitute loop=False, lo and behold, the Movie doesn't loop!Generally, this will want to use renpy.music.play() to start the movie playing on the given channel, with synchro_start=True. A minimal implementation is:Code: Select all
def play_callback(old, new): renpy.music.play(new._play, channel=new.channel, loop=True, synchro_start=True) if new.mask: renpy.music.play(new.mask, channel=new.mask_channel, loop=True, synchro_start=True)
Part 2 of the trick relates to what happens when the Movie finishes playing. The Ren'py docs say:
Thus, when the video reaches the end, it will disappear off the screen. Well, technically, the Movie Displayable is still there - it's just transparent. If that's what you want, then all well and good. But maybe you want to give the illusion of "play through and stop with the last frame showing." In this case, have a normal image that is the last frame of the video, and display it once the video ends. You can do this easily by setting up a compound image using ATL, with it starting with the Movie, delaying for the length of the movie (or maybe just a scrinch less) and then replacing the movie with the last frame.This displayable will be transparent when the movie is not playing.
Here's a sample script that shows this off. The video in question is the "rocket lifting off" video from the Ren'py Tutorial project. So if you use this as the "script.rpy" and copy the movie in, you'll have a full working demo.
Code: Select all
init python:
# play_callback function for Movie() that starts the movie _without_ looping
# It's just the reference implementation from https://www.renpy.org/doc/html/movie.html#Movie
# but with "loop=True" changed to "loop=False"
def play_movie_only_once_callback(old,new):
renpy.music.play(new._play, channel=new.channel, loop=False, synchro_start=True)
if new.mask:
renpy.music.play(new.mask, channel=new.mask_channel, loop=False, synchro_start=True)
# Just a grey background to show things against
image grey = "#888"
# The movie we want to play through once
image the_movie = Movie(play='oa4_launch.webm', play_callback=play_movie_only_once_callback)
# This should contain the last frame from the movie, but I'm too lazy to extract
# it, so I'm just using a black rectangle of the same size as the movie.
image the_movie_last_frame = Crop((0,0,640,360), "#000")
# The movie image we actually "show"
image one_time_movie:
"the_movie" # The movie
pause 7.99 # A delay to get to the end of the movie
"the_movie_last_frame" # The last frame of the movie, now displayed as an image
label start:
scene grey
"Ready"
show one_time_movie:
align(0.5,0.5)
"Playing through once, and stopping at the (faked) final frame"
hide one_time_movie
"Done"
return
Hope that (a) someone finds this useful and (b) I didn't just re-create the wheel that someone else had already posted here...