minor fixes

This commit is contained in:
Anthony Samms
2025-11-02 18:29:46 -05:00
parent a1bc58b5ea
commit f93accd4a1
16 changed files with 60 additions and 55 deletions

View File

@@ -21,7 +21,7 @@ from libs.utils import (
from scenes.devtest import DevScreen from scenes.devtest import DevScreen
from scenes.entry import EntryScreen from scenes.entry import EntryScreen
from scenes.game import GameScreen from scenes.game import GameScreen
from scenes.game_dan import DanGameScreen from scenes.dan.game_dan import DanGameScreen
from scenes.two_player.game import TwoPlayerGameScreen from scenes.two_player.game import TwoPlayerGameScreen
from scenes.two_player.result import TwoPlayerResultScreen from scenes.two_player.result import TwoPlayerResultScreen
from scenes.loading import LoadScreen from scenes.loading import LoadScreen
@@ -30,7 +30,7 @@ from scenes.settings import SettingsScreen
from scenes.song_select import SongSelectScreen from scenes.song_select import SongSelectScreen
from scenes.title import TitleScreen from scenes.title import TitleScreen
from scenes.two_player.song_select import TwoPlayerSongSelectScreen from scenes.two_player.song_select import TwoPlayerSongSelectScreen
from scenes.dan_select import DanSelectScreen from scenes.dan.dan_select import DanSelectScreen
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -3,6 +3,7 @@ import platform
import logging import logging
from pathlib import Path from pathlib import Path
from libs.global_data import VolumeConfig
from libs.utils import get_config from libs.utils import get_config
ffi = cffi.FFI() ffi = cffi.FFI()
@@ -118,7 +119,7 @@ except OSError as e:
class AudioEngine: class AudioEngine:
"""Initialize an audio engine for playing sounds and music.""" """Initialize an audio engine for playing sounds and music."""
def __init__(self, device_type: int, sample_rate: float, buffer_size: int, volume_presets: dict[str, float]): def __init__(self, device_type: int, sample_rate: float, buffer_size: int, volume_presets: VolumeConfig):
self.device_type = device_type self.device_type = device_type
if sample_rate < 0: if sample_rate < 0:
self.target_sample_rate = 44100 self.target_sample_rate = 44100
@@ -142,7 +143,10 @@ class AudioEngine:
def get_host_api_name(self, api_id: int) -> str: def get_host_api_name(self, api_id: int) -> str:
"""Returns the name of the host API with the given ID""" """Returns the name of the host API with the given ID"""
result = lib.get_host_api_name(api_id) # type: ignore result = lib.get_host_api_name(api_id) # type: ignore
return ffi.string(result).decode('utf-8') result = ffi.string(result)
if isinstance(result, bytes):
result = result.decode('utf-8')
return result
def init_audio_device(self) -> bool: def init_audio_device(self) -> bool:
"""Initialize the audio device""" """Initialize the audio device"""

View File

@@ -75,10 +75,6 @@ class DonBG(DonBGBase):
self.move = Animation.create_move(10000, total_distance=-1280) self.move = Animation.create_move(10000, total_distance=-1280)
self.move.start() self.move.start()
self.move.loop = True self.move.loop = True
def draw(self, tex: TextureWrapper): def _draw_textures(self, tex: TextureWrapper, fade: float, y: float):
self._draw_textures(tex, 1.0)
if self.is_clear:
self._draw_textures(tex, self.clear_fade.attribute)
def _draw_textures(self, tex: TextureWrapper, fade: float):
for i in range(2): for i in range(2):
tex.draw_texture(self.name, 'background', frame=self.is_clear, fade=fade, x=(i*1280)+self.move.attribute) tex.draw_texture(self.name, 'background', frame=self.is_clear, fade=fade, x=(i*1280)+self.move.attribute)

View File

@@ -37,7 +37,5 @@ class DancerGroup(BaseDancerGroup):
class BGFever(BGFeverBase): class BGFever(BGFeverBase):
def start(self): def start(self):
self.transitioned = True self.transitioned = True
def update(self, current_time_ms: float):
pass
def draw(self, tex: TextureWrapper): def draw(self, tex: TextureWrapper):
tex.draw_texture(self.name, 'background') tex.draw_texture(self.name, 'background')

View File

@@ -36,8 +36,6 @@ class DancerGroup(BaseDancerGroup):
class BGFever(BGFeverBase): class BGFever(BGFeverBase):
def start(self): def start(self):
self.transitioned = True self.transitioned = True
def update(self, current_time_ms: float):
pass
def draw(self, tex: TextureWrapper): def draw(self, tex: TextureWrapper):
tex.draw_texture(self.name, 'background') tex.draw_texture(self.name, 'background')
tex.draw_texture(self.name, 'overlay') tex.draw_texture(self.name, 'overlay')

View File

@@ -19,8 +19,8 @@ class Background:
self.chibi = ChibiController(self.tex_wrapper, 2, bpm, path) self.chibi = ChibiController(self.tex_wrapper, 2, bpm, path)
class DonBG(DonBG6): class DonBG(DonBG6):
def __init__(self, tex: TextureWrapper, player_num: int, bpm: float, path: str): def __init__(self, tex: TextureWrapper, index: int, player_num: int, path: str):
super().__init__(tex, player_num, bpm, path) super().__init__(tex, index, player_num, path)
self.overlay_move_2 = Animation.create_move(8000, total_distance=-760) self.overlay_move_2 = Animation.create_move(8000, total_distance=-760)
self.overlay_move_2.loop = True self.overlay_move_2.loop = True
self.overlay_move_2.start() self.overlay_move_2.start()

View File

@@ -404,7 +404,7 @@ class YellowBox:
if self.tja.metadata.course_data[diff].is_branching and (get_current_ms() // 1000) % 2 == 0: if self.tja.metadata.course_data[diff].is_branching and (get_current_ms() // 1000) % 2 == 0:
tex.draw_texture('yellow_box', 'branch_indicator', x=(diff*60), color=color) tex.draw_texture('yellow_box', 'branch_indicator', x=(diff*60), color=color)
def _draw_tja_data_diff(self, is_ura: bool, song_box): def _draw_tja_data_diff(self, is_ura: bool, song_box: Optional[SongBox] = None):
if self.tja is None: if self.tja is None:
return return
tex.draw_texture('diff_select', 'back', fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'back', fade=self.fade_in.attribute)
@@ -412,6 +412,8 @@ class YellowBox:
tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute)
for diff in self.tja.metadata.course_data: for diff in self.tja.metadata.course_data:
if song_box is None:
continue
if diff >= 4: if diff >= 4:
continue continue
elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] == 2 and song_box.scores[diff][2] == 0) or (song_box.scores[diff][2] == 0 and song_box.scores[diff][3] == 0)): elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] == 2 and song_box.scores[diff][2] == 0) or (song_box.scores[diff][2] == 0 and song_box.scores[diff][3] == 0)):
@@ -472,7 +474,7 @@ class YellowBox:
tex.draw_texture('yellow_box', 'yellow_box_top', x=self.left_x + self.edge_height, y=self.top_y, x2=self.center_width) tex.draw_texture('yellow_box', 'yellow_box_top', x=self.left_x + self.edge_height, y=self.top_y, x2=self.center_width)
tex.draw_texture('yellow_box', 'yellow_box_center', x=self.left_x + self.edge_height, y=self.top_y + self.edge_height, x2=self.center_width, y2=self.center_height) tex.draw_texture('yellow_box', 'yellow_box_center', x=self.left_x + self.edge_height, y=self.top_y + self.edge_height, x2=self.center_width, y2=self.center_height)
def draw(self, song_box: SongBox, fade_override: Optional[float], is_ura: bool): def draw(self, song_box: Optional[SongBox], fade_override: Optional[float], is_ura: bool):
self._draw_yellow_box() self._draw_yellow_box()
if self.is_dan: if self.is_dan:
return return
@@ -604,7 +606,7 @@ class DanBox:
def _draw_open(self, x: int, y: int, is_ura: bool): def _draw_open(self, x: int, y: int, is_ura: bool):
if self.yellow_box is not None: if self.yellow_box is not None:
self.yellow_box.draw(x, y, False) self.yellow_box.draw(None, None, False)
for i, song in enumerate(self.song_text): for i, song in enumerate(self.song_text):
title, subtitle = song title, subtitle = song
x = i * 140 x = i * 140
@@ -895,8 +897,8 @@ class DanCourse(FileSystemItem):
self.charts = [] self.charts = []
for chart in data["charts"]: for chart in data["charts"]:
hash = chart["hash"] hash = chart["hash"]
chart_title = chart["title"] #chart_title = chart["title"]
chart_subtitle = chart["subtitle"] #chart_subtitle = chart["subtitle"]
difficulty = chart["difficulty"] difficulty = chart["difficulty"]
if hash in global_data.song_hashes: if hash in global_data.song_hashes:
path = Path(global_data.song_hashes[hash][0]["file_path"]) path = Path(global_data.song_hashes[hash][0]["file_path"])
@@ -997,10 +999,11 @@ class FileNavigator:
song_list = self._read_song_list(self.favorite_folder.path) song_list = self._read_song_list(self.favorite_folder.path)
for song_obj in song_list: for song_obj in song_list:
if str(song_obj) in self.all_song_files: if str(song_obj) in self.all_song_files:
if isinstance(self.all_song_files[str(song_obj)].box, DanBox): box = self.all_song_files[str(song_obj)].box
if isinstance(box, DanBox):
logger.warning(f"Cannot favorite DanCourse: {song_obj}") logger.warning(f"Cannot favorite DanCourse: {song_obj}")
else: else:
self.all_song_files[str(song_obj)].box.is_favorite = True box.is_favorite = True
logging.info(f"Object generation complete. " logging.info(f"Object generation complete. "
f"Directories: {len(self.all_directories)}, " f"Directories: {len(self.all_directories)}, "

View File

@@ -120,7 +120,7 @@ class SessionData:
result_bad: int = 0 result_bad: int = 0
result_max_combo: int = 0 result_max_combo: int = 0
result_total_drumroll: int = 0 result_total_drumroll: int = 0
result_gauge_length: int = 0 result_gauge_length: float = 0
prev_score: int = 0 prev_score: int = 0
@dataclass @dataclass
@@ -142,7 +142,7 @@ class GlobalData:
session_data (list[SessionData]): Session data for both players. session_data (list[SessionData]): Session data for both players.
""" """
songs_played: int = 0 songs_played: int = 0
config: Config = field(default_factory=lambda: dict()) config: dict = field(default_factory=dict)
song_hashes: dict[str, list[dict]] = field(default_factory=lambda: dict()) #Hash to path song_hashes: dict[str, list[dict]] = field(default_factory=lambda: dict()) #Hash to path
song_paths: dict[Path, str] = field(default_factory=lambda: dict()) #path to hash song_paths: dict[Path, str] = field(default_factory=lambda: dict()) #path to hash
song_progress: float = 0.0 song_progress: float = 0.0

View File

@@ -51,14 +51,17 @@ class Transition:
offset = 816 - self.rainbow_up.attribute offset = 816 - self.rainbow_up.attribute
global_tex.draw_texture('rainbow_transition', 'text_bg', y=-self.rainbow_up.attribute - offset, color=color_2) global_tex.draw_texture('rainbow_transition', 'text_bg', y=-self.rainbow_up.attribute - offset, color=color_2)
texture = self.title.texture if isinstance(self.title, OutlinedText):
x = 1280//2 - texture.width//2 texture = self.title.texture
y = 1176 - texture.height//2 - int(self.rainbow_up.attribute) - offset - 20 x = 1280//2 - texture.width//2
self.title.draw(outline_color=ray.BLACK, x=x, y=y, color=color_1) y = 1176 - texture.height//2 - int(self.rainbow_up.attribute) - offset - 20
self.title.draw(outline_color=ray.BLACK, x=x, y=y, color=color_1)
texture = self.subtitle.texture if isinstance(self.subtitle, OutlinedText):
x = 1280//2 - texture.width//2 texture = self.subtitle.texture
self.subtitle.draw(outline_color=ray.BLACK, x=x, y=y + 50, color=color_1) x = 1280//2 - texture.width//2
y = 1176 - texture.height//2 - int(self.rainbow_up.attribute) - offset - 20
self.subtitle.draw(outline_color=ray.BLACK, x=x, y=y + 50, color=color_1)
def draw(self): def draw(self):
"""Draw the transition effect.""" """Draw the transition effect."""

View File

@@ -54,9 +54,10 @@ class VideoPlayer:
image = ray.Image(frame_data, self.video.w, self.video.h, 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8) image = ray.Image(frame_data, self.video.w, self.video.h, 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
self.texture = ray.load_texture_from_image(image) self.texture = ray.load_texture_from_image(image)
else: else:
frame_bytes = frame_data.tobytes() if frame_data is not None:
pixels_ptr = ray.ffi.cast('void *', ray.ffi.from_buffer('unsigned char[]', frame_bytes)) frame_bytes = frame_data.tobytes()
ray.update_texture(self.texture, pixels_ptr) pixels_ptr = ray.ffi.cast('void *', ray.ffi.from_buffer('unsigned char[]', frame_bytes))
ray.update_texture(self.texture, pixels_ptr)
self.current_frame_data = frame_data self.current_frame_data = frame_data
return True return True

View File

@@ -183,16 +183,13 @@ class DanSelectPlayer:
def handle_input(self, state, screen): def handle_input(self, state, screen):
"""Main input dispatcher. Delegates to state-specific handlers.""" """Main input dispatcher. Delegates to state-specific handlers."""
if self.is_voice_playing():
return
if state == State.BROWSING: if state == State.BROWSING:
screen.handle_input_browsing() screen.handle_input_browsing()
elif state == State.SONG_SELECTED: elif state == State.SONG_SELECTED:
res = screen.handle_input_selected() res = screen.handle_input_selected()
if res:
if res: return res
return res
def handle_input_selected(self): def handle_input_selected(self):
"""Handle input for selecting difficulty. Returns 'cancel', 'confirm', or None""" """Handle input for selecting difficulty. Returns 'cancel', 'confirm', or None"""

View File

@@ -12,7 +12,7 @@ from libs.tja import TJAParser
from libs.transition import Transition from libs.transition import Transition
from libs.utils import OutlinedText, get_current_ms from libs.utils import OutlinedText, get_current_ms
from libs.texture import tex from libs.texture import tex
from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, ResultTransition, SongInfo from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, Gauge, ResultTransition, SongInfo
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -91,7 +91,8 @@ class DanGameScreen(GameScreen):
session_data.selected_difficulty = difficulty session_data.selected_difficulty = difficulty
self.player_1.difficulty = difficulty self.player_1.difficulty = difficulty
self.tja = TJAParser(song.file_path, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X) self.tja = TJAParser(song.file_path, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
audio.unload_music_stream(self.song_music) if self.song_music is not None:
audio.unload_music_stream(self.song_music)
self.song_music = None self.song_music = None
self.song_started = False self.song_started = False
@@ -326,7 +327,7 @@ class DanTransition:
tex.draw_texture('dan', 'transition', index=1, x=-self.move.attribute) tex.draw_texture('dan', 'transition', index=1, x=-self.move.attribute)
class DanGauge: class DanGauge(Gauge):
"""The player's gauge""" """The player's gauge"""
def __init__(self, player_num: str, total_notes: int): def __init__(self, player_num: str, total_notes: int):
self.player_num = player_num self.player_num = player_num

View File

@@ -122,12 +122,12 @@ class ResultPlayer:
plate_info = global_data.config[f'nameplate_{self.player_num}p'] plate_info = global_data.config[f'nameplate_{self.player_num}p']
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], int(self.player_num), plate_info['dan'], plate_info['gold'], plate_info['title_bg']) self.nameplate = Nameplate(plate_info['name'], plate_info['title'], int(self.player_num), plate_info['dan'], plate_info['gold'], plate_info['title_bg'])
self.score, self.good, self.ok, self.bad, self.max_combo, self.total_drumroll = '', '', '', '', '', '' self.score, self.good, self.ok, self.bad, self.max_combo, self.total_drumroll = '', '', '', '', '', ''
self.update_list: list[tuple[str, int]] = [['score', session_data.result_score], self.update_list: list[tuple[str, int]] = [('score', session_data.result_score),
['good', session_data.result_good], ('good', session_data.result_good),
['ok', session_data.result_ok], ('ok', session_data.result_ok),
['bad', session_data.result_bad], ('bad', session_data.result_bad),
['max_combo', session_data.result_max_combo], ('max_combo', session_data.result_max_combo),
['total_drumroll', session_data.result_total_drumroll]] ('total_drumroll', session_data.result_total_drumroll)]
self.update_index = 0 self.update_index = 0
if session_data.result_ok == 0 and session_data.result_bad == 0: if session_data.result_ok == 0 and session_data.result_bad == 0:
self.crown_type = 'crown_dfc' self.crown_type = 'crown_dfc'

View File

@@ -252,7 +252,7 @@ class SettingsScreen(Screen):
display_value = ', '.join(map(str, value)) display_value = ', '.join(map(str, value))
else: else:
display_value = str(value) display_value = str(value)
if key == 'device_type': if key == 'device_type' and not isinstance(value, list):
display_value = f'{display_value} ({audio.get_host_api_name(value)})' display_value = f'{display_value} ({audio.get_host_api_name(value)})'
ray.draw_text(f'{key}: {display_value}', 250, i*25 + 70, 20, color) ray.draw_text(f'{key}: {display_value}', 250, i*25 + 70, 20, color)

View File

@@ -5,7 +5,7 @@ from pathlib import Path
import pyray as ray import pyray as ray
import logging import logging
from libs.file_navigator import navigator from libs.file_navigator import DanCourse, navigator
from libs.audio import audio from libs.audio import audio
from libs.chara_2d import Chara2D from libs.chara_2d import Chara2D
from libs.file_navigator import Directory, SongBox, SongFile from libs.file_navigator import Directory, SongBox, SongFile
@@ -74,7 +74,9 @@ class SongSelectScreen(Screen):
return self.on_screen_end("ENTRY") return self.on_screen_end("ENTRY")
if str(session_data.selected_song) in self.navigator.all_song_files: if str(session_data.selected_song) in self.navigator.all_song_files:
self.navigator.mark_crowns_dirty_for_song(self.navigator.all_song_files[str(session_data.selected_song)]) selected_song = self.navigator.all_song_files[str(session_data.selected_song)]
if not isinstance(selected_song, DanCourse):
self.navigator.mark_crowns_dirty_for_song(selected_song)
curr_item = self.navigator.get_current_item() curr_item = self.navigator.get_current_item()
curr_item.box.get_scores() curr_item.box.get_scores()
@@ -214,7 +216,7 @@ class SongSelectScreen(Screen):
def handle_input(self): def handle_input(self):
self.player_1.handle_input(self.state, self) self.player_1.handle_input(self.state, self)
def update_players(self, current_time): def update_players(self, current_time) -> str:
self.player_1.update(current_time) self.player_1.update(current_time)
if self.text_fade_out.is_finished: if self.text_fade_out.is_finished:
self.player_1.selected_song = True self.player_1.selected_song = True
@@ -376,6 +378,7 @@ class SongSelectPlayer:
self.selected_difficulty = -3 self.selected_difficulty = -3
self.prev_diff = -3 self.prev_diff = -3
self.selected_song = False self.selected_song = False
self.is_ready = False
self.is_ura = False self.is_ura = False
self.ura_toggle = 0 self.ura_toggle = 0
self.diff_select_move_right = False self.diff_select_move_right = False
@@ -492,7 +495,7 @@ class SongSelectPlayer:
def handle_input(self, state, screen): def handle_input(self, state, screen):
"""Main input dispatcher. Delegates to state-specific handlers.""" """Main input dispatcher. Delegates to state-specific handlers."""
if self.is_voice_playing(): if self.is_voice_playing() or self.is_ready:
return return
if state == State.BROWSING: if state == State.BROWSING:
@@ -538,6 +541,7 @@ class SongSelectPlayer:
self.neiro_selector = NeiroSelector(self.player_num) self.neiro_selector = NeiroSelector(self.player_num)
return None return None
else: else:
self.is_ready = True
return "confirm" return "confirm"
if is_l_kat_pressed(self.player_num) or is_r_kat_pressed(self.player_num): if is_l_kat_pressed(self.player_num) or is_r_kat_pressed(self.player_num):

View File

@@ -128,7 +128,7 @@ class TwoPlayerSongSelectScreen(SongSelectScreen):
super()._cancel_selection() super()._cancel_selection()
self.player_2.selected_song = False self.player_2.selected_song = False
def _confirm_selection(self, player_selected: int): def _confirm_selection(self, player_selected: int = 1):
"""Confirm song selection and create game transition""" """Confirm song selection and create game transition"""
audio.play_sound('don', 'sound') audio.play_sound('don', 'sound')
audio.play_sound(f'voice_start_song_{global_data.player_num}p', 'voice') audio.play_sound(f'voice_start_song_{global_data.player_num}p', 'voice')
@@ -160,7 +160,7 @@ class TwoPlayerSongSelectScreen(SongSelectScreen):
self.game_transition.start() self.game_transition.start()
logger.info(f"Game transition started for song: {title} - {subtitle}") logger.info(f"Game transition started for song: {title} - {subtitle}")
def update_players(self, current_time): def update_players(self, current_time) -> str:
self.player_1.update(current_time) self.player_1.update(current_time)
self.player_2.update(current_time) self.player_2.update(current_time)
if self.text_fade_out.is_finished: if self.text_fade_out.is_finished: