Large animated sprites

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Large animated sprites

#1 Post by Mole-chan »

Hello,
A bit of an odd question, here. I'm planning to use animated sprites in my next game, all of which have several poses and composite eyes and mouths to save space. Even with the frame rate cut dramatically (about 5fps on average), the result is a pretty large use of memory.

So one alternative I wanted to look into is using an OGV video for the base image. In which case transparency is an obvious issue.

While I understand none of the video formats Renpy uses support transparency, I was wondering if it was maybe possible to use some sort of alpha masking instead.

It's probably a long shot, but I thought it'd be worth a shot to ask.

Thanks!
Last edited by Mole-chan on Sun Aug 24, 2014 11:27 pm, edited 1 time in total.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Video Masking

#2 Post by xela »

*I'd say that the lack of responses to the question is basically the absurdity of the approach. It shouldn't matter if you use 1 - 100000 sprites if you structure you code properly and not planning to call all of them simultaneously so the video approach would be considered borderline insane by most (or at least me)... If you have a concept with loads of sprites that is causing you trouble, post the concept and base code so people might help you out instead of weird video plans ;)
Like what we're doing? Support us at:
Image

User avatar
Holland
Regular
Posts: 92
Joined: Mon Jun 09, 2014 4:10 pm
Projects: Lycoris: Their Journies [WIP], With or Without You [NaNo19]
Location: NJ, USA
Contact:

Re: Video Masking

#3 Post by Holland »

If you're using a video anyway, why not just put the backgrounds and other sprites in the videos as well instead of trying to set transparency around them? :0

Though I agree with xela that it's best to fix the original problem instead of looking for some weird work-around.

User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Re: Video Masking

#4 Post by Mole-chan »

xela wrote:*I'd say that the lack of responses to the question is basically the absurdity of the approach. It shouldn't matter if you use 1 - 100000 sprites if you structure you code properly and not planning to call all of them simultaneously so the video approach would be considered borderline insane by most (or at least me)... If you have a concept with loads of sprites that is causing you trouble, post the concept and base code so people might help you out instead of weird video plans ;)
Haha, I agree honestly. It hit me not even an hour or so after posting this how flawed my plans were, and was hoping the silence would continue so it would die quietly. I'm honestly kind of glad no one bothered.

As for base code, here's an example of what I have so far in the test project. All the declarations follow this pattern, so it should be enough to go off of.

The basic premise is to animate the body in frame by frame, but use ATL to position the face so smaller blink and lip flap animations can be utilized. The entire thing is then wrapped in ATL. Persistent.charAnims refers to an option in preferences to either allow all animation, disable the body animation, or disable animation entirely.

Code: Select all

    transform cad_still_sad_mouth:
        xpos 201 ypos 75
    if persistent.charAnims < 2:
        $cad_anim_sad_mouth = cad_still_sad_mouth
        
    else:
        transform cad_anim_sad_mouth:
            subpixel True
            xpos 201 ypos 75
            linear .9 ypos 77
            linear .9 ypos 74
            linear .9 ypos 75
            repeat
    transform cad_still_sad_eyes:
        xpos 188 ypos 86
    
    if persistent.charAnims < 2:
        $cad_anim_sad_eyes = cad_still_sad_eyes
        
    else:    
        transform cad_anim_sad_eyes:
            subpixel True
            xpos 188 ypos 86
            linear .9 ypos 88
            linear .9 ypos 85
            linear .9 ypos 86
            repeat
   if persistent.charAnims < 2:
        image cadfael_base sad = "gfx/cadfael/base/sad/cad_sad_base_0028.png"
    else:
        image cadfael_base sad:
            "gfx/cadfael/base/sad/cad_sad_base_0028.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0029.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0030.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0031.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0032.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0033.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0034.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0035.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0036.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0037.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0038.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0039.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0040.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0041.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0042.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0043.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0044.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0045.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0046.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0047.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0048.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0049.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0050.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0051.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0052.png"
            .2
            #"gfx/cadfael/base/sad/cad_sad_base_0053.png"
            #.2
            "gfx/cadfael/base/sad/cad_sad_base_0054.png"
            .2

            repeat
    image cadfael_mouth sad = ConditionSwitch("persistent.charAnims == 0",  "gfx/cadfael/mouth/sad/cad_sad_mouth_static_0003.png",
        "persistent.charAnims >= 1", WhileSpeaking("cadfael", 
        Animation("gfx/cadfael/mouth/sad/cad_sad_mouth_static_0000.png", .1, 
            "gfx/cadfael/mouth/sad/cad_sad_mouth_static_0001.png", .1,
            "gfx/cadfael/mouth/sad/cad_sad_mouth_static_0002.png", .1,
            "gfx/cadfael/mouth/sad/cad_sad_mouth_static_0003.png", .1,), 
        "gfx/cadfael/mouth/sad/cad_sad_mouth_static_0003.png"),
        )
    image cadfael_eyes sad:
        parallel:
            choice (persistent.charAnims == 0):
                "gfx/cadfael/eyes/sad/cad_sad_eyes_static_0005.png"

            choice (persistent.charAnims > 0):
                "gfx/cadfael/eyes/sad/cad_sad_eyes_static_0005.png"
                2.0
                "gfx/cadfael/eyes/sad/cad_sad_eyes_static_0006.png"
                .15
                repeat
    image cadfael sad:
        contains:
            "cadfael_base sad"
        contains:
            "cadfael_eyes sad"

        contains:
            "cadfael_mouth sad"
            block:
                choice (persistent.charAnims == 2):
                    cad_anim_sad_mouth
                choice (persistent.charAnims < 2):
                    cad_still_sad_mouth
