diff --git a/libs/chara_2d.py b/libs/chara_2d.py index 9201452..7998dab 100644 --- a/libs/chara_2d.py +++ b/libs/chara_2d.py @@ -5,7 +5,7 @@ from libs.utils import global_tex logger = logging.getLogger(__name__) class Chara2D: - def __init__(self, index: int, bpm: float, path: str = 'chara'): + def __init__(self, index: int, bpm: float = 100, path: str = 'chara'): """ Initialize a Chara2D object. @@ -67,7 +67,7 @@ class Chara2D: self.current_anim = name self.anims[name].start() logger.debug(f"Animation set: {name}") - def update(self, current_time_ms: float, bpm: float, is_clear: bool, is_rainbow: bool): + def update(self, current_time_ms: float, bpm: float = 100, is_clear: bool = False, is_rainbow: bool = False): """ Update the character's animation state and appearance. diff --git a/libs/global_objects.py b/libs/global_objects.py index 93f0ca9..874be87 100644 --- a/libs/global_objects.py +++ b/libs/global_objects.py @@ -45,12 +45,12 @@ class Nameplate: """Unload the Nameplate object.""" self.name.unload() self.title.unload() - def draw(self, x: int, y: int, fade: float = 1.0): + def draw(self, x: float, y: float, fade: float = 1.0): """Draw the Nameplate object. Args: - x (int): The x-coordinate of the Nameplate object. - y (int): The y-coordinate of the Nameplate object. + x (float): The x-coordinate of the Nameplate object. + y (float): The y-coordinate of the Nameplate object. fade (float): The fade value of the Nameplate object. """ tex = global_tex @@ -103,7 +103,7 @@ class Indicator: self.blue_arrow_move.update(current_time_ms) self.blue_arrow_fade.update(current_time_ms) - def draw(self, x: int, y: int, fade=1.0): + def draw(self, x: float, y: float, fade=1.0): """Draw the indicator at the given position with the given fade.""" tex = global_tex tex.draw_texture('indicator', 'background', x=x, y=y, fade=fade) @@ -156,7 +156,7 @@ class EntryOverlay: def update(self, current_time_ms: float): """Update the Banapass and Camera status icons.""" pass - def draw(self, x: int = 0, y: int = 0): + def draw(self, x: float = 0, y: float = 0): """Draw the Banapass and Camera status icons.""" tex = global_tex tex.draw_texture('overlay', 'banapass_or', x=x, y=y, frame=self.online) diff --git a/libs/texture.py b/libs/texture.py index 971a995..14ca9a1 100644 --- a/libs/texture.py +++ b/libs/texture.py @@ -16,6 +16,11 @@ SCREEN_HEIGHT = 720 logger = logging.getLogger(__name__) +class Coordinates: + def __init__(self, x: float, y: float): + self.x = x + self.y = y + class Texture: """Texture class for managing textures and animations.""" def __init__(self, name: str, texture: Union[ray.Texture, list[ray.Texture]], init_vals: dict[str, int]): @@ -41,7 +46,13 @@ class TextureWrapper: def __init__(self): self.textures: dict[str, dict[str, Texture]] = dict() self.animations: dict[int, BaseAnimation] = dict() + self.skin_config: dict[str, Coordinates] = dict() self.graphics_path = Path("Graphics") + if (self.graphics_path / "skin_config.json").exists(): + data = json.loads((self.graphics_path / "skin_config.json").read_text()) + self.skin_config: dict[str, Coordinates] = { + k: Coordinates(v['x'], v['y']) for k, v in data.items() + } def unload_textures(self): """Unload all textures and animations.""" diff --git a/scenes/dan/game_dan.py b/scenes/dan/game_dan.py index 82bd1e2..2ca3d31 100644 --- a/scenes/dan/game_dan.py +++ b/scenes/dan/game_dan.py @@ -11,14 +11,11 @@ from libs.global_objects import AllNetIcon from libs.tja import TJAParser from libs.transition import Transition from libs.utils import OutlinedText, get_current_ms -from libs.texture import tex +from libs.texture import SCREEN_WIDTH, tex from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, Gauge, ResultTransition, SongInfo logger = logging.getLogger(__name__) -SCREEN_WIDTH = 1280 -SCREEN_HEIGHT = 720 - class DanGameScreen(GameScreen): JUDGE_X = 414 diff --git a/scenes/entry.py b/scenes/entry.py index 742dfed..00e831a 100644 --- a/scenes/entry.py +++ b/scenes/entry.py @@ -6,7 +6,7 @@ from libs.audio import audio from libs.chara_2d import Chara2D from libs.global_data import PlayerNum from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, EntryOverlay, Timer -from libs.texture import tex +from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex from libs.screen import Screen from libs.utils import ( OutlinedText, @@ -45,7 +45,7 @@ class EntryScreen(Screen): self.side_select_fade = tex.get_animation(0) self.bg_flicker = tex.get_animation(1) self.side_select_fade.start() - self.chara = Chara2D(0, 100) + self.chara = Chara2D(0) self.announce_played = False self.players: list[Optional[EntryPlayer]] = [None, None] audio.play_sound('bgm', 'music') @@ -158,7 +158,7 @@ class EntryScreen(Screen): tex.draw_texture('side_select', 'question', fade=fade) - self.chara.draw(480, 240) + self.chara.draw(tex.skin_config["chara_entry"].x, tex.skin_config["chara_entry"].y) tex.draw_texture('side_select', '1P', fade=fade) tex.draw_texture('side_select', 'cancel', fade=fade) @@ -173,7 +173,7 @@ class EntryScreen(Screen): tex.draw_texture('side_select', '2P_highlight', fade=fade) tex.draw_texture('side_select', '1P2P_outline', index=1, fade=fade) tex.draw_texture('side_select', 'cancel_text', fade=fade) - self.nameplate.draw(500, 185) + self.nameplate.draw(tex.skin_config["nameplate_entry"].x, tex.skin_config["nameplate_entry"].y) def draw_player_drum(self): for player in self.players: @@ -212,10 +212,10 @@ class EntryScreen(Screen): tex.draw_texture('global', 'player_entry') if self.box_manager.is_finished(): - ray.draw_rectangle(0, 0, 1280, 720, ray.BLACK) + ray.draw_rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ray.BLACK) self.timer.draw() - self.entry_overlay.draw(y=-10) + self.entry_overlay.draw(y=tex.skin_config['entry_overlay_entry'].y) self.coin_overlay.draw() self.allnet_indicator.draw() @@ -248,7 +248,7 @@ class EntryPlayer: # Character (0 for red/1P, 1 for blue/2P) chara_id = 0 if side == 0 else 1 - self.chara = Chara2D(chara_id, 100) + self.chara = Chara2D(chara_id) # Animations self.drum_move_1 = tex.get_animation(2) @@ -283,7 +283,7 @@ class EntryPlayer: self.nameplate_fadein.update(current_time) self.nameplate.update(current_time) self.indicator.update(current_time) - self.chara.update(current_time, 100, False, False) + self.chara.update(current_time) def draw_drum(self): """Draw the player's drum with animations""" @@ -323,11 +323,11 @@ class EntryPlayer: def draw_nameplate_and_indicator(self, fade: float = 1.0): """Draw nameplate and indicator at player-specific position""" if self.side == 0: # Left side - self.nameplate.draw(30, 640, fade=fade) - self.indicator.draw(50, 575, fade=fade) + self.nameplate.draw(tex.skin_config['nameplate_entry_left'].x, tex.skin_config['nameplate_entry_left'].y, fade=fade) + self.indicator.draw(tex.skin_config['indicator_entry_left'].x, tex.skin_config['indicator_entry_left'].y, fade=fade) else: # Right side - self.nameplate.draw(950, 640, fade=fade) - self.indicator.draw(770, 575, fade=fade) + self.nameplate.draw(tex.skin_config['nameplate_entry_right'].x, tex.skin_config['nameplate_entry_right'].y, fade=fade) + self.indicator.draw(tex.skin_config['indicator_entry_right'].x, tex.skin_config['indicator_entry_right'].y, fade=fade) def is_cloud_animation_finished(self) -> bool: """Check if cloud texture change animation is finished""" @@ -368,6 +368,7 @@ class Box: self.is_selected = False self.moving_left = False self.moving_right = False + self.outline_color = ray.Color(109, 68, 24, 255) def set_positions(self, x: int): """Set the positions of the box""" @@ -425,7 +426,7 @@ class Box: if self.is_selected: self.text.draw(outline_color=ray.BLACK, x=text_x, y=text_y, color=color) else: - self.text.draw(outline_color=ray.Color(109, 68, 24, 255), x=text_x, y=text_y, color=color) + self.text.draw(outline_color=self.outline_color, x=text_x, y=text_y, color=color) def draw(self, fade: float): color = ray.fade(ray.WHITE, fade) @@ -451,7 +452,7 @@ class BoxManager: spacing = 80 box_width = self.boxes[0].texture.width total_width = self.num_boxes * box_width + (self.num_boxes - 1) * spacing - start_x = 640 - total_width//2 + start_x = SCREEN_WIDTH//2 - total_width//2 for i, box in enumerate(self.boxes): box.set_positions(start_x + i * (box_width + spacing)) if i > 0: diff --git a/scenes/game.py b/scenes/game.py index 9d3c625..a1dffda 100644 --- a/scenes/game.py +++ b/scenes/game.py @@ -15,7 +15,7 @@ from libs.chara_2d import Chara2D from libs.global_data import Crown, Difficulty, Modifiers, PlayerNum from libs.global_objects import AllNetIcon, Nameplate from libs.screen import Screen -from libs.texture import tex +from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex from libs.tja import ( Balloon, Drumroll, @@ -41,9 +41,6 @@ from libs.utils import ( ) from libs.video import VideoPlayer -SCREEN_WIDTH = 1280 -SCREEN_HEIGHT = 720 - logger = logging.getLogger(__name__) class GameScreen(Screen): diff --git a/scenes/practice/game.py b/scenes/practice/game.py index ba6adf7..b785899 100644 --- a/scenes/practice/game.py +++ b/scenes/practice/game.py @@ -336,9 +336,9 @@ class PracticePlayer(Player): # Group 2: Judgement and hit effects if self.gogo_time is not None: - self.gogo_time.draw() + self.gogo_time.draw(self.judge_x, self.judge_y) for anim in self.draw_judge_list: - anim.draw() + anim.draw(self.judge_x, self.judge_y) # Group 3: Notes and bars (game content) if not self.paused: diff --git a/scenes/song_select.py b/scenes/song_select.py index b4c1cae..a33e21b 100644 --- a/scenes/song_select.py +++ b/scenes/song_select.py @@ -12,7 +12,7 @@ from libs.file_navigator import Directory, SongBox, SongFile from libs.global_data import Difficulty, Modifiers, PlayerNum from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, Timer from libs.screen import Screen -from libs.texture import tex +from libs.texture import SCREEN_WIDTH, tex from libs.transition import Transition from libs.utils import ( OutlinedText, @@ -329,7 +329,7 @@ class SongSelectScreen(Screen): for item in self.navigator.items: box = item.box - if -156 <= box.position <= 1280 + 144: + if -156 <= box.position <= SCREEN_WIDTH + 144: if box.position <= 500: box.draw(box.position - int(self.move_away.attribute), 95, self.player_1.is_ura, fade_override=self.diff_fade_out.attribute) else: diff --git a/scenes/title.py b/scenes/title.py index a7d5ec8..1f366b4 100644 --- a/scenes/title.py +++ b/scenes/title.py @@ -119,7 +119,7 @@ class TitleScreen(Screen): tex.draw_texture('movie', 'background', fade=self.fade_out.attribute) self.coin_overlay.draw() self.allnet_indicator.draw() - self.entry_overlay.draw(x=155, y=-10) + self.entry_overlay.draw(tex.skin_config["entry_overlay_title"].x, y=tex.skin_config["entry_overlay_title"].y) global_tex.draw_texture('overlay', 'hit_taiko_to_start', index=0, fade=self.text_overlay_fade.attribute) global_tex.draw_texture('overlay', 'hit_taiko_to_start', index=1, fade=self.text_overlay_fade.attribute) @@ -252,6 +252,7 @@ class WarningScreen: self.fade_in.update(current_ms) self.fade_out.update(current_ms) delay = 566.67 + fade_out_delay = 500 elapsed_time = current_ms - self.start_ms self.warning_x.update(current_ms) self.characters.update(current_ms) @@ -259,7 +260,7 @@ class WarningScreen: if self.characters.is_finished: self.warning_bachi_hit.update(current_ms) else: - self.fade_out.delay = elapsed_time + 500 + self.fade_out.delay = elapsed_time + fade_out_delay if delay <= elapsed_time and not audio.is_sound_playing('bachi_swipe'): audio.play_sound('warning_voiceover', 'attract_mode') audio.play_sound('bachi_swipe', 'attract_mode')