I wrote a custom pygame.sprite.RenderPlain() class. It modifies .draw() to include a source rect of the sprite. Now I need to modify the dest rect, converting its world() coordinates to screen() coordinates.
I wrote: Map().coord_to_screen( world ) and Map().coord_to_world( screen ) and they are working. But I can't access the member spr.rect.left or spr.rect.top of the sprite's Rect() to modify it. I get an AttributeError. The classes I'm using in this sprite group are: class Unit(pygame.sprite.Sprite): Which derives .Sprite(), adding movement. It works fine until I try accessing the .rect in RenderSrcRect().draw(): to blit with global coordinates converted to screen coordinates. (1) The documentation says that these aren't members( .top, .left, etc...), but are virtual attributes. What is a virtual attribute? (2) What's wrong with my code? The first code snippet is my working class, that just uses spr.rect as the dest rect. The second code snippet is my failed attempts to modify to convert the .rect world() coords to screen() coords. # code: original class, before screen() coords. This class *does* work. # file: RenderSrcRect.py # Author: jake bolton [created: 2007/11/14] # About: RenderSrcRect # child of RenderPlain, adds source rect support import pygame class RenderSrcRect(pygame.sprite.RenderPlain): """custom sprite group rendering class. Uses src Rect()s of sprite. the inheritance is: RenderPlain() == Group() which derives AbstractGroup() members used from the sprites to blit: .image = the sprite's surface .rect = the blit dest rect .rect_source = the blit source rect """ def __init__(self): """initialize Unit()""" pygame.sprite.RenderPlain.__init__(self) def draw(self, surface): """draw(surface). Draw all sprites onto the surface same as .RenderPlain.draw() except spr.rect_source is used to blit""" sprites = self.sprites() surface_blit = surface.blit for spr in sprites: # blit with src rect self.spritedict[spr] = surface_blit(spr.image, spr.rect, spr.rect_source) self.lostsprites = [] # modified class, uses screen() coords. This class has AttributeError: # the error: AttributeError: 'tuple' object has no attribute 'left' on line: spr.rect.left = 40 If you comment out the whole (try 1) block, (try 2) will still fail. # code: # file: RenderSrcRect.py # Author: jake bolton [created: 2007/11/14] # About: RenderSrcRect # child of RenderPlain, adds source rect support, and uses screen() coords from euclid import Vector2 import pygame from pygame.locals import * # needed for Rect() ? class RenderSrcRect(pygame.sprite.RenderPlain): """custom sprite group rendering class. Uses src rects of sprite. the inheritance is: RenderPlain() == Group() which derives AbstractGroup() members used from the sprites to blit: .image = the sprite's surface .rect = the blit dest rect .rect_source = the blit source rect """ def __init__(self, game): """initialize Unit()""" pygame.sprite.RenderPlain.__init__(self) # reference to the Map() class, for the later .coord_to_screen() call self.game = game self.map = self.game.map def draw(self, surface): """draw(surface). Draw all sprites onto the surface same as .RenderPlain.draw() except spr.rect_source is used to blit""" sprites = self.sprites() surface_blit = surface.blit for spr in sprites: # use screen coords for dest rect # == (try 1): I want to do something like this: but it fails: == # note: self.map.coord_to_screen() returns a euclid.Vector2() dest_rect = pygame.Rect( self.map.coord_to_screen( spr.rect.topleft ).x, self.map.coord_to_screen( spr.rect.topleft ).y, spr.rect.x, spr.rect.y, 0, 0 ) # dest rect ignores w,h values # (try 2): try 1 didn't work, so I test just Rect() member access: fails spr.rect.left = 40 # this line gives an attribute error self.spritedict[spr] = surface_blit(spr.image, dest_rect, spr.rect_source) self.lostsprites = [] thanks, -- Jake