0

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)

Community
  • 1
  • 1
Mee
  • 27
  • 1
  • 8
  • BTW: pygame has own function to load images `pygame.image.load` so you don't need `PIL`. `get_rect()` returns `Rect` object so you can do `self.rect = self.ground.get_rect()` - without `pygame.Rect()` or even you can use it with topleft `self.rect = self.ground.get_rect(topleft=position)` – furas Oct 18 '16 at 09:50
  • I know that, I used `PIL` especially for access to resizing and transformation functionality, which may be useful later. – Mee Oct 18 '16 at 09:53
  • I try you code (withoute `import OpenGL`) and `allsprites` gives me empty list or list with two `Rect` but both with size `128x128`. Maybe it is problem only with OpenGL or with your OS - I use Linux Mint, Python 3.5.1. – furas Oct 18 '16 at 19:31
  • I installed OpenGL and now `allsprites` gives `(0,0,1920,1080)` so OpenGL works different. – furas Oct 18 '16 at 19:40

0 Answers0