Source code for rubato.classes.group

"""
Groups contain game objects or other groups and allow separation between game objects.
"""
from __future__ import annotations
from typing import List, TYPE_CHECKING

from . import GameObject, Hitbox, Engine
from .. import Error

if TYPE_CHECKING:
    from . import Camera


[docs]class Group: """ The group class implementation. Args: name: The name of the group. Defaults to "" and is set to "Group #" when it is added to another Group or Scene. z_index: The z-index of the group. Defaults to 0. active: Whether the group is active or not. Defaults to True. Attributes: name (str): The name of the group. groups (List[Group]): A list of groups that are children of this group. game_objects (List[GameObject]): A list of game objects that are children of this group. z_index (int): The z-index of the group. active (bool): Whether the group is active or not. """ def __init__(self, name: str = "", z_index: int = 0, active: bool = True): self.name: str = name self.groups: List[Group] = [] self.game_objects: List[GameObject] = [] self.z_index: int = z_index self.active: bool = active
[docs] def add(self, *items: GameObject | Group): """ Adds an item to the group. Args: items: The item(s) you wish to add to the group Raises: Error: The item being added is the group itself. A group cannot be added to itself. ValueError: The group can only hold game objects or other groups. """ for item in items: if isinstance(item, GameObject): self.add_game_obj(item) elif isinstance(item, Group): self.add_group(item) else: raise ValueError(f"The group {self.name} can only hold game objects/groups.")
[docs] def add_group(self, g: Group): """Add a group to the group.""" if self == g: raise Error("Cannot add a group to itself.") if g.name == "": g.name = f"Group {len(self.groups)}" self.groups.append(g)
[docs] def add_game_obj(self, g: GameObject): """Add a game object to the group""" if g.name == "": g.name = f"Game Object {len(self.game_objects)}" self.game_objects.append(g)
[docs] def delete(self, item: GameObject | Group): """ Removes an item from the group. Args: item: The item to remove from the group. Note: The actually game object is not deleted, just removed from the group. Raises: ValueError: The item is not in the group and cannot be deleted. """ try: if isinstance(item, GameObject): self.game_objects.remove(item) elif isinstance(item, Group): self.groups.remove(item) except ValueError as e: raise ValueError(f"The item {item.name} is not in the group {self.name}") from e
def update(self): if self.active: for group in self.groups: group.update() for game_obj in self.game_objects: game_obj.update()
[docs] def fixed_update(self): """ Runs a physics iteration on the group. Called automatically by rubato as long as the group is added to a scene. """ if self.active: for game_obj in self.game_objects: game_obj.fixed_update() # collide all hitboxes with each other hitboxes: List[Hitbox] = [] for game_obj in self.game_objects: if hts := game_obj._components.get(Hitbox, []): # pylint: disable=protected-access for ht in hts: for hitbox in hitboxes: Engine.collide(ht, hitbox) hitboxes.extend(hts) for group in self.groups: group.fixed_update() # collide children groups with parent hitboxes for game_obj in group.game_objects: if hts := game_obj._components.get(Hitbox, []): # pylint: disable=protected-access for ht in hts: for hitbox in hitboxes: Engine.collide(ht, hitbox)
def draw(self, camera: Camera): if self.active: self.groups.sort(key=lambda i: i.z_index) for group in self.groups: if group.z_index <= camera.z_index: group.draw(camera) self.game_objects.sort(key=lambda i: i.z_index) for game_obj in self.game_objects: if game_obj.z_index <= camera.z_index: game_obj.draw(camera)
[docs] def count(self) -> int: """ Counts all the GameObjects in this group and all groups it contains. Returns: int: The number of GameObjects in a group """ return len(self.game_objects) + sum([group.count() for group in self.groups])