Ren'Py Play a video or images series with the mouse mouvement.

UncleNanard

I am to music what Kanye West is to adult games.
Game Developer
Jul 1, 2017
1,644
1,617
Hello everyone, I would like to know if it's possible to play an animation (video or series of images) on Renpy in the following way:

show myvideo
-Idle, no click or movement = frame 1
-Click on the image + drag to the left, for example = video playback until the last frame. The further to the left I drag, the more the video progresses until the last frame.
-If I drag to the right the further to the right I drag, the more the video goes back to the beginning.
-When I drag for more than 3 seconds to the left and I am at the last frame, it continues to the next image, or a label, or an image button, whatever (maybe imagebutton is the best option).

To put it simply, imagine a character on the right side of the screen, I click on it (or anywhere on the screen if it's easier) and when I drag the mouse to the left while holding the click, the video plays, showing the character moving from the right side of the screen to the left.

(i can send an exemple in PM)

Thanks for your help.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Hello everyone, I would like to know if it's possible to play an animation (video or series of images) on Renpy in the following way:
With still images, yes it's possible.
With videos, well, it's not impossible, but it would need that you handle the video all by yourself instead of relying on Ren'Py for that.

The question is more, does it worth it ? Or, if you prefer, what value would this add to the game exactly ?

Not that a mechanism necessarily have to add value to the game. It's more that a complex, and possibly breaking, mechanism that add (near to) nothing to the game is generally more a burden than an advantage.


To put it simply, imagine a character on the right side of the screen, I click on it (or anywhere on the screen if it's easier) and when I drag the mouse to the left while holding the click, the video plays, showing the character moving from the right side of the screen to the left.
And now I have a totally different picture in mind that what I visualized when reading the pure video explanation.
What are you trying to achieve exactly ? A video(-like) player that offer some control over the played video, or something else ?
 
  • Like
Reactions: UncleNanard

UncleNanard

I am to music what Kanye West is to adult games.
Game Developer
Jul 1, 2017
1,644
1,617
With still images, yes it's possible.
With videos, well, it's not impossible, but it would need that you handle the video all by yourself instead of relying on Ren'Py for that.

The question is more, does it worth it ? Or, if you prefer, what value would this add to the game exactly ?

Not that a mechanism necessarily have to add value to the game. It's more that a complex, and possibly breaking, mechanism that add (near to) nothing to the game is generally more a burden than an advantage.




And now I have a totally different picture in mind that what I visualized when reading the pure video explanation.
What are you trying to achieve exactly ? A video(-like) player that offer some control over the played video, or something else ?
Hello, I have sent you an example via private message. Thank you for your response.
 

DuniX

Well-Known Member
Dec 20, 2016
1,238
826
An old trick you can do is make a big image with all your frames and use Crop to show parts of the image.
Use that with a dynamic displayable.

You can use that in combination with a Screen Bar to control the dynamic displayable. Also just because it's a horizontal bar doesn't mean it can't fit the entire sprite and you can use a imagemap with a hotbar to make a effectively invisible bar.

I am not sure how well Renpy handles updating a lot of smaller images frequently or using one big image so that's what you should test what is best.

Edit: Seems like you shouldn't use as that is mostly for images that don't change frequently.
Best bet is still to have a big image with a crop transform and make a python function to update. Don't use the Crop from the displayables as that would create a entire new image.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
I am not sure how well Renpy handles updating a lot of smaller images frequently or using one big image so that's what you should test what is best.
It's not about how Ren'Py handle it, but how it can be handled whatever the engine and language.

Displaying a single image imply a raw Byte copy. Nowadays you'll provide the starting point and size to the API, that will do all the works.
Displaying a portion of an image imply a line by line copy. Therefore, either you'll have to rely on an intermediary buffer, or you'll multiply the API calls (one by line). In both case it don't need to be a genius to understand that, as atomic as it will be (and it will be), it will still be slower.

The way it will be handled by the engine only define how slower your cropping approach will be, that's all.
As handled by Ren'Py, it will be around 10% slower. Ren'Py always pass by an intermediary buffer, because it assume that the image can have to be altered by some effect, and because most images will be resized.
As it can be handled by Unity or Unreal, it can easily be 50% slower.
 
  • Angry
Reactions: DuniX

DuniX

Well-Known Member
Dec 20, 2016
1,238
826
It's not about how Ren'Py handle it, but how it can be handled whatever the engine and language.

Displaying a single image imply a raw Byte copy. Nowadays you'll provide the starting point and size to the API, that will do all the works.
Displaying a portion of an image imply a line by line copy. Therefore, either you'll have to rely on an intermediary buffer, or you'll multiply the API calls (one by line). In both case it don't need to be a genius to understand that, as atomic as it will be (and it will be), it will still be slower.
It depends, loading and unloading 1000 images is not the same thing as loading one image.
It depends on how Renpy batches things and sends it to the graphics api.
I am pretty sure ATL is pretty optimized so you should be able to use crop from there.

Edit: Basically what you have to consider is if you want a series of images instead of a "movie" that would all be uncompressed image data that has to be stored both in memory and the graphics video memory.
Renpy has a image cache and image prediction that you have to handle.



I am not sure how Renpy handles that with the graphics api, if you have a 20k texture that might be split into multiple 8k textures.
And I am not sure how fast is just updating the images if it's already loaded into video memory.
I think the ideal is to split it into multiple images of multiple frames that way when you update things it only has to handle one or two images at a time.
Ideally it should be split into less than 4k textures as that is usually the standard.

Obviously if your frames are at 1080p you probably have no chance to do this without using the movie which I don't think you can use for your case. The uncompressed data would be too large and Renpy will struggle to handle.
 
Last edited:
  • Angry
Reactions: anne O'nymous

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Since your edit clearly show that you know absolutely nothing about the subject, I'll finally answer you...

It depends, loading and unloading 1000 images is not the same thing as loading one image.
It depends on how Renpy batches things and sends it to the graphics api.
No it don't depends, especially with your example of 1,000 images.

Firstly, because if you have 1,000 frames, you'll not be stupid enough to display them on frame by frame animation. You'll turn them into a movie, at least because it will save a lot of space on the drive.

Secondly, because an 1920x1080 image need 8.3 MB of space in the RAM, against 8.3 GB for your all frames in one image approach. Even counting the hard drive speed, loading and processing a thousand images will not be really slower than loading and processing your astoundingly gigantic image. I don't even talk about the whole day you'll need to save it in the first place.

Thirdly, because threads exist, and here you'll benefit from three + one.
With 1,000 independent frames, and thanks to its prediction feature, Ren'Py will already have loaded ten of them, more if you resized its cache, before it even reach the moment when it need to display the first frame. Therefore, the animation will starts instantly and Ren'Py will load the following frames will displaying the already loaded ones, including the small waiting time that will be defined between them. This already represent two threads, the one displaying the image, and the one loading the next ones.
Then, in top of this if you put the said image in a RPA archive, you'll benefit from both the hard drive and OS cache, what mean that you'll not be slowed down by the seeking and reading time. This represent the last thread and the "plus one" (the HD cache isn't technically a thread).
Globally speaking (because the chunk size will not precisely match), while Ren'Py will be displaying the first batch of images, it will be loading the second batch of images in its cache. This while the OS will be loading the third batch of images in its own cache, and in the same time the hard drive will be loading the forth batch in its own cache.
And this is something that will not apply with your single image. Since Ren'Py will be asking in real time, the OS and HD cache will collide. When Ren'Py will ask for the next block of the image, the OS cache will it be asking for the same block, and the HD cache will be loading it. Unlike with the 1.000 independent image, the three caches will be totally useless here and offer no optimization.


I am pretty sure ATL is pretty optimized so you should be able to use crop from there.
Except that, like I said and explained in my first answer, the issue is not the cropping algorithm, but what it imply in terms of link CPU RAM -> GPU RAM.
Therefore, it's something totally independent of the game engine. Whatever if you're trying to do this with Ren'Py or Unreal, your cropping approach will always be slower.

It doesn't matter how optimized Ren'Py cropping is, cropping will still mean that you need to fill a buffer line by line, with a computing part between each line. Something that is not needed when you just blit the whole image.

Whatever the language you use, even Assembler, this algorithm:
Code:
for( i=0 ; i < 1920*1080*4 ; i++ )
{   dest[i] = src[i] }
while always be faster than this one:
Code:
k = 0
for( i=0 ; i < 1920*1080*4 ; i += 1080*4 )
{
   for( j=i ; j < (i+1)*1080*4 ; j++ )
  { 
     dest[k++] = src[j]
  }
}
 
  • Angry
Reactions: DuniX

DuniX

Well-Known Member
Dec 20, 2016
1,238
826
No it don't depends, especially with your example of 1,000 images.

Firstly, because if you have 1,000 frames, you'll not be stupid enough to display them on frame by frame animation. You'll turn them into a movie, at least because it will save a lot of space on the drive.

Secondly, because an 1920x1080 image need 8.3 MB of space in the RAM, against 8.3 GB for your all frames in one image approach. Even counting the hard drive speed, loading and processing a thousand images will not be really slower than loading and processing your astoundingly gigantic image. I don't even talk about the whole day you'll need to save it in the first place.
Like I said it's impossible to achive what the OP wants with a full resolution 1920x1080 frames.
If you could do that with a movie system that renpy has and sample from that we wouldn't need to have this kind of workarounds in the first place.
But there is still things we can do, we can extract the sprites and things that move from the "background".

Even counting the hard drive speed, loading and processing a thousand images will not be really slower than loading and processing your astoundingly gigantic image. I don't even talk about the whole day you'll need to save it in the first place.
Loading is not the real issue, it's how it's rendered and updated.
And I didn't say to use a gigantic image, I said to test and find out how large the image renpy handles best.

Thirdly, because threads exist, and here you'll benefit from three + one.
With 1,000 independent frames, and thanks to its prediction feature, Ren'Py will already have loaded ten of them, more if you resized its cache, before it even reach the moment when it need to display the first frame. Therefore, the animation will starts instantly and Ren'Py will load the following frames will displaying the already loaded ones, including the small waiting time that will be defined between them. This already represent two threads, the one displaying the image, and the one loading the next ones.
Prediction isn't going to save you with the functionality the OP wants. If he wanted just that he could just play a movie.
It's precisely that you have to be deliberate with what you load as well as having some leeway to keep things smooth.
If he scrolls to the left all your predictions to the right are a waste while the things you discarded to left that you think you didn't need has to be reloaded.
If you have a image with a couple of frames you can ensure you maintain a load of images with a certain amount of frames in both directions and if that is within the scrolling speed and loading speed it will maintain smoothness.
In terms of chunks of frames you need to maintain it's the same either way as a lot of smaller images or a few bigger images so it's a question again on what Renpy handles best that has to be tested.

Except that, like I said and explained in my first answer, the issue is not the cropping algorithm, but what it imply in terms of link CPU RAM -> GPU RAM.
Therefore, it's something totally independent of the game engine. Whatever if you're trying to do this with Ren'Py or Unreal, your cropping approach will always be slower.

It doesn't matter how optimized Ren'Py cropping is, cropping will still mean that you need to fill a buffer line by line, with a computing part between each line. Something that is not needed when you just blit the whole image.

Whatever the language you use, even Assembler, this algorithm:
You do realize what a GPU is and how Textures work right?
Their whole job is to sample parts of the texture to map to the polygons that make up to model.
Depending on how the crop is implemented in ATL you can basically get it for free.

How GPU rendering works is they are precisely massively parallelized so they don't just do one "line by line" but thousands of them in parallel drawing parts of the image in buckets.

So once you are in video memory you are in a completely different universe, you can sample any parts of the image as much as you want.

The only issue is how you send it to the GPU memory and what format fits it best, if the GPU for some reason only supported 4k textures then you would want to split your frames to fit that.

That and how Renpy handles the rendering, it could well be that ATL crop might not be able do this but you could use the Model-Based Rendered to ensure you have that instead.
Although I am pretty sure ATL is accelerated and optimized since the whole point is to ensure smooth animations, just cropping shouldn't be a issue.
And I said to test things, not that this is the best option, just that it is an option you have.

You aren't treating it as a problem that needs to be solved, you want to be "right", but if your solution doesn't work your "right" is worthless.
If your 1000 images that you loaded individually don't render smoothly, then by your logic we should give up and cry because the "right" answer doesn't work.
 
Last edited:
  • Haha
Reactions: anne O'nymous

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
Like I said it's impossible to achive what the OP wants with a full resolution 1920x1080 frames.
Totally.

And this code absolutely don't permit to do it. It also haven't been tested with 50 frames at 1920x1080 and so don't proved that it worked smoothly without a single slowdown.
You don't have permission to view the spoiler content. Log in or register now.

Oh, wait... What am I saying. Of course that it works. But it's true that it haven't been tested with 50 frames, during my tests there were 200.


You aren't treating it as a problem that needs to be solved, you want to be "right", but if your solution doesn't work your "right" is worthless.
The main difference between you and me, is that I think before I talk and limits to what I know. This mean that when I give a solution, it's because I already know that it will works ; this even if I don't necessarily know precisely what the code looks like. Else, because it happen that I sometimes talk purely theoretically, I say it explicitly.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,971
16,229
It was there to handle the image cache also.
Oh, really ? You thought about the image cache before the image cache was introduced into the discussion by the edit you did 8 hours later ?
Be careful, you just lost one point.

But anyway since the displayable have no predict_one_action method, the images are not cached by Ren'Py (at least no when walking forward) because it's mostly useless unless you really have big uncompressed images ; the HD and OS caches are enough.
And if really you need to cache them, it would be way better to do it from event with renpy.load_image() addressing the following frame(s), or with a dedicated method and through a list coupled to renpy.load_image().
 

DuniX

Well-Known Member
Dec 20, 2016
1,238
826
Oh, really ? You thought about the image cache before the image cache was introduced into the discussion by the edit you did 8 hours later ?
It was always part of the discussion. At least the part that you were complaining about.
And it's not really about 1000 frames in particular but making it robust enugh to handle any length.