Search code examples
pythonpygamedrawingpygame-surfacegroup

Pass `special_flags` argument to group.draw in pygame


Is there a way to pass the special_flags argument to Group.draw so that it calls the .blit method with those flags? I've tried just passing it as a keyword argument like this:

group.draw(surface, special_flags=pygame.BLEND_SOURCE_ALPHA)

but it gives this error:

Traceback (most recent call last):
  File "C:\Users\MarciAdam\PycharmProjects\pygame_stuff_1\main.py", line 394, in <module>
    group.draw(surface, special_flags=pygame.BLEND_RGBA_MAX)
TypeError: draw() got an unexpected keyword argument 'special_flags'

I know I could do something like this:

for sprite in group.sprites():
    surface.blit(sprite.image, sprite.rect, special_flags=pygame.BLEND_SOURCE_ALPHA)

but I would need to duplicate a lot of the pygame code for the more complicated group types eg. LayeredUpdates.


Solution

  • The requested feature is implemented with Pygame version 2.3.0. See pygame.sprite.Group.draw. With this version, the code works and you can set the blending mode directly

    group.draw(surface, special_flags=pygame.BLEND_SOURCE_ALPHA)
    

    Before Pygame 2.3.0, this optional parameter did not exist. If you are using an older version of Pygame, you must implement a workaround.

    Draw the sprite with a "for" loop. I suggest to write a function for this or implement your own MyGroup class derived from pygame.sprite.Group:

    class MyGroup(pygame.sprite.Group):
        def __init__(self, *args):
            super().__init__(*args) 
        def draw(self, surface, special_flags=0):
            for sprite in self:
                surface.blit(sprite.image, sprite.rect, special_flags = special_flags)
    
    group = MyGroup()
    
    group.draw(surface, special_flags=pygame.BLEND_RGBA_MAX)
    

    If you want to do the same for pygame.sprite.LayeredUpdates or pygame.sprite.RenderUpdates, you have to implement all the drawing features of these objects yourself.


    A completely different solution is to use pygame.sprite.DirtySprite. This class is derived from pygame.sprite.Sprite and has an additional blendmode attribute which is its the special_flags argument of blit.

    class MySprite(pygame.sprite.DirtySprite):
        def __init__(self):
            super().__init__() 
            self.dirty = 2
            self.blendmode = pygame.BLEND_RGBA_MIN
            # [...]
    

    Note, DirtySprite only works with pygame.sprite.LayeredDirty and all sprites in the group must be of this type.