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, Union
from . import GameObject, Hitbox, UIElement
from .. import Error, Defaults, Game
[docs]class Group:
"""The group class implementation."""
[docs] def __init__(self, options: dict = {}) -> None:
"""
Initializes a group object.
Args:
options: A group object config. Defaults to the :ref:`Group defaults <groupdef>`.
"""
param = Defaults.group_defaults | options
self.name: str = param["name"]
self.groups: List[Group] = []
self.game_objects: List[GameObject] = []
self.z_index: int = param["z_index"]
[docs] def add(self, *items: Union[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 Game.state == Game.RUNNING:
item.setup()
if isinstance(item, UIElement):
self.add_ui_element(item)
elif 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 add_ui_element(self, ui: UIElement):
"""Add a ui element to the group."""
if ui.name == "":
ui.name = f"UI {len(self.game_objects)}"
self.game_objects.append(ui)
[docs] def delete(self, item: Union[GameObject, Group]):
"""
Removes an item from the group.
Args:
item: The item to remove 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 setup(self):
for group in self.groups:
group.setup()
for game_obj in self.game_objects:
game_obj.setup()
def update(self):
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 when added to a scene."""
for group in self.groups:
group.fixed_update()
hitboxes: List[Hitbox] = []
for game_obj in self.game_objects:
game_obj.fixed_update()
if hts := game_obj._components.get(Hitbox, []): # pylint: disable=protected-access
for ht in hts:
for hitbox in hitboxes:
ht.collide(hitbox)
hitboxes.extend(hts)
def draw(self):
self.groups.sort(key=lambda i: i.z_index)
for group in self.groups:
if group.z_index <= Game.camera.z_index:
group.draw()
self.game_objects.sort(key=lambda i: i.z_index)
for game_obj in self.game_objects:
if game_obj.z_index <= Game.camera.z_index:
game_obj.draw()
[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
"""
children = 0
for group in self.groups:
children += group.count()
return len(self.game_objects) + children