I recently started playing around with pygame and I wanted to create a tiled field that will highlight the tiles that are moused over. For that end I used DirtySprite and LayeredDirty, so that only the updated tiles would be drawn. However, when I run the code, the FPS drop to 11 and when I check, it's always the entirety of the screen that is drawn. Here's my code:
import os,sys
import pygame
import OpenGL
from pygame.locals import *
from PIL import Image
import pygame, math, sys
from pygame.locals import *
TILE_SIZE = 128
screen = pygame.display.set_mode((1920, 1080))
screen_height = pygame.display.get_surface().get_height()
screen_width = pygame.display.get_surface().get_width()
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))
X_TILES = screen_width/TILE_SIZE
Y_TILES = screen_height/TILE_SIZE
class Tiles(pygame.sprite.DirtySprite):
ground = Image.open('grass20.png')
select_rect = Image.open('Select_rect.png')
fore = Image.open('grass20.png')
fore.paste(select_rect,(0,0),select_rect)
select_rect = fore
del fore
select_rect =select_rect.resize((TILE_SIZE,TILE_SIZE),Image.ANTIALIAS)
ground =ground.resize((TILE_SIZE,TILE_SIZE),Image.ANTIALIAS)
size = ground.size
mode = ground.mode
bytes = ground.tobytes()
ground = pygame.image.fromstring(bytes,size,mode)
size = select_rect.size
mode = select_rect.mode
bytes = select_rect.tobytes()
select_rect = pygame.image.fromstring(bytes,size,mode)
del size
del mode
del bytes
def __init__(self,position):
pygame.sprite.DirtySprite.__init__(self)
self.rect = pygame.Rect(self.ground.get_rect())
self.rect.topleft=position
self.coords = (position[0]/TILE_SIZE,position[1]/TILE_SIZE)
self.image = self.ground
def update(self, hit_list):
if hit_list != self:
if self.image == self.select_rect:
self.dirty = 1
self.image = self.ground
else:
self.dirty = 0
elif self.image != self.select_rect:
self.dirty = 1
self.image = self.select_rect
else: self.dirty = 0
#print self.dirty, self.coords
class Mouse_pos(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.Rect((0,0),(1,1))
####
pygame.display.init()
clock = pygame.time.Clock()
city.set_position(screen_width/2,screen_height/2)
tiles = []
for x in xrange(X_TILES):
for y in xrange(Y_TILES):
tiles.append(Tiles((x*TILE_SIZE,y*TILE_SIZE)))
Tile_group = pygame.sprite.LayeredDirty(*tiles)
Tile_group.clear(screen,background)
del tiles
Tile_group.draw(screen)
mouse_pos = Mouse_pos()
tiles = []
while 1:
clock.tick(60)
for event in pygame.event.get():
if not hasattr(event, 'key'):
continue
down = event.type == KEYDOWN # key down or up?
if event.key == K_ESCAPE: sys.exit(0) # quit the game
mouse_pos.rect.center = pygame.mouse.get_pos()
collided_tile = pygame.sprite.spritecollideany(mouse_pos,Tile_group)
Tile_group.update(collided_tile)
allsprites = Tile_group.draw(screen)
pygame.display.update(allsprites)
When I check for dirty tiles, only 2 appear as dirty (as it should be).
However, when I print the allsprites
Rect, I always get (0,0,1920,1080)
.
Why is always the entire screen repainted and not only the updated tiles?
Update
When I print:
print [a.rect for a in Tile_group if a.dirty == 1]
and
print allsprites
I get different results; the a.rect
print returns two rects that are to be updated, however allsprites
returns (0,0,1920,1080)