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.

So I have a question that may be out of the realm of normal visual novel/ Renpy questions.

Before you ask why in the world I would need to have 100+ individual instances of the same displayable displaying at once... Its because I am not really using Renpy for it's intended purpose. I am making an action game with visual novel story elements. I know I could have used more action-oriented engines to do this, but I love Renpy and Pygame. Why am I doing this? I ask myself that sometimes too, but its fun

Ok, now onto the actual question.
I have pushed Renpy quite far beyond its intended scope, so I was expecting this issue eventually. Using Fraps to check Frames per second, my game is running 60fps most of the time, but drops to 28- 34 fps under maximum load.

The source of this framerate dip is a large number of custom displayables being rendered to the screen. They are fairly small, only about 108x25 px, and have some transparency. They move very fast, and currently between 80 and 100 of them are being displayed at maximum load.

Efficiencies I have already implemented:
- Do not create a new displayable unless absolutely necessary. Recycle ones that have been destroyed or left bounds of screen. This allows me to have the appearance of hundreds of displayables being created, while only having about a maximum of 250 actually loaded into memory.
- Pre-create the displayables that are being instantiated at start. So during gameplay none of them actually have to be created, you simply reset their visibility/position when needed.

I believe what is hogging the memory is in rendering them. I am using the standard method to render something in Renpy(python) / pygame:

I am saving all active of this type of displayable in a list, and iterating through it calling render on all entries in the list.
Elsewhere on the web, I have heard suggestion that because they all use the same image and are the same size, it would be far more efficient to draw them all in a single step each frame, instead of iterating through them and rendering them one at a time.
I think this would speed things up significantly, but not quite sure how to implement it. I considered making a step where I run all of the displayables renderer.blit in a single block of code, but I don't think that would work. I would need to find some way to combine all of the displayables into a single Image and blit that one image.

I have also heard you can get a large performance boost by converting the alpha of transparent images in pygame.

I was wondering if anybody had any advice for how I can make the rendering step more efficient?

You should likely look at Sprites and the SpriteManager Class which is optimized to display many 'caches' of the same image many times. Also have a read through the actual SpriteManager class in the Ren'py source to see how it uses caching.

That does look like it might help, but the problem is that every sprite wouldn't necessarily behave the same way. So a single update() method wouldn't work. Some go in a straight line, while others may follow a path.

Can the individual sprites be updated externally? For example, could I create a spritemanager, but then the objects the sprites represent create the sprite using the spritemanager and they give it its positional info every update?

That simply uses the SpriteManager to throw 400 sprites on the screen as either Image("images/180.png") or Image("images/307.png") then tells them that one image type moves vertically and the other horizontally. I used a simple -- if i.cache.child == img1: -- test, though you could extend both classes (and SpriteManager.create() ) to just pass in an extra parameter such as Sprite.type...

Doesn't seem to work. It wants 5 arguments (4 given if you include self)

renpy.show(self.spriteManagerName) results in the error that Spritemanager has no attribute 'split'

I do not understand why you want to call the render method like that? Is not screen language or a label enough?
Did you even read the class definitions in the Ren'py source? If you did, you'd see "def render(self, width, height, st, at):" which should be hint enough.

Sorry, I know it's confusing, but I am not actually using the screen language very much, instead going straight to python.
The game I am making swaps between two modes. The story segments are 90% renpy screen language with a little bit of python for flags, but the main gameplay segments barely use any renpy screen language. Mostly working directly with pygame with a little bit of renpy's features. It may be possible to mix the screen language and python more in the action segments but I have been keeping it consistent.

Not too frustrating, I just wondered if you were choosing the best option and whether what you are doing might actually work as well or better just in Ren'py.

Modern Ren'py uses a pygame SDL2 API which exposes most of the standard old sdl 1.n API of pygame with a few omissions (bitmask collision detection among them, grrr - working on that though ) ... for info SDL2 went stable in Aug 2013 which kind of shows how old the hardware abstraction layer for pygame is. The more modern SDL2 helps Ren'py run smoothly on more platforms, so the benefits outweigh the costs.

Screen language, Sprites, Transforms, Events and all those features of Ren'py can (with a little work and study) accomplish a lot more than just VN game play. If you are actually writing the pygame part, you might find it more useful to learn to do it through Ren'py instead/as well.