Note that the code snippets here are usually organized by function (transforms are with transforms, eyes with eyes, etc) rather than what sprite they'd go with, so if there's any indentation errors in the example, that's just bad copy pasting on my part. In the actual test they're indented correctly.

Nothing really special to show script wise. Just showing one sprite and some dialogue.
Last edited by Mole-chan on Sun Aug 24, 2014 11:25 pm, edited 1 time in total.

User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Re: Video Masking

#5 Post by Mole-chan »

BarabiSama wrote:If you're using a video anyway, why not just put the backgrounds and other sprites in the videos as well instead of trying to set transparency around them? :0

Though I agree with xela that it's best to fix the original problem instead of looking for some weird work-around.
That'd occurred to me, too, but seemed like it would result in a lot more files, and kind of go against the original intent of saving space. I was honestly planning to ditch the idea entirely if it wasn't feasible, and it's seeming that way.

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Large animated sprites

#6 Post by xela »

I wonder what eating up the memory or why framerate is so low... Does seem like there is anything off but I am having trouble following code because of indents/skips...

When would you say memory is being wasted? When Ren'Py starts (init phase), screen/show predicted or image is shown?
Like what we're doing? Support us at:
Image

Asceai
Eileen-Class Veteran
Posts: 1258
Joined: Fri Sep 21, 2007 7:13 am
Projects: a battle engine
Contact:

Re: Large animated sprites

#7 Post by Asceai »

anim.Filmstrip() > a ton of images.
If you need more control, atl crop.

After that the issue is just your image cache size (configurable), although I started having performance issues with very large animations eventually.

If you want to send me a renpy project with your current attempt at this I can play with it for you.

EDIT: I just saw that the original question was about alpha masking video files. Yes, you can do this, except not with a video as the source of the alpha mask. While you can AlphaBlend with the video, you'll have to get your mask from elsewhere, which means you still need an animation and I anticipate it will be a nightmare synchronising the two.

User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Re: Large animated sprites

#8 Post by Mole-chan »

xela wrote:I wonder what eating up the memory or why framerate is so low... Does seem like there is anything off but I am having trouble following code because of indents/skips...

When would you say memory is being wasted? When Ren'Py starts (init phase), screen/show predicted or image is shown?
The framerate is low as half of the frames are commented out, for experimentation. So that really wasn't the issue. Renpy runs every frame its told to, it's just that it's not being fed a lot of frames.

After running through it a few times, it seems to be mostly when new poses are shown. Just switching expressions doesn't effect it too much, which makes sense. Sometimes there'll also be a lag to go with the memory spike, but not consistently. Sometimes it will mellow out a bit if the sprite is left long enough without change. But even then it's pretty consistently using about 70-80 mb for one character.

There's also a spike/some lag when the game is started (not Ren'py itself, but the script). I'm not too concerned about this, as there's a loading screen at this point, since there's also a lot of other stuff Ren'py has to declare. With that, it'll hardly be noticeable.
Last edited by Mole-chan on Mon Aug 25, 2014 5:00 pm, edited 1 time in total.

User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Re: Large animated sprites

