diff --git a/PyTaiko.py b/PyTaiko.py index a0dc86a..a7af7b5 100644 --- a/PyTaiko.py +++ b/PyTaiko.py @@ -79,6 +79,8 @@ def main(): ray.init_window(screen_width, screen_height, "PyTaiko") global_data.tex.load_screen_textures('global') + global_data.tex.load_zip('chara', 'chara_0') + global_data.tex.load_zip('chara', 'chara_1') if global_data.config["video"]["borderless"]: ray.toggle_borderless_windowed() if global_data.config["video"]["fullscreen"]: diff --git a/libs/background.py b/libs/background.py index 6c2b631..221bf00 100644 --- a/libs/background.py +++ b/libs/background.py @@ -51,8 +51,6 @@ class Background: self.renda.add_renda() def update(self, current_time_ms: float, bpm: float, gauge): - is_clear = gauge.gauge_length > gauge.clear_start[min(gauge.difficulty, 3)] - is_rainbow = gauge.gauge_length == gauge.gauge_max clear_threshold = gauge.clear_start[min(gauge.difficulty, 3)] if gauge.gauge_length < clear_threshold: current_milestone = min(self.max_dancers - 1, int(gauge.gauge_length / (clear_threshold / self.max_dancers))) @@ -61,12 +59,12 @@ class Background: if current_milestone > self.last_milestone and current_milestone < self.max_dancers: self.dancer.add_dancer() self.last_milestone = current_milestone - if not self.is_clear and is_clear: + if not self.is_clear and gauge.is_clear: self.bg_fever.start() - if not self.is_rainbow and is_rainbow and self.fever is not None: + if not self.is_rainbow and gauge.is_rainbow and self.fever is not None: self.fever.start() - self.is_clear = is_clear - self.is_rainbow = is_rainbow + self.is_clear = gauge.is_clear + self.is_rainbow = gauge.is_rainbow self.don_bg.update(current_time_ms, self.is_clear) self.bg_normal.update(current_time_ms) self.bg_fever.update(current_time_ms) diff --git a/libs/chara_2d.py b/libs/chara_2d.py new file mode 100644 index 0000000..5be94a8 --- /dev/null +++ b/libs/chara_2d.py @@ -0,0 +1,74 @@ +from libs.animation import Animation +from libs.utils import global_data + +class Chara2D: + def __init__(self, index: int, bpm: float, path: str = 'chara'): + self.name = "chara_" + str(index) + self.tex = global_data.tex + self.anims = dict() + self.bpm = bpm + self.current_anim = 'normal' + self.past_anim = 'normal' + self.is_rainbow = False + self.is_clear = False + self.temp_anims = {'10_combo','10_combo_max', 'soul_in', 'clear_in', 'balloon_pop', 'balloon_miss'} + for name in self.tex.textures[self.name]: + tex_list = self.tex.textures[self.name][name].texture + keyframe_len = len(tex_list) if isinstance(tex_list, list) else 1 + if index == 0: + duration = 2250*2 / self.bpm + else: + duration = 2250 / self.bpm + total_duration = duration * keyframe_len + keyframes = [i for i in range(keyframe_len)] + textures = [[duration*i, duration*(i+1), index] for i, index in enumerate(keyframes)] + self.anims[name] = Animation.create_texture_change(total_duration, textures=textures) + self.anims[name].start() + + def set_animation(self, name: str): + if name == self.current_anim: + return + if self.current_anim in self.temp_anims: + return + self.past_anim = self.current_anim + if name == 'balloon_pop' or name == 'balloon_miss': + self.past_anim = 'normal' + if self.is_clear: + self.past_anim = 'clear' + self.current_anim = name + self.anims[name].start() + def update(self, current_time_ms: float, bpm: float, is_clear: bool, is_rainbow: bool): + if is_rainbow and not self.is_rainbow: + self.is_rainbow = True + self.set_animation('soul_in') + if is_clear and not self.is_clear: + self.is_clear = True + self.set_animation('clear_in') + self.past_anim = 'clear' + if bpm != self.bpm: + self.bpm = bpm + for name in self.tex.textures[self.name]: + tex_list = self.tex.textures[self.name][name].texture + keyframe_len = len(tex_list) if isinstance(tex_list, list) else 1 + duration = 2250 / self.bpm + total_duration = duration * keyframe_len + keyframes = [i for i in range(keyframe_len)] + textures = [[duration*i, duration*(i+1), index] for i, index in enumerate(keyframes)] + self.anims[name] = Animation.create_texture_change(total_duration, textures=textures) + self.anims[name].start() + self.anims[self.current_anim] = self.anims[self.current_anim] + self.anims[self.current_anim].update(current_time_ms) + if self.anims[self.current_anim].is_finished: + if self.current_anim in self.temp_anims: + self.anims[self.current_anim].reset() + self.current_anim = self.past_anim + self.anims[self.current_anim].restart() + + def draw(self, x: float = 0, y: float = 0, mirror=False): + if self.is_rainbow and self.current_anim not in {'soul_in', 'balloon_pop', 'balloon_popping'}: + self.tex.draw_texture(self.name, self.current_anim + '_max', frame=self.anims[self.current_anim].attribute, x=x, y=y) + else: + if mirror: + self.tex.draw_texture(self.name, self.current_anim, frame=self.anims[self.current_anim].attribute, x=x, y=y, mirror='horizontal') + else: + self.tex.draw_texture(self.name, self.current_anim, frame=self.anims[self.current_anim].attribute, x=x, y=y) diff --git a/libs/texture.py b/libs/texture.py index 8051187..43a264f 100644 --- a/libs/texture.py +++ b/libs/texture.py @@ -98,6 +98,9 @@ class TextureWrapper: def load_zip(self, screen_name: str, subset: str): zip = (self.graphics_path / screen_name / subset).with_suffix('.zip') + if screen_name in self.textures and subset in self.textures[screen_name]: + print(screen_name, subset) + return with zipfile.ZipFile(zip, 'r') as zip_ref: if 'texture.json' not in zip_ref.namelist(): raise Exception(f"texture.json file missing from {zip}") diff --git a/scenes/entry.py b/scenes/entry.py index 6fb127a..4986af0 100644 --- a/scenes/entry.py +++ b/scenes/entry.py @@ -3,6 +3,7 @@ from pathlib import Path import pyray as ray from libs.audio import audio +from libs.chara_2d import Chara2D from libs.global_objects import Nameplate, Indicator from libs.texture import tex from libs.utils import ( @@ -55,6 +56,7 @@ class EntryScreen: self.cloud_fade = tex.get_animation(8) self.nameplate_fadein = tex.get_animation(12) self.side_select_fade.start() + self.chara = Chara2D(0, 100) audio.play_sound(self.bgm) def on_screen_end(self, next_screen: str): @@ -85,6 +87,10 @@ class EntryScreen: self.nameplate = Nameplate(plate_info['name'], plate_info['title'], round((self.side/3) + 1), plate_info['dan'], plate_info['gold']) self.nameplate_fadein.start() self.state = State.SELECT_MODE + if self.side == 2: + self.chara = Chara2D(1, 100) + else: + self.chara = Chara2D(0, 100) audio.play_sound(self.sound_don) if is_l_kat_pressed(): audio.play_sound(self.sound_kat) @@ -105,19 +111,21 @@ class EntryScreen: def update(self): self.on_screen_start() - self.side_select_fade.update(get_current_ms()) - self.bg_flicker.update(get_current_ms()) - self.drum_move_1.update(get_current_ms()) - self.drum_move_2.update(get_current_ms()) - self.drum_move_3.update(get_current_ms()) - self.cloud_resize.update(get_current_ms()) - self.cloud_texture_change.update(get_current_ms()) - self.cloud_fade.update(get_current_ms()) - self.cloud_resize_loop.update(get_current_ms()) - self.box_manager.update(get_current_ms()) - self.nameplate_fadein.update(get_current_ms()) - self.nameplate.update(get_current_ms()) - self.indicator.update(get_current_ms()) + current_time = get_current_ms() + self.side_select_fade.update(current_time) + self.bg_flicker.update(current_time) + self.drum_move_1.update(current_time) + self.drum_move_2.update(current_time) + self.drum_move_3.update(current_time) + self.cloud_resize.update(current_time) + self.cloud_texture_change.update(current_time) + self.cloud_fade.update(current_time) + self.cloud_resize_loop.update(current_time) + self.box_manager.update(current_time) + self.nameplate_fadein.update(current_time) + self.nameplate.update(current_time) + self.indicator.update(current_time) + self.chara.update(current_time, 100, False, False) if self.box_manager.is_finished(): return self.on_screen_end(self.box_manager.selected_box()) return self.handle_input() @@ -152,6 +160,8 @@ class EntryScreen: tex.draw_texture('side_select', 'question', fade=fade) + self.chara.draw(480, 240) + tex.draw_texture('side_select', '1P', fade=fade) tex.draw_texture('side_select', 'cancel', fade=fade) tex.draw_texture('side_select', '2P', fade=fade) @@ -181,6 +191,10 @@ class EntryScreen: scale = self.cloud_resize.attribute if self.cloud_resize.is_finished: scale = max(1, self.cloud_resize_loop.attribute) + if self.side == 2: + self.chara.draw(move_x + offset + 130, 570 + move_y, mirror=True) + else: + self.chara.draw(move_x + offset + 170, 570 + move_y) tex.draw_texture('side_select', 'cloud', x=move_x + offset, y=move_y, frame=self.cloud_texture_change.attribute, fade=self.cloud_fade.attribute, scale=scale, center=True) def draw_mode_select(self): diff --git a/scenes/game.py b/scenes/game.py index bcf115b..f52ded6 100644 --- a/scenes/game.py +++ b/scenes/game.py @@ -10,6 +10,7 @@ import pyray as ray from libs.animation import Animation from libs.audio import audio from libs.background import Background +from libs.chara_2d import Chara2D from libs.global_objects import Nameplate from libs.texture import tex from libs.tja import ( @@ -164,7 +165,7 @@ class GameScreen: self.movie.update() else: if len(self.player_1.current_bars) > 0: - self.bpm = self.player_1.current_bars[0].bpm + self.bpm = self.player_1.bpm if self.background is not None: self.background.update(current_time, self.bpm, self.player_1.gauge) @@ -240,6 +241,7 @@ class Player: self.is_balloon = False self.curr_balloon_count = 0 self.balloon_index = 0 + self.bpm = self.play_notes[0].bpm if self.play_notes else 120 #Score management self.good_count = 0 @@ -264,6 +266,7 @@ class Player: self.score_counter = ScoreCounter(self.score) plate_info = global_data.config['nameplate'] self.nameplate = Nameplate(plate_info['name'], plate_info['title'], global_data.player_num, plate_info['dan'], plate_info['gold']) + self.chara = Chara2D(player_number - 1, self.bpm) self.input_log: dict[float, tuple] = dict() @@ -397,6 +400,8 @@ class Player: if note.type < 7: self.combo += 1 + if self.combo % 10 == 0: + self.chara.set_animation('10_combo') if self.combo > self.max_combo: self.max_combo = self.combo @@ -521,9 +526,11 @@ class Player: def balloon_manager(self, current_time: float): if self.balloon_anim is not None: + self.chara.set_animation('balloon_popping') self.balloon_anim.update(current_time, self.curr_balloon_count, not self.is_balloon) if self.balloon_anim.is_finished: self.balloon_anim = None + self.chara.set_animation('balloon_pop') if self.kusudama_anim is not None: self.kusudama_anim.update(current_time, not self.is_balloon) self.kusudama_anim.update_count(self.curr_balloon_count) @@ -617,6 +624,9 @@ class Player: self.handle_input(game_screen, current_time) self.nameplate.update(current_time) self.gauge.update(current_time) + if self.play_notes: + self.bpm = self.play_notes[0].bpm + self.chara.update(current_time, self.bpm, self.gauge.is_clear, self.gauge.is_rainbow) def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int): start_position = self.get_position_x(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_x) @@ -668,13 +678,7 @@ class Player: if not self.current_notes_draw: return - # Cache eighth calculations - if self.current_bars: - bpm = self.current_bars[0].bpm - else: - bpm = self.current_notes_draw[0].bpm - - eighth_in_ms = 0 if bpm == 0 else (60000 * 4 / bpm) / 8 + eighth_in_ms = 0 if self.bpm == 0 else (60000 * 4 / self.bpm) / 8 current_eighth = 0 if self.combo >= 50 and eighth_in_ms != 0: current_eighth = int((current_ms - start_ms) // eighth_in_ms) @@ -721,7 +725,6 @@ class Player: tex.draw_texture('lane', 'lane_hit_circle') for anim in self.draw_judge_list: anim.draw() - current_ms = game_screen.current_ms self.draw_bars(current_ms) self.draw_notes(current_ms, game_screen.start_ms) @@ -738,6 +741,7 @@ class Player: if not global_data.modifiers.auto: self.nameplate.draw(-62, 285) self.draw_modifiers() + self.chara.draw() if self.drumroll_counter is not None: self.drumroll_counter.draw() for anim in self.draw_arc_list: @@ -1047,7 +1051,7 @@ class BalloonAnimation: tex.draw_texture('balloon', 'pop', frame=7, color=self.color) elif self.balloon_count >= 1: balloon_index = min(6, (self.balloon_count - 1) * 6 // self.balloon_total) - tex.draw_texture('balloon', 'pop', frame=balloon_index, color=self.color) + tex.draw_texture('balloon', 'pop', frame=balloon_index, color=self.color, index=global_data.player_num-1) if self.balloon_count > 0: tex.draw_texture('balloon', 'bubble') counter = str(max(0, self.balloon_total - self.balloon_count + 1)) @@ -1335,6 +1339,8 @@ class Gauge: self.clear_start = [68, 68, 68, 68] self.gauge_max = 87 self.level = min(10, level) + self.is_clear = False + self.is_rainbow = False self.table = [ [ None, @@ -1404,6 +1410,8 @@ class Gauge: self.gauge_length = 0 def update(self, current_ms: float): + self.is_clear = self.gauge_length > self.clear_start[min(self.difficulty, 3)] + self.is_rainbow = self.gauge_length == self.gauge_max if self.gauge_length == 87 and self.rainbow_fade_in is None: self.rainbow_fade_in = Animation.create_fade(450, initial_opacity=0.0, final_opacity=1.0) self.rainbow_fade_in.start() diff --git a/scenes/result.py b/scenes/result.py index 1cb0fed..39be65c 100644 --- a/scenes/result.py +++ b/scenes/result.py @@ -5,6 +5,7 @@ from raylib import SHADER_UNIFORM_FLOAT from libs import utils from libs.audio import audio +from libs.chara_2d import Chara2D from libs.global_objects import Nameplate from libs.texture import tex from libs.utils import ( @@ -57,6 +58,7 @@ class ResultScreen: self.high_score_indicator = None plate_info = global_data.config['nameplate'] self.nameplate = Nameplate(plate_info['name'], plate_info['title'], global_data.player_num, plate_info['dan'], plate_info['gold']) + self.chara = Chara2D(global_data.player_num - 1, 100) self.score_animator = ScoreAnimator(session_data.result_score) self.score = '' self.good = '' @@ -124,8 +126,8 @@ class ResultScreen: def update(self): self.on_screen_start() - - self.fade_in.update(get_current_ms()) + current_time = get_current_ms() + self.fade_in.update(current_time) if self.fade_in.is_finished and self.gauge is None: self.gauge = Gauge(str(global_data.player_num), session_data.result_gauge_length) self.bottom_characters.start() @@ -137,37 +139,38 @@ class ResultScreen: self.crown = Crown() if self.gauge is not None: - self.gauge.update(get_current_ms()) + self.gauge.update(current_time) if self.gauge.is_finished and self.score_delay is None: - self.score_delay = get_current_ms() + 1883 + self.score_delay = current_time + 1883 if self.score_delay is not None: - if get_current_ms() > self.score_delay and not self.fade_in_bottom.is_started: + if current_time > self.score_delay and not self.fade_in_bottom.is_started: self.fade_in_bottom.start() if self.gauge is not None: self.state = self.gauge.state if self.high_score_indicator is not None: - self.high_score_indicator.update(get_current_ms()) + self.high_score_indicator.update(current_time) - self.fade_in_bottom.update(get_current_ms()) + self.fade_in_bottom.update(current_time) alpha_loc = ray.get_shader_location(self.alpha_shader, "ext_alpha") alpha_value = ray.ffi.new('float*', self.fade_in_bottom.attribute) ray.set_shader_value(self.alpha_shader, alpha_loc, alpha_value, SHADER_UNIFORM_FLOAT) - if get_current_ms() >= self.start_ms + 5000 and not self.fade_out.is_started: + if current_time >= self.start_ms + 5000 and not self.fade_out.is_started: self.handle_input() self.update_score_animation() - self.fade_out.update(get_current_ms()) + self.fade_out.update(current_time) if self.fade_out.is_finished: return self.on_screen_end() if self.crown is not None: - self.crown.update(get_current_ms()) + self.crown.update(current_time) - self.nameplate.update(get_current_ms()) + self.nameplate.update(current_time) + self.chara.update(current_time, 100, False, False) def draw_score_info(self): if self.good != '': @@ -260,6 +263,8 @@ class ResultScreen: if self.high_score_indicator is not None: self.high_score_indicator.draw() + self.chara.draw(y=100) + self.fade_in.draw() ray.draw_rectangle(0, 0, self.width, self.height, ray.fade(ray.BLACK, self.fade_out.attribute)) diff --git a/scenes/song_select.py b/scenes/song_select.py index 1678954..901f9f2 100644 --- a/scenes/song_select.py +++ b/scenes/song_select.py @@ -9,6 +9,7 @@ import pyray as ray from libs.animation import Animation, MoveAnimation from libs.audio import audio +from libs.chara_2d import Chara2D from libs.global_objects import Nameplate, Indicator from libs.texture import tex from libs.tja import TJAParser, test_encodings @@ -75,6 +76,7 @@ class SongSelectScreen: self.diff_sort_selector = None self.neiro_selector = None self.modifier_selector = None + self.chara = Chara2D(global_data.player_num - 1, 100) self.texture_index = SongBox.DEFAULT_INDEX self.last_texture_index = SongBox.DEFAULT_INDEX self.last_moved = get_current_ms() @@ -352,17 +354,19 @@ class SongSelectScreen: ret_val = self.on_screen_start() if ret_val is not None: return ret_val - self.background_move.update(get_current_ms()) - self.move_away.update(get_current_ms()) - self.diff_fade_out.update(get_current_ms()) - self.background_fade_change.update(get_current_ms()) - self.text_fade_out.update(get_current_ms()) - self.text_fade_in.update(get_current_ms()) - self.ura_switch_animation.update(get_current_ms()) - self.diff_selector_move_1.update(get_current_ms()) - self.diff_selector_move_2.update(get_current_ms()) - self.nameplate.update(get_current_ms()) - self.indicator.update(get_current_ms()) + current_time = get_current_ms() + self.background_move.update(current_time) + self.move_away.update(current_time) + self.diff_fade_out.update(current_time) + self.background_fade_change.update(current_time) + self.text_fade_out.update(current_time) + self.text_fade_in.update(current_time) + self.ura_switch_animation.update(current_time) + self.diff_selector_move_1.update(current_time) + self.diff_selector_move_2.update(current_time) + self.nameplate.update(current_time) + self.indicator.update(current_time) + self.chara.update(current_time, 100, False, False) if self.text_fade_out.is_finished: self.selected_song = True @@ -470,11 +474,6 @@ class SongSelectScreen: tex.draw_texture('global', 'footer') - if self.nameplate.player_num == 1: - self.nameplate.draw(30, 640) - else: - self.nameplate.draw(950, 640) - self.ura_switch_animation.draw() if self.state == State.BROWSING and self.navigator.items != []: @@ -490,14 +489,35 @@ class SongSelectScreen: else: tex.draw_texture('global', 'song_select', fade=self.text_fade_out.attribute) + offset = 0 + direction = 1 + if self.neiro_selector is not None: + offset = self.neiro_selector.move.attribute + if self.neiro_selector.is_confirmed: + offset += -370 + else: + offset *= -1 + if self.modifier_selector is not None: + offset = self.modifier_selector.move.attribute + if self.modifier_selector.is_confirmed: + offset += -370 + else: + offset *= -1 + if self.nameplate.player_num == 1: + self.nameplate.draw(30, 640) + self.chara.draw(x=-50, y=410 + (offset*0.6)) + else: + self.nameplate.draw(950, 640) + self.chara.draw(mirror=True, x=950, y=410 + (offset*0.6)) + + self.indicator.draw(410, 575) + if self.neiro_selector is not None: self.neiro_selector.draw() if self.modifier_selector is not None: self.modifier_selector.draw() - self.indicator.draw(410, 575) - if self.game_transition is not None: self.game_transition.draw() @@ -1235,28 +1255,29 @@ class NeiroSelector: y = -370 + self.move.attribute else: y = -self.move.attribute - tex.draw_texture('neiro', 'background', y=y) - tex.draw_texture('neiro', f'{global_data.player_num}p', y=y) - tex.draw_texture('neiro', 'divisor', y=y) - tex.draw_texture('neiro', 'music_note', y=y, x=(self.move_sideways.attribute*self.direction), fade=self.fade_sideways.attribute) - tex.draw_texture('neiro', 'music_note', y=y, x=(self.direction*-100) + (self.move_sideways.attribute*self.direction), fade=1 - self.fade_sideways.attribute) - tex.draw_texture('neiro', 'blue_arrow', y=y, x=-self.blue_arrow_move.attribute, fade=self.blue_arrow_fade.attribute) - tex.draw_texture('neiro', 'blue_arrow', y=y, x=200 + self.blue_arrow_move.attribute, mirror='horizontal', fade=self.blue_arrow_fade.attribute) + x = (global_data.player_num - 1) * 800 + tex.draw_texture('neiro', 'background', x=x, y=y) + tex.draw_texture('neiro', f'{global_data.player_num}p', x=x, y=y) + tex.draw_texture('neiro', 'divisor', x=x, y=y) + tex.draw_texture('neiro', 'music_note', y=y, x=x+(self.move_sideways.attribute*self.direction), fade=self.fade_sideways.attribute) + tex.draw_texture('neiro', 'music_note', y=y, x=x+(self.direction*-100) + (self.move_sideways.attribute*self.direction), fade=1 - self.fade_sideways.attribute) + tex.draw_texture('neiro', 'blue_arrow', y=y, x=x-self.blue_arrow_move.attribute, fade=self.blue_arrow_fade.attribute) + tex.draw_texture('neiro', 'blue_arrow', y=y, x=x+200 + self.blue_arrow_move.attribute, mirror='horizontal', fade=self.blue_arrow_fade.attribute) counter = str(self.selected_sound+1) total_width = len(counter) * 20 for i in range(len(counter)): - tex.draw_texture('neiro', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * 20), y=y) + tex.draw_texture('neiro', 'counter', frame=int(counter[i]), x=x-(total_width // 2) + (i * 20), y=y) counter = str(len(self.sounds)) total_width = len(counter) * 20 for i in range(len(counter)): - tex.draw_texture('neiro', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * 20) + 60, y=y) + tex.draw_texture('neiro', 'counter', frame=int(counter[i]), x=x-(total_width // 2) + (i * 20) + 60, y=y) - dest = ray.Rectangle(235 - (self.text.texture.width//2) + (self.move_sideways.attribute*self.direction), y+1000, self.text.texture.width, self.text.texture.height) + dest = ray.Rectangle(x+235 - (self.text.texture.width//2) + (self.move_sideways.attribute*self.direction), y+1000, self.text.texture.width, self.text.texture.height) self.text.draw(self.text.default_src, dest, ray.Vector2(0, 0), 0, ray.fade(ray.WHITE, self.fade_sideways.attribute)) - dest = ray.Rectangle((self.direction*-100) + 235 - (self.text_2.texture.width//2) + (self.move_sideways.attribute*self.direction), y+1000, self.text_2.texture.width, self.text_2.texture.height) + dest = ray.Rectangle(x+(self.direction*-100) + 235 - (self.text_2.texture.width//2) + (self.move_sideways.attribute*self.direction), y+1000, self.text_2.texture.width, self.text_2.texture.height) self.text_2.draw(self.text_2.default_src, dest, ray.Vector2(0, 0), 0, ray.fade(ray.WHITE, 1 - self.fade_sideways.attribute)) class ModifierSelector: @@ -1392,18 +1413,19 @@ class ModifierSelector: move = self.move.attribute - 370 else: move = -self.move.attribute - tex.draw_texture('modifier', 'top', y=move) - tex.draw_texture('modifier', f'{global_data.player_num}p', y=move) - tex.draw_texture('modifier', 'bottom', y=move + (len(self.mods)*50)) + x = (global_data.player_num - 1) * 800 + tex.draw_texture('modifier', 'top', y=move, x=x) + tex.draw_texture('modifier', f'{global_data.player_num}p', y=move, x=x) + tex.draw_texture('modifier', 'bottom', y=move + (len(self.mods)*50), x=x) for i in range(len(self.mods)): - tex.draw_texture('modifier', 'background', y=move + (i*50)) + tex.draw_texture('modifier', 'background', y=move + (i*50), x=x) if i == self.current_mod_index: - tex.draw_texture('modifier', 'mod_bg_highlight', y=move + (i*50)) + tex.draw_texture('modifier', 'mod_bg_highlight', y=move + (i*50), x=x) else: - tex.draw_texture('modifier', 'mod_bg', y=move + (i*50)) - tex.draw_texture('modifier', 'mod_box', y=move + (i*50)) - dest = ray.Rectangle(92, 819 + move + (i*50), self.text_name[i].texture.width, self.text_name[i].texture.height) + tex.draw_texture('modifier', 'mod_bg', y=move + (i*50), x=x) + tex.draw_texture('modifier', 'mod_box', y=move + (i*50), x=x) + dest = ray.Rectangle(92 + x, 819 + move + (i*50), self.text_name[i].texture.width, self.text_name[i].texture.height) self.text_name[i].draw(self.text_name[i].default_src, dest, ray.Vector2(0, 0), 0, ray.WHITE) current_mod = self.mods[i] @@ -1412,44 +1434,44 @@ class ModifierSelector: if current_mod.type is bool: if current_value: - tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50)) - x = 330 - (self.text_true.texture.width//2) - y = 819 + move + (i*50) - self._draw_animated_text(self.text_true, self.text_true_2, x, y, is_current_mod) + tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50), x=x) + text_x = 330 - (self.text_true.texture.width//2) + text_y = 819 + move + (i*50) + self._draw_animated_text(self.text_true, self.text_true_2, text_x + x, text_y, is_current_mod) else: - x = 330 - (self.text_false.texture.width//2) - y = 819 + move + (i*50) - self._draw_animated_text(self.text_false, self.text_false_2, x, y, is_current_mod) + text_x = 330 - (self.text_false.texture.width//2) + text_y = 819 + move + (i*50) + self._draw_animated_text(self.text_false, self.text_false_2, text_x + x, text_y, is_current_mod) elif current_mod.name == 'speed': - x = 330 - (self.text_speed.texture.width//2) - y = 819 + move + (i*50) - self._draw_animated_text(self.text_speed, self.text_speed_2, x, y, is_current_mod) + text_x = 330 - (self.text_speed.texture.width//2) + text_y = 819 + move + (i*50) + self._draw_animated_text(self.text_speed, self.text_speed_2, text_x + x, text_y, is_current_mod) if current_value >= 4.0: - tex.draw_texture('modifier', 'mod_yonbai', y=move + (i*50)) + tex.draw_texture('modifier', 'mod_yonbai', x=x, y=move + (i*50)) elif current_value >= 3.0: - tex.draw_texture('modifier', 'mod_sanbai', y=move + (i*50)) + tex.draw_texture('modifier', 'mod_sanbai', x=x, y=move + (i*50)) elif current_value > 1.0: - tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50)) + tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], x=x, y=move + (i*50)) elif current_mod.name == 'random': if current_value == 1: - x = 330 - (self.text_kimagure.texture.width//2) - y = 819 + move + (i*50) - self._draw_animated_text(self.text_kimagure, self.text_kimagure_2, x, y, is_current_mod) - tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50)) + text_x = 330 - (self.text_kimagure.texture.width//2) + text_y = 819 + move + (i*50) + self._draw_animated_text(self.text_kimagure, self.text_kimagure_2, text_x + x, text_y, is_current_mod) + tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], x=x, y=move + (i*50)) elif current_value == 2: - x = 330 - (self.text_detarame.texture.width//2) - y = 819 + move + (i*50) - self._draw_animated_text(self.text_detarame, self.text_detarame_2, x, y, is_current_mod) - tex.draw_texture('modifier', 'mod_detarame', y=move + (i*50)) + text_x = 330 - (self.text_detarame.texture.width//2) + text_y = 819 + move + (i*50) + self._draw_animated_text(self.text_detarame, self.text_detarame_2, text_x + x, text_y, is_current_mod) + tex.draw_texture('modifier', 'mod_detarame', x=x, y=move + (i*50)) else: - x = 330 - (self.text_false.texture.width//2) - y = 819 + move + (i*50) - self._draw_animated_text(self.text_false, self.text_false_2, x, y, is_current_mod) + text_x = 330 - (self.text_false.texture.width//2) + text_y = 819 + move + (i*50) + self._draw_animated_text(self.text_false, self.text_false_2, text_x + x, text_y, is_current_mod) if i == self.current_mod_index: - tex.draw_texture('modifier', 'blue_arrow', y=move + (i*50), x=-self.blue_arrow_move.attribute, fade=self.blue_arrow_fade.attribute) - tex.draw_texture('modifier', 'blue_arrow', y=move + (i*50), x=110 + self.blue_arrow_move.attribute, mirror='horizontal', fade=self.blue_arrow_fade.attribute) + tex.draw_texture('modifier', 'blue_arrow', y=move + (i*50), x=x-self.blue_arrow_move.attribute, fade=self.blue_arrow_fade.attribute) + tex.draw_texture('modifier', 'blue_arrow', y=move + (i*50), x=x+110 + self.blue_arrow_move.attribute, mirror='horizontal', fade=self.blue_arrow_fade.attribute) class ScoreHistory: def __init__(self, scores: dict[int, tuple[int, int, int, int]], current_ms):