import logging import random import libs.bg_collabs from libs.bg_objects.bg_fever import BGFever from libs.bg_objects.bg_normal import BGNormal from libs.bg_objects.chibi import ChibiController from libs.bg_objects.dancer import Dancer from libs.bg_objects.don_bg import DonBG from libs.bg_objects.fever import Fever from libs.bg_objects.footer import Footer from libs.bg_objects.renda import RendaController from libs.global_data import Difficulty, PlayerNum from libs.texture import TextureWrapper logger = logging.getLogger(__name__) class Background: """The background class for the game.""" COLLABS = { "A3": (libs.bg_collabs.a3.Background, 'background/collab/a3', 4), "ANIMAL": (libs.bg_collabs.animal.Background, 'background/collab/animal', 5), "BUTTOBURST": (libs.bg_collabs.buttoburst.Background, 'background/collab/buttoburst', 4), "OSHIRI": (libs.bg_collabs.oshiri.Background, 'background/collab/oshiri', 5), "IMAS": (libs.bg_collabs.imas.Background, 'background/collab/imas', 5), "IMAS_CG": (libs.bg_collabs.imas.Background, 'background/collab/imas_cg', 3), "IMAS_ML": (libs.bg_collabs.imas.Background, 'background/collab/imas_ml', 3), "IMAS_SIDEM": (libs.bg_collabs.imas_sidem.Background, 'background/collab/imas_sidem', 3), "DAN": (libs.bg_collabs.dan.Background, 'background/collab/dan', 1), "PRACTICE": (libs.bg_collabs.practice.Background, 'background/collab/practice', 1) } def __init__(self, player_num: PlayerNum, bpm: float, scene_preset: str = ''): """ Initialize the background class. Args: player_num (int): The player number. bpm (float): The beats per minute. scene_preset (str): The scene preset. """ self.tex_wrapper = TextureWrapper() self.tex_wrapper.load_animations('background') if player_num == PlayerNum.TWO_PLAYER: if scene_preset == '': self.max_dancers = 5 don_bg_num = random.randint(0, 5) self.don_bg = DonBG.create(self.tex_wrapper, don_bg_num, PlayerNum.P1) self.don_bg_2 = DonBG.create(self.tex_wrapper, don_bg_num, PlayerNum.P2) self.renda = RendaController(self.tex_wrapper, random.randint(0, 2)) self.chibi = ChibiController(self.tex_wrapper, random.randint(0, 13), bpm) self.bg_normal = None self.bg_fever = None self.footer = None self.fever = None self.dancer = None else: bg_obj, path, max_dancers = Background.COLLABS[scene_preset] collab_bg = bg_obj(self.tex_wrapper, PlayerNum.P1, bpm, path, max_dancers) self.max_dancers = max_dancers self.don_bg = collab_bg.don_bg self.don_bg_2 = collab_bg.don_bg self.bg_normal = None self.bg_fever = None self.footer = None self.fever = None self.dancer = None self.renda = collab_bg.renda self.chibi = collab_bg.chibi elif scene_preset == '': self.max_dancers = 5 self.don_bg = DonBG.create(self.tex_wrapper, random.randint(0, 5), player_num) self.don_bg_2 = None self.bg_normal = BGNormal.create(self.tex_wrapper, random.randint(0, 4)) self.bg_fever = BGFever.create(self.tex_wrapper, random.randint(0, 3)) self.footer = Footer(self.tex_wrapper, random.randint(0, 2)) self.fever = Fever.create(self.tex_wrapper, random.randint(0, 3), bpm) self.dancer = Dancer.create(self.tex_wrapper, random.randint(0, 20), bpm) self.renda = RendaController(self.tex_wrapper, random.randint(0, 2)) self.chibi = ChibiController(self.tex_wrapper, random.randint(0, 13), bpm) else: bg_obj, path, max_dancers = Background.COLLABS[scene_preset] collab_bg = bg_obj(self.tex_wrapper, PlayerNum.P1, bpm, path, max_dancers) self.max_dancers = max_dancers self.don_bg = collab_bg.don_bg self.don_bg_2 = None self.bg_normal = collab_bg.bg_normal self.bg_fever = collab_bg.bg_fever self.footer = collab_bg.footer self.fever = collab_bg.fever self.dancer = collab_bg.dancer self.renda = collab_bg.renda self.chibi = collab_bg.chibi self.is_clear = False self.is_rainbow = False self.last_milestone = 1 logger.info(f"Background initialized for player {player_num}, bpm={bpm}, scene_preset={scene_preset}") def add_chibi(self, bad: bool, player_num: int): """ Add a chibi to the background. Args: player_num (int): The player number. bad (bool): Whether the chibi is bad. """ if self.chibi is not None: self.chibi.add_chibi(player_num, bad) def add_renda(self): """ Add a renda to the background. """ if self.renda is not None: self.renda.add_renda() def update(self, current_time_ms: float, bpm: float, gauge_1p = None, gauge_2p = None): """ Update the background. Args: current_time_ms (float): The current time in milliseconds. bpm (float): The beats per minute. gauge_1p (Gauge): The gauge object for player 1. gauge_2p (Gauge): The gauge object for player 2. """ if self.dancer is not None and gauge_1p is not None: clear_threshold = gauge_1p.clear_start[min(gauge_1p.difficulty, Difficulty.ONI)] if gauge_1p.gauge_length < clear_threshold: current_milestone = min(self.max_dancers - 1, int(gauge_1p.gauge_length / (clear_threshold / self.max_dancers))) else: current_milestone = self.max_dancers if current_milestone > self.last_milestone and current_milestone <= self.max_dancers: self.dancer.add_dancer() self.last_milestone = current_milestone logger.info(f"Dancer milestone reached: {current_milestone}/{self.max_dancers}") if self.bg_fever is not None and gauge_1p is not None: if not self.is_clear and gauge_1p.is_clear: self.bg_fever.start() logger.info("Fever started") if not self.is_rainbow and gauge_1p.is_rainbow and self.fever is not None: self.fever.start() logger.info("Rainbow fever started") if gauge_1p is not None: self.is_clear = gauge_1p.is_clear self.is_rainbow = gauge_1p.is_rainbow self.don_bg.update(current_time_ms, self.is_clear) if self.don_bg_2 is not None and gauge_2p is not None: self.don_bg_2.update(current_time_ms, gauge_2p.is_clear) if self.bg_normal is not None: self.bg_normal.update(current_time_ms) if self.bg_fever is not None: self.bg_fever.update(current_time_ms) if self.fever is not None: self.fever.update(current_time_ms, bpm) if self.dancer is not None: self.dancer.update(current_time_ms, bpm) if self.renda is not None: self.renda.update(current_time_ms) if self.chibi is not None: self.chibi.update(current_time_ms, bpm) def draw(self): """ Draw the background. """ if self.bg_normal is not None: if self.bg_fever is not None: if self.is_clear and not self.bg_fever.transitioned: self.bg_normal.draw(self.tex_wrapper) self.bg_fever.draw(self.tex_wrapper) elif self.is_clear: self.bg_fever.draw(self.tex_wrapper) else: self.bg_normal.draw(self.tex_wrapper) else: self.bg_normal.draw(self.tex_wrapper) self.don_bg.draw(self.tex_wrapper) if self.don_bg_2 is not None: self.don_bg_2.draw(self.tex_wrapper, y=536) if self.renda is not None: self.renda.draw() if self.dancer is not None: self.dancer.draw(self.tex_wrapper) if self.footer is not None: self.footer.draw(self.tex_wrapper) if self.is_rainbow and self.fever is not None: self.fever.draw(self.tex_wrapper) if self.chibi is not None: self.chibi.draw() def unload(self): """ Unload the background. """ self.tex_wrapper.unload_textures() logger.info("Background textures unloaded")