#9 Post by Mole-chan »

Asceai wrote:anim.Filmstrip() > a ton of images.
If you need more control, atl crop.

After that the issue is just your image cache size (configurable), although I started having performance issues with very large animations eventually.

If you want to send me a renpy project with your current attempt at this I can play with it for you.

EDIT: I just saw that the original question was about alpha masking video files. Yes, you can do this, except not with a video as the source of the alpha mask. While you can AlphaBlend with the video, you'll have to get your mask from elsewhere, which means you still need an animation and I anticipate it will be a nightmare synchronising the two.
Oooh, good point. I shouldn't need the cropping, either, since the image sizes are pretty uniform.
I actually have configured the image cache to 16 whenever animations are enabled. Admittedly I'm not sure if that's enough, as this is my first time dealing with large images.

That'd be great! I really appreciate it. 8D

As for the edit, even though that's no longer the plan, it's still pretty interesting to see that it's possible. Thanks for sating my curiosity. :3

User avatar
xela
Lemma-Class Veteran
Posts: 2481
Joined: Sun Sep 18, 2011 10:13 am
Contact:

Re: Large animated sprites

#10 Post by xela »

Mole-chan wrote:
xela wrote:I wonder what eating up the memory or why framerate is so low... Does seem like there is anything off but I am having trouble following code because of indents/skips...

When would you say memory is being wasted? When Ren'Py starts (init phase), screen/show predicted or image is shown?
The framerate is low as half of the frames are commented out, for experimentation. So that really wasn't the issue. Renpy runs every frame its told to, it's just that it's not being fed a lot of frames.

After running through it a few times, it seems to be mostly when new poses are shown. Just switching expressions doesn't effect it too much, which makes sense. Sometimes there'll also be a lag to go with the memory spike, but not consistently. Sometimes it will mellow out a bit if the sprite is left long enough without change. But even then it's pretty consistently using about 70-80 mb for one character.

There's also a spike/some lag when the game is started (not Ren'py itself, but the script). I'm not too concerned about this, as there's a loading screen at this point, since there's also a lot of other stuff Ren'py has to declare. With that, it'll hardly be noticeable.
I see, so you think that it's not coding related and sprites are simply too large for Ren'Py?

nyaatrap once suggested in a similar discussion to make all sprites smaller and use zoom transform on them, should be a huge increase in performance and very little quality loss.

Otherwise, if it's code related, you may not want to declare images to Ren'Py at all (I <almost> never do). Basically if you have a lot of images in the game and do this:

Code: Select all

        for f in renpy.list_files():
            if f.endswith((".png", ".jpg")):
                renpy.image(f, At(f, some_simple_transform))
It will cause a huge memory consumption during the whole duration of the game. If you create a class/function that calls images on conditions returning At(f, some_simple_transform) as required, it will cause no such issues.
Like what we're doing? Support us at:
Image

User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Re: Large animated sprites

#11 Post by Mole-chan »

@Xela: I think it's possible. The images are decently large, at about 720px high, but I'm also showing myself to be pretty incompetent, so all bet's are off.
I tried the resizing suggestion, but man. I don't know what kind of black magic Nyaatrap is using, because the result is pretty blurry and terrible.

The second suggestion is interesting, and probably would cut a lot off the consumption. I'm not sure how it would work with animation, off the top of my head, though.
I've no doubt it's possible, but I don't usually work with directly calling images that way, so I guess I'm failing to see the immediate connection.

User avatar
Mole-chan
Veteran
Posts: 333
Joined: Thu Aug 27, 2009 12:46 am
Completed: DUAEL, Escape from Puzzlegate
Projects: A Bird with Gold-Mended Wings
Deviantart: mole-chan
Skype: mole-chan
itch: moleworks
Contact:

Re: Large animated sprites

#12 Post by Mole-chan »

So I did get everything moved over to filmStrip, and while the space saved is considerable, it seems to actually amplify the lag and memory consumption. Which seems..really contrary. Peaked at about 170mb loading one of the poses.

It probably is a cache issue at this point, because there are so comparatively few images to work with.

Image
There are points I can see it loading a few poses ahead, which is pretty unnecessary. But mostly it's loading as it goes with few redundancies, and still doing a pretty poor job.

I'm still curious about how the image calling class would work with animation, since that seems like it'd at least be worth trying.

Post Reply

Who is online

Users browsing this forum: DewyNebula, Ocelot