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:
Code: Select all
def render( self, renderer, shownTimebase, animationTimebase ):
# Display this object
if ( self.active ):
r = renpy.render( self.image, SCENE_RIGHT, SCENE_DOWN, shownTimebase, animationTimebase )
renderer.blit( r, (self.position[0], self.position[1]) )
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?