How to get frame rate (fps) up in Python + Pygame?

Let events come to you with event.wait

Do you really need to do processing every tick? If not, use pygame.event.wait for your event loop to only process when an event comes in, and pygame.time.set_timer if you need periodic events like your SecondEvent.

This means you won't be drawing many frames during seconds when events aren't coming in, but that's okay. Using event.wait will decrease CPU usage and let you still be responsive, and likely removes the need for the time.wait you have in there instead.

Don't re-draw the entire board from scratch every tick

Don't have Room.render blit the background every time, which means then it has to go through and re-draw the entire board and all the cards. Do that once. Then don't have cards re-render themselves unless they changed darkness or they're moving.

When cards are moving, you should be able to restore the background by blitting just a chunk of the background graphic instead of the whole thing.

Pass a rectangle list to display.update

Once you're only updating certain areas, you can pass those areas to display.update so it doesn't have to update the whole screen. For an example, see the Solarwolf code and how it marks dirty rectangles.


On your profile results:

I recently found out that you should only update the areas of the screen that have changed, but I'm still foggy on how that accomplished exactly... could this be a huge performance issue?

Yes. display.update and Surface.blit are at the top of your profile results. You did over a million blits, in about 5000 ticks, which works out to 200 blits every tick.

Also, sixth on your profile results is display.set_caption, which I guess is the display of the FPS counter itself? At 7 seconds of 157, this isn't your major hotspot, but still interesting to know.