[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] Slow rendering speed - sprites
Hi,
See the attached for some tweaks.
I bumped the number of sprites up to 200.
When I used my own 100x100-pixels png that has an alpha layer I get a
bit more than 100 fps. Alpha layers take extra CPU to render.
When I use same-size filled rects of the same dimensions I get a little
over 200 fps.
When you load your image, you might get better performance if you
convert() it or convert_alpha().
Hope this helps.
Gumm
On 3/7/2015 1:37 PM, David Unric wrote:
Hello,
I'm considering a game framework for next more serious project. As I'm
Python/Ruby language agnostic, I did rewrote simple sprite benchmark
from Gosu to latest Pygame to do a performance comparison. You may
find the code bellow.
I was very surprised Pygame version performs much more worse. To get
an idea, it was tested on the same machine, in the same environment,
linked against same SDL 1.2.15, run with Python 2.7.5. It starts
significantly drop framerate when sprites count gets over 20, whereas
Gosu version with Ruby 2.2.0 smoothly renders 200 sprites at 60 fps !
At about 100 sprites on the screen it becomes just a very slow slideshow.
I don't know if something important performance-wise was missed.
Simple background is a static surface, display is also initialized
with native resolution 1376x768 in fullscreen,
LayeredDirty group with DirtySprites for better performance (Gosu
version also handles z-order of each sprite).
Any idea what am I doing wrong ?
_______________________________________ snip
____________________________________________________
import pygame, pygame.gfxdraw
from pygame import *
from random import randint
def main():
pygame.init()
video_info = pygame.display.Info()
if video_info.current_w != -1 and video_info.current_h != -1:
screen_width, screen_height = video_info.current_w, video_info.current_h
else:
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height),
FULLSCREEN | DOUBLEBUF | HWSURFACE)
pygame.display.set_caption(__name__.upper())
background = pygame.Surface(screen.get_size()).convert()
background.fill((0, 0, 0))
pygame.gfxdraw.filled_trigon(background,
screen_width/10, screen_height/10,
screen_width*9/10, screen_height*9/10,
screen_width/2, screen_height*9/10,
(210, 200, 77))
sprites = pygame.sprite.LayeredDirty()
image = pygame.image.load('my_sprite.png')
for _ in xrange(30): XSprite(image, sprites)
del image
# main game loop
while True:
for event in pygame.event.get():
if event.type == QUIT: return
elif event.type == KEYDOWN and event.key == K_ESCAPE: return
screen.blit(background, (0, 0))
sprites.update(screen)
sprites.draw(screen)
pygame.display.flip()
class XSprite(pygame.sprite.DirtySprite):
def __init__(self, image, *groups):
super(XSprite, self).__init__(*groups)
self.image = image
self.rect = self.image.get_rect()
self.rect.x = randint(0, 60)
self.rect.y = randint(0, 40)
self.dx, self.dy = randint(1, 16), randint(1, 16)
def update(self, screen, *args):
screen_w, screen_h = screen.get_size()
self.rect.x += self.dx
self.rect.y += self.dy
if (self.rect.x + self.dx + self.rect.w > screen_w) or \
(self.rect.x + self.dx < 0):
self.dx = -self.dx
if (self.rect.y + self.dy + self.rect.h > screen_h) or \
(self.rect.y + self.dy < 0):
self.dy = -self.dy
self.rect.move_ip(self.dx, self.dy)
if __name__ == '__main__':
main()
# vim: set ft=python ts=8 sts=4 sw=4 tw=79 fdm=indent:
_______________________________________ snip
____________________________________________________
import pygame, pygame.gfxdraw
from pygame import *
from random import randint
def main():
pygame.init()
video_info = pygame.display.Info()
if video_info.current_w != -1 and video_info.current_h != -1:
screen_width, screen_height = video_info.current_w, video_info.current_h
else:
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height), FULLSCREEN | DOUBLEBUF) # | HWSURFACE)
pygame.display.set_caption(__name__.upper())
background = pygame.Surface(screen.get_size()).convert()
background.fill((0, 0, 0))
pygame.gfxdraw.filled_trigon(
background,
screen_width / 10, screen_height / 10,
screen_width * 9 / 10, screen_height * 9 / 10,
screen_width / 2, screen_height * 9 / 10,
(210, 200, 77))
sprites = pygame.sprite.LayeredDirty()
sprites.clear(screen, background)
# image = pygame.image.load('tomato.png').convert_alpha()
image = pygame.Surface((100, 100))
image.fill(Color('red'))
for _ in xrange(200):
XSprite(image, sprites)
del image
clock = pygame.time.Clock()
timer = 1.0
sans_font = pygame.font.SysFont('sans', 18, True)
fps = None
fps_rect = None
# main game loop
while True:
timer -= clock.tick() / 1000.0
if timer <= 0.0:
timer += 1.0
fps = sans_font.render('{0:0.0f} fps'.format(clock.get_fps()), True, Color('yellow'))
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE:
return
if fps_rect:
screen.blit(background, (0, 0), fps_rect)
sprites.update(screen)
dirty_rects = sprites.draw(screen)
if fps:
fps_rect = screen.blit(fps, (0, 0))
dirty_rects.append(fps_rect)
pygame.display.update(dirty_rects)
class XSprite(pygame.sprite.DirtySprite):
def __init__(self, image, *groups):
super(XSprite, self).__init__(*groups)
self.image = image
self.rect = self.image.get_rect()
self.rect.x = randint(0, 60)
self.rect.y = randint(0, 40)
self.dx, self.dy = randint(1, 16), randint(1, 16)
def update(self, screen, *args):
screen_w, screen_h = screen.get_size()
self.rect.x += self.dx
self.rect.y += self.dy
if (self.rect.x + self.dx + self.rect.w > screen_w) or \
(self.rect.x + self.dx < 0):
self.dx = -self.dx
if (self.rect.y + self.dy + self.rect.h > screen_h) or \
(self.rect.y + self.dy < 0):
self.dy = -self.dy
self.rect.move_ip(self.dx, self.dy)
self.dirty = True
if __name__ == '__main__':
main()