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.entry import EntryScreen
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.result import TwoPlayerResultScreen
from scenes.loading import LoadScreen
@@ -30,7 +30,7 @@ from scenes.settings import SettingsScreen
from scenes.song_select import SongSelectScreen
from scenes.title import TitleScreen
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__)

View File

@@ -3,6 +3,7 @@ import platform
import logging
from pathlib import Path
from libs.global_data import VolumeConfig
from libs.utils import get_config
ffi = cffi.FFI()
@@ -118,7 +119,7 @@ except OSError as e:
class AudioEngine:
"""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
if sample_rate < 0:
self.target_sample_rate = 44100
@@ -142,7 +143,10 @@ class AudioEngine:
def get_host_api_name(self, api_id: int) -> str:
"""Returns the name of the host API with the given ID"""
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:
"""Initialize the audio device"""

View File

@@ -75,10 +75,6 @@ class DonBG(DonBGBase):
self.move = Animation.create_move(10000, total_distance=-1280)
self.move.start()
self.move.loop = True
def draw(self, tex: TextureWrapper):
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):
def _draw_textures(self, tex: TextureWrapper, fade: float, y: float):
for i in range(2):
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):
def start(self):
self.transitioned = True
def update(self, current_time_ms: float):
pass
def draw(self, tex: TextureWrapper):
tex.draw_texture(self.name, 'background')

View File

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

View File

@@ -19,8 +19,8 @@ class Background:
self.chibi = ChibiController(self.tex_wrapper, 2, bpm, path)
class DonBG(DonBG6):
def __init__(self, tex: TextureWrapper, player_num: int, bpm: float, path: str):
super().__init__(tex, player_num, bpm, path)
def __init__(self, tex: TextureWrapper, index: int, player_num: int, path: str):
super().__init__(tex, index, player_num, path)
self.overlay_move_2 = Animation.create_move(8000, total_distance=-760)
self.overlay_move_2.loop = True
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:
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:
return
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)
for diff in self.tja.metadata.course_data:
if song_box is None:
continue
if diff >= 4:
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)):
@@ -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_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()
if self.is_dan:
return
@@ -604,7 +606,7 @@ class DanBox:
def _draw_open(self, x: int, y: int, is_ura: bool):
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):
title, subtitle = song
x = i * 140
@@ -895,8 +897,8 @@ class DanCourse(FileSystemItem):
self.charts = []
for chart in data["charts"]:
hash = chart["hash"]
chart_title = chart["title"]
chart_subtitle = chart["subtitle"]
#chart_title = chart["title"]
#chart_subtitle = chart["subtitle"]
difficulty = chart["difficulty"]
if hash in global_data.song_hashes:
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)
for song_obj in song_list:
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}")
else:
self.all_song_files[str(song_obj)].box.is_favorite = True
box.is_favorite = True
logging.info(f"Object generation complete. "
f"Directories: {len(self.all_directories)}, "

View File

@@ -120,7 +120,7 @@ class SessionData:
result_bad: int = 0
result_max_combo: int = 0
result_total_drumroll: int = 0
result_gauge_length: int = 0
result_gauge_length: float = 0
prev_score: int = 0
@dataclass
@@ -142,7 +142,7 @@ class GlobalData:
session_data (list[SessionData]): Session data for both players.
"""
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_paths: dict[Path, str] = field(default_factory=lambda: dict()) #path to hash
song_progress: float = 0.0

View File

@@ -51,13 +51,16 @@ class Transition:
offset = 816 - self.rainbow_up.attribute
global_tex.draw_texture('rainbow_transition', 'text_bg', y=-self.rainbow_up.attribute - offset, color=color_2)
if isinstance(self.title, OutlinedText):
texture = self.title.texture
x = 1280//2 - texture.width//2
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)
if isinstance(self.subtitle, OutlinedText):
texture = self.subtitle.texture
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):

View File

