Aug-28-2018, 10:40 PM
I've had another run at this group thing. I think the way I've got it now offers greater flexibility. With the next project I have in mind I'll be wanting to make use of the LayeredUpdates group, and this approach gives me the option of working with more or less groups. Its still under construction but most of the meat is on the bones.
In theory I should still be able to call upon all the groups to draw by calling a single method from the SpriteGroup class.
Here's one of my earlier attempts.
In theory I should still be able to call upon all the groups to draw by calling a single method from the SpriteGroup class.
Here's one of my earlier attempts.
import pygame pygame.init() class ScreenObject(pygame.sprite.Sprite): pass # ScreenObject() ------------------------------------------------------------ """ One of my earlier attempts. """ import pygame def enum(*args): # --------------------------------------------------------------------------- # Used to create enumate values. # # Example: # fruits =enum("APPLES", "ORANGES", "PEARS") # if fruits.APPLES ==fruits.ORANGES: # print("they're the same.") # # --------------------------------------------------------------------------- enums =dict(zip(args, range(len(args)))) return type('Enum', (), enums) # enum() -------------------------------------------------------------------- SPRITE_GROUPS =enum("BACKGROUND", "ZPLANES", "INTERFACE", "OVERLAY") class SpriteGroup: """Screen Object Group - manages sprites within a group. Returns: n/a Functions: add, remove, remove_all, draw Attributes: n/a""" CONST =SPRITE_GROUPS groups = { CONST.BACKGROUND: pygame.sprite.Group(), CONST.ZPLANES: pygame.sprite.Group(), CONST.INTERFACE: pygame.sprite.Group(), CONST.OVERLAY: pygame.sprite.Group(), } @classmethod def add(cls, group, item, z_plane =None): 'Function - adds an item to a group.' result =False if group ==SPRITE_GROUPS.ZPLANES: if isinstance(z_plane, int): pygame.sprite.LayeredUpdates.add(item, z_plane) result =True else: cls.groups[group].add(item ) result =True return result # add() ----------------------------------------------------------------- @classmethod def remove(cls, group, item): 'Function - removes the item from the group.' cls.groups[group].remove(item) # remove() -------------------------------------------------------------- @classmethod def remove_all(cls, item): 'Function - removes the item from all of the groups.' # Build up a list of all the groups managed by this class. grp_lst =[] grp_lst.append(SPRITE_GROUPS.BACKGROUND) grp_lst.append(SPRITE_GROUPS.ZPLANES) grp_lst.append(SPRITE_GROUPS.INTERFACE) grp_lst.append(SPRITE_GROUPS.OVERLAY) # _. # Search all of our groups and remove the item when found. for grp in grp_lst: if grp.has(item): grp.remove() # _. # remove_all() ---------------------------------------------------------- @classmethod def draw(cls, surface): 'Function - draws all the sprite items from all of managed groups.' CONST =SPRITE_GROUPS cls.groups[CONST.BACKGROUND].draw(surface) cls.groups[CONST.ZPLANES].draw(surface) cls.groups[CONST.INTERFACE].draw(surface) cls.groups[CONST.OVERLAY].draw(surface) # draw() ---------------------------------------------------------------- # SpriteGroup --------------------------------------------------------------- item =pygame.sprite.Sprite() CONST =SPRITE_GROUPS SpriteGroup.add( CONST.BACKGROUND, item ) item =pygame.sprite.Sprite() SpriteGroup.add( CONST.ZPLANES, item ) SpriteGroup.CONST.BACKGROUND SPRITE_GROUPS.BACKGROUNDBut the one I want to use is listed below.
import pygame if __name__ =="__main__": pygame.init() from clsExceptions import * # My custom error. class SpriteGroup: """Class - manages groups from the pygame.sprite.Group collection. Returns: n/a Functions: add_item, add_group, remove_item, remove_all_items, draw, init, groups Attributes: n/a""" _groups_list =[] _grp_cntr_id =0 _surface =None # Pygame surface. @classmethod def _new_group_name(cls): for tries in range(1000): cls._grp_cntr_id +=1 name ="Group" +str(cls._grp_cntr_id) grp =cls._search_groups(name) if grp ==None: # The name is unique. fnd =False break else: fnd =True if fnd: # A unique name could not be found, so lets return nothing. name =None return name # _new_group_name() ----------------------------------------------------- @classmethod def _search_groups(cls, name): for grp in cls._groups_list: if grp.name.lower() ==name.lower(): fnd =True break else: fnd =False if not fnd: grp =None return grp # _search_groups() ------------------------------------------------------ @classmethod def add_group(cls, name =None, layered_updates =False): 'Function - adds a new group to the collection.' # NOTE(S): # ------- # There can be only ONE. # # The Layered-Updates is a special group, and there can only be # one. if cls._surface ==None: # The class hasn't been initialised yet. cls.init() if isinstance(name, str): # Check if they passed an empty string. if len(name.strip()) <1: raise CustomError("Group name cannont be an empty string.") else: # Check if a name was passed. if not name ==None: # Something other than a string was passed as a name. raise TypeError("Wrong variable type passed. Expected 'name' to be string.") if not isinstance(layered_updates, bool): raise TypeError("Wrong variable type passed. Expected 'layered_updates' to be boolean.") if name ==None: # Generate a unique name. name =cls._new_group_name() if name ==None: raise CustomError("Failed to generate a unique group name.") # Have a look at all the groups in our collection to see if the # name supplied is already been used by a group. ## for grp in cls._groups_list: ## if grp.name.lower() ==name.lower(): ## fnd =True ## break ## else: ## fnd =False ## ## if fnd: ## raise CustomError("A group with that name already exists.") grp =cls._search_groups(name) if not grp ==None: raise CustomError("A group with that name already exists.") # _. # Search through our collection of groups to see if any of them # have been designated as being the Layered-Updates group. for grp in cls._groups_list: if grp.layered_updates: fnd =True break else: fnd =False # _. if fnd ==True and layered_updates ==True: raise CustomError("There can only be one. {0} has already been designated as the layered-Updates groups.".format(grp.name)) # Create the group and add it to the list. grp =pygame.sprite.Group() grp.name =name grp.layered_updates =layered_updates cls._groups_list.append(grp) # _. return grp # add_group() ----------------------------------------------------------- @classmethod def add_item(cls, group, item, z_plane =None): 'Function - adds a sprite item to a group.' if not isinstance(item, pygame.sprite.Sprite): raise TypeError if not hasattr(item, "layer"): # NOTE(S): # ------- # The default layer is 0. # # If the sprite you add has an attribute 'layer' then that layer # will be used when applying it to the layered updates group. if not z_plane ==None: item.layer =z_plane # Create the attribute. else: item.layer =0 if isinstance(group, pygame.sprite.Group): group.add(item) elif isinstance(group, str): for grp in cls._groups_list: if grp.name.lower() ==group.lower(): fnd =True break else: fnd =False if fnd: if grp.layered_updates: if z_plane ==None: # Allow pygame to add the item to layer based on # the value of the items 'layer' attribute. pygame.sprite.LayeredUpdates.add(item) else: # Make a request to pygame for the item to be added # to the specified layer. pygame.sprite.LayeredUpdates.add(item, z_plane) else: grp.add(item) # add_item() ------------------------------------------------------------ @classmethod def init(cls): 'Function - initialises the class.' return_status =False # The pygame draw methods require a reference to a surface. By # calling this routine we ensure that a reference can easily passed. cls._surface =pygame.display.get_surface() return_status =True return return_status # init() ---------------------------------------------------------------- @classmethod def draw(cls): 'Function - paints any screen object found in the groups onto the screen.' return_status =False for grp in cls._groups_list: if grp.layered_updates: # Call the appropriate draw method. pygame.sprite.LayeredUpdates.draw(cls._surface) else: grp.draw() return_status =True return return_status # draw() --------------------------------------------------------------- @classmethod def groups(cls): 'Function - returns a diction of all the group in the collection.' group_dict ={} for grp in cls._groups_list: group_dict[grp.name] =grp return group_dict # groups() -------------------------------------------------------------- @classmethod def remove_all_items(cls, item): 'Function - removes the item from all the groups.' for grp in cls._groups_list: cls.remove_item(grp.name, item) # remove_all_items() ---------------------------------------------------- @classmethod def remove_item(cls, group, item): 'Function - removes the item from a group.' return_status =False if isinstance(group, pygame.sprite.Group): group.remove(item) elif isinstance(group, str): for grp in cls._groups_list: if grp.name.lower() ==group.lower(): fnd =True break else: fnd =False if fnd: if grp.layered_updates: sprites_list =pygame.sprite.LayeredUpdates.remove_sprites_of_layer(item.layer) for index in range(len(sprites_list)): if sprite_list[index] ==item: fnd =True else: fnd =False if fnd: removed_item =sprites_list.pop(index) pygame.sprite.LayeredUpdates.add(sprite_list) return_status =True else: grp.remove(item) return_status =True return return_status # remove_item() -------------------------------------------------------------- # SpriteGroup ------------------------------------------------------------------ if __name__ =="__main__": grp ={} # Generate a new group by just providing a name. SpriteGroup.add_group("background") # _. # Generate new groups and store them in a dict object. grp["z_layers"] =SpriteGroup.add_group("z_layers", layered_updates=True) grp["interface"] =SpriteGroup.add_group("interface") # _. # Generate a new group and modiying the group name later. new_group =SpriteGroup.add_group() new_group.name ="overlay" # _. # Obtain a full list of groups stored in our collection. full_grp_listing =SpriteGroup.groups() # _. # Generate a new sprite and add it to the special layers group # (LayeredUpdates). player =pygame.sprite.Sprite() SpriteGroup.add_item("z_layers", player) # _. print("Group '{0}' layered group status ={1}.".format(grp["z_layers"].name, grp["z_layers"].layered_updates)) print("\nThe common group var ('grp') has the following groups:") for g in grp: print(" ",g) print() print("The full list of groups returned by the class is as follows:") for g in full_grp_listing: print(" ",g) print("\nPS: Not sure why the groups are listed in Shell output the way they are.\n The groups aren't listed in the order they'll draw to the screen.")and here's my [clsExceptions] exeption class file.
class CustomError(Exception): pass
Output:Group 'z_layers' layered group status =True.
The common group var ('grp') has the following groups:
z_layers
interface
The full list of groups returned by the class is as follows:
z_layers
background
interface
overlay
PS: Not sure why the groups are listed in Shell output the way they are.
The groups aren't listed in the order they'll draw to the screen.