@@ -54,6 +54,7 @@ class VideoPlayer:
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)
else:
if frame_data is not None:
frame_bytes = frame_data.tobytes()
pixels_ptr = ray.ffi.cast('void *', ray.ffi.from_buffer('unsigned char[]', frame_bytes))
ray.update_texture(self.texture, pixels_ptr)

View File

@@ -183,14 +183,11 @@ class DanSelectPlayer:
def handle_input(self, state, screen):
"""Main input dispatcher. Delegates to state-specific handlers."""
if self.is_voice_playing():
return
if state == State.BROWSING:
screen.handle_input_browsing()
elif state == State.SONG_SELECTED:
res = screen.handle_input_selected()
if res:
return res

View File

@@ -12,7 +12,7 @@ from libs.tja import TJAParser
from libs.transition import Transition
from libs.utils import OutlinedText, get_current_ms
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__)
@@ -91,6 +91,7 @@ class DanGameScreen(GameScreen):
session_data.selected_difficulty = difficulty
self.player_1.difficulty = difficulty
self.tja = TJAParser(song.file_path, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
if self.song_music is not None:
audio.unload_music_stream(self.song_music)
self.song_music = None
self.song_started = False
@@ -326,7 +327,7 @@ class DanTransition:
tex.draw_texture('dan', 'transition', index=1, x=-self.move.attribute)
class DanGauge:
class DanGauge(Gauge):
"""The player's gauge"""
def __init__(self, player_num: str, total_notes: int):
self.player_num = player_num

View File

@@ -122,12 +122,12 @@ class ResultPlayer:
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.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],
['good', session_data.result_good],
['ok', session_data.result_ok],
['bad', session_data.result_bad],
['max_combo', session_data.result_max_combo],
['total_drumroll', session_data.result_total_drumroll]]
self.update_list: list[tuple[str, int]] = [('score', session_data.result_score),
('good', session_data.result_good),
('ok', session_data.result_ok),
('bad', session_data.result_bad),
('max_combo', session_data.result_max_combo),
('total_drumroll', session_data.result_total_drumroll)]
self.update_index = 0
if session_data.result_ok == 0 and session_data.result_bad == 0:
self.crown_type = 'crown_dfc'

View File

@@ -252,7 +252,7 @@ class SettingsScreen(Screen):
display_value = ', '.join(map(str, value))
else:
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)})'
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 logging
from libs.file_navigator import navigator
from libs.file_navigator import DanCourse, navigator
from libs.audio import audio
from libs.chara_2d import Chara2D
from libs.file_navigator import Directory, SongBox, SongFile
@@ -74,7 +74,9 @@ class SongSelectScreen(Screen):
return self.on_screen_end("ENTRY")
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.box.get_scores()
@@ -214,7 +216,7 @@ class SongSelectScreen(Screen):
def handle_input(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)
if self.text_fade_out.is_finished:
self.player_1.selected_song = True
@@ -376,6 +378,7 @@ class SongSelectPlayer:
self.selected_difficulty = -3
self.prev_diff = -3
self.selected_song = False
self.is_ready = False
self.is_ura = False
self.ura_toggle = 0
self.diff_select_move_right = False
@@ -492,7 +495,7 @@ class SongSelectPlayer:
def handle_input(self, state, screen):
"""Main input dispatcher. Delegates to state-specific handlers."""
if self.is_voice_playing():
if self.is_voice_playing() or self.is_ready:
return
if state == State.BROWSING:
@@ -538,6 +541,7 @@ class SongSelectPlayer:
self.neiro_selector = NeiroSelector(self.player_num)
return None
else:
self.is_ready = True
return "confirm"
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()
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"""
audio.play_sound('don', 'sound')
audio.play_sound(f'voice_start_song_{global_data.player_num}p', 'voice')
@@ -160,7 +160,7 @@ class TwoPlayerSongSelectScreen(SongSelectScreen):
self.game_transition.start()
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_2.update(current_time)
if self.text_fade_out.is_finished: