mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 11:40:13 +01:00
update to add every missing feature ever
This commit is contained in:
@@ -2,7 +2,7 @@ from pathlib import Path
|
||||
|
||||
import pyray as ray
|
||||
|
||||
from libs.utils import get_config, load_texture_from_zip
|
||||
from libs.utils import is_l_don_pressed, is_r_don_pressed, load_texture_from_zip
|
||||
|
||||
|
||||
class EntryScreen:
|
||||
@@ -18,16 +18,16 @@ class EntryScreen:
|
||||
if not self.screen_init:
|
||||
self.screen_init = True
|
||||
|
||||
def on_screen_end(self):
|
||||
def on_screen_end(self, next_screen: str):
|
||||
self.screen_init = False
|
||||
return "SONG_SELECT"
|
||||
return next_screen
|
||||
|
||||
def update(self):
|
||||
self.on_screen_start()
|
||||
keys = get_config()["keybinds"]["left_don"] + get_config()["keybinds"]["right_don"]
|
||||
for key in keys:
|
||||
if ray.is_key_pressed(ord(key)):
|
||||
return self.on_screen_end()
|
||||
if is_l_don_pressed() or is_r_don_pressed():
|
||||
return self.on_screen_end("SONG_SELECT")
|
||||
if ray.is_key_pressed(ray.KeyboardKey.KEY_F1):
|
||||
return self.on_screen_end("SETTINGS")
|
||||
|
||||
def draw(self):
|
||||
ray.draw_texture(self.texture_footer, 0, self.height - 151, ray.WHITE)
|
||||
|
||||
108
scenes/game.py
108
scenes/game.py
@@ -15,6 +15,10 @@ from libs.utils import (
|
||||
get_config,
|
||||
get_current_ms,
|
||||
global_data,
|
||||
is_l_don_pressed,
|
||||
is_l_kat_pressed,
|
||||
is_r_don_pressed,
|
||||
is_r_kat_pressed,
|
||||
load_all_textures_from_zip,
|
||||
load_image_from_zip,
|
||||
load_texture_from_zip,
|
||||
@@ -38,6 +42,7 @@ class GameScreen:
|
||||
self.end_ms = 0
|
||||
self.start_delay = 1000
|
||||
self.song_started = False
|
||||
self.prev_touch_count = 0
|
||||
|
||||
self.background = Background(width, height)
|
||||
|
||||
@@ -150,14 +155,14 @@ class GameScreen:
|
||||
result = cursor.fetchone()
|
||||
if result is None or session_data.result_score > result[0]:
|
||||
insert_query = '''
|
||||
INSERT OR REPLACE INTO Scores (hash, en_name, jp_name, diff, score, good, ok, bad, drumroll, combo)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
INSERT OR REPLACE INTO Scores (hash, en_name, jp_name, diff, score, good, ok, bad, drumroll, combo, clear)
|
||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||
'''
|
||||
data = (hash, self.tja.metadata.title['en'],
|
||||
self.tja.metadata.title['ja'], self.player_1.difficulty,
|
||||
self.tja.metadata.title.get('ja', ''), self.player_1.difficulty,
|
||||
session_data.result_score, session_data.result_good,
|
||||
session_data.result_ok, session_data.result_bad,
|
||||
session_data.result_total_drumroll, session_data.result_max_combo)
|
||||
session_data.result_total_drumroll, session_data.result_max_combo, int(self.player_1.gauge.gauge_length > self.player_1.gauge.clear_start[min(self.player_1.difficulty, 3)]))
|
||||
cursor.execute(insert_query, data)
|
||||
con.commit()
|
||||
|
||||
@@ -222,6 +227,7 @@ class Player:
|
||||
|
||||
self.player_number = player_number
|
||||
self.difficulty = difficulty
|
||||
self.visual_offset = get_config()["general"]["visual_offset"]
|
||||
|
||||
self.play_notes, self.draw_note_list, self.draw_bar_list = game_screen.tja.notes_to_position(self.difficulty)
|
||||
self.total_notes = len([note for note in self.play_notes if 0 < note.type < 5])
|
||||
@@ -259,7 +265,7 @@ class Player:
|
||||
|
||||
self.input_log: dict[float, tuple] = dict()
|
||||
|
||||
self.gauge = Gauge(self.difficulty, game_screen.tja.metadata.course_data[self.difficulty].level)
|
||||
self.gauge = Gauge(self.difficulty, game_screen.tja.metadata.course_data[self.difficulty].level, self.total_notes)
|
||||
self.gauge_hit_effect: list[GaugeHitEffect] = []
|
||||
|
||||
self.autoplay_hit_side = 'L'
|
||||
@@ -269,7 +275,7 @@ class Player:
|
||||
return self.score, self.good_count, self.ok_count, self.bad_count, self.total_drumroll, self.max_combo
|
||||
|
||||
def get_position(self, game_screen: GameScreen, ms: float, pixels_per_frame: float) -> int:
|
||||
return int(game_screen.width + pixels_per_frame * 60 / 1000 * (ms - game_screen.current_ms) - 64)
|
||||
return int(game_screen.width + pixels_per_frame * 60 / 1000 * (ms - game_screen.current_ms) - 64) - self.visual_offset
|
||||
|
||||
def animation_manager(self, animation_list: list):
|
||||
if len(animation_list) <= 0:
|
||||
@@ -305,6 +311,7 @@ class Player:
|
||||
if 0 < note.type <= 4:
|
||||
self.combo = 0
|
||||
self.bad_count += 1
|
||||
self.gauge.add_bad()
|
||||
self.play_notes.popleft()
|
||||
elif note.type != 8:
|
||||
tail = self.play_notes[1]
|
||||
@@ -437,6 +444,7 @@ class Player:
|
||||
self.score += self.base_score
|
||||
self.base_score_list.append(ScoreCounterAnimation(self.base_score))
|
||||
self.note_correct(game_screen, curr_note)
|
||||
self.gauge.add_good()
|
||||
|
||||
elif (curr_note.hit_ms - Player.TIMING_OK) <= game_screen.current_ms <= (curr_note.hit_ms + Player.TIMING_OK):
|
||||
self.draw_judge_list.append(Judgement('OK', big, ms_display=game_screen.current_ms - curr_note.hit_ms))
|
||||
@@ -444,12 +452,14 @@ class Player:
|
||||
self.score += 10 * math.floor(self.base_score / 2 / 10)
|
||||
self.base_score_list.append(ScoreCounterAnimation(10 * math.floor(self.base_score / 2 / 10)))
|
||||
self.note_correct(game_screen, curr_note)
|
||||
self.gauge.add_ok()
|
||||
|
||||
elif (curr_note.hit_ms - Player.TIMING_BAD) <= game_screen.current_ms <= (curr_note.hit_ms + Player.TIMING_BAD):
|
||||
self.draw_judge_list.append(Judgement('BAD', big, ms_display=game_screen.current_ms - curr_note.hit_ms))
|
||||
self.bad_count += 1
|
||||
self.combo = 0
|
||||
self.play_notes.popleft()
|
||||
self.gauge.add_bad()
|
||||
|
||||
def drumroll_counter_manager(self, game_screen: GameScreen):
|
||||
if self.is_drumroll and self.curr_drumroll_count > 0 and self.drumroll_counter is None:
|
||||
@@ -467,26 +477,23 @@ class Player:
|
||||
if self.balloon_anim.is_finished:
|
||||
self.balloon_anim = None
|
||||
|
||||
def key_manager(self, game_screen: GameScreen):
|
||||
key_configs = [
|
||||
{"keys": get_config()["keybinds"]["left_don"], "type": "DON", "side": "L", "note_type": 1},
|
||||
{"keys": get_config()["keybinds"]["right_don"], "type": "DON", "side": "R", "note_type": 1},
|
||||
{"keys": get_config()["keybinds"]["left_kat"], "type": "KAT", "side": "L", "note_type": 2},
|
||||
{"keys": get_config()["keybinds"]["right_kat"], "type": "KAT", "side": "R", "note_type": 2}
|
||||
]
|
||||
for config in key_configs:
|
||||
for key in config["keys"]:
|
||||
if ray.is_key_pressed(ord(key)):
|
||||
hit_type = config["type"]
|
||||
self.lane_hit_effect = LaneHitEffect(hit_type)
|
||||
self.draw_drum_hit_list.append(DrumHitEffect(hit_type, config["side"]))
|
||||
def handle_input(self, game_screen: GameScreen):
|
||||
input_checks = [
|
||||
(is_l_don_pressed, 'DON', 'L', game_screen.sound_don),
|
||||
(is_r_don_pressed, 'DON', 'R', game_screen.sound_don),
|
||||
(is_l_kat_pressed, 'KAT', 'L', game_screen.sound_kat),
|
||||
(is_r_kat_pressed, 'KAT', 'R', game_screen.sound_kat)
|
||||
]
|
||||
for check_func, note_type, side, sound in input_checks:
|
||||
if check_func():
|
||||
self.lane_hit_effect = LaneHitEffect(note_type)
|
||||
self.draw_drum_hit_list.append(DrumHitEffect(note_type, side))
|
||||
|
||||
sound = game_screen.sound_don if hit_type == "DON" else game_screen.sound_kat
|
||||
if get_config()["general"]["sfx"]:
|
||||
audio.play_sound(sound)
|
||||
if get_config()["general"]["sfx"]:
|
||||
audio.play_sound(sound)
|
||||
|
||||
self.check_note(game_screen, config["note_type"])
|
||||
self.input_log[game_screen.current_ms] = (hit_type, key)
|
||||
self.check_note(game_screen, 1 if note_type == 'DON' else 2)
|
||||
self.input_log[game_screen.current_ms] = (note_type, side)
|
||||
|
||||
def autoplay_manager(self, game_screen: GameScreen):
|
||||
if not get_config()["general"]["autoplay"]:
|
||||
@@ -558,7 +565,7 @@ class Player:
|
||||
self.animation_manager(self.base_score_list)
|
||||
self.score_counter.update(get_current_ms(), self.score)
|
||||
self.autoplay_manager(game_screen)
|
||||
self.key_manager(game_screen)
|
||||
self.handle_input(game_screen)
|
||||
|
||||
self.gauge.update(get_current_ms(), self.good_count, self.ok_count, self.bad_count, self.total_notes)
|
||||
|
||||
@@ -686,6 +693,7 @@ class Player:
|
||||
self.score_counter.draw(game_screen)
|
||||
for anim in self.base_score_list:
|
||||
anim.draw(game_screen)
|
||||
#ray.draw_circle(game_screen.width//2, game_screen.height, 300, ray.ORANGE)
|
||||
|
||||
class Judgement:
|
||||
def __init__(self, type: str, big: bool, ms_display: Optional[float]=None):
|
||||
@@ -1232,8 +1240,10 @@ class ResultTransition:
|
||||
x += texture_2.width
|
||||
|
||||
class Gauge:
|
||||
def __init__(self, difficulty: int, level: int):
|
||||
def __init__(self, difficulty: int, level: int, total_notes: int):
|
||||
self.gauge_length = 0
|
||||
self.previous_length = 0
|
||||
self.total_notes = total_notes
|
||||
self.difficulty = min(3, difficulty)
|
||||
self.clear_start = [0, 0, 68, 68]
|
||||
self.level = min(10, level)
|
||||
@@ -1285,16 +1295,29 @@ class Gauge:
|
||||
self.rainbow_fade_in = None
|
||||
self.rainbow_animation = None
|
||||
|
||||
def add_good(self):
|
||||
self.gauge_update_anim = Animation.create_fade(450)
|
||||
self.previous_length = int(self.gauge_length)
|
||||
self.gauge_length += (1 / self.total_notes) * (100 * (self.clear_start[self.difficulty] / self.table[self.difficulty][self.level]["clear_rate"]))
|
||||
if self.gauge_length > 87:
|
||||
self.gauge_length = 87
|
||||
|
||||
def add_ok(self):
|
||||
self.gauge_update_anim = Animation.create_fade(450)
|
||||
self.previous_length = int(self.gauge_length)
|
||||
self.gauge_length += ((1 * self.table[self.difficulty][self.level]["ok_multiplier"]) / self.total_notes) * (100 * (self.clear_start[self.difficulty] / self.table[self.difficulty][self.level]["clear_rate"]))
|
||||
if self.gauge_length > 87:
|
||||
self.gauge_length = 87
|
||||
|
||||
def add_bad(self):
|
||||
self.previous_length = int(self.gauge_length)
|
||||
self.gauge_length += ((1 * self.table[self.difficulty][self.level]["bad_multiplier"]) / self.total_notes) * (100 * (self.clear_start[self.difficulty] / self.table[self.difficulty][self.level]["clear_rate"]))
|
||||
if self.gauge_length < 0:
|
||||
self.gauge_length = 0
|
||||
|
||||
def update(self, current_ms: float, good_count: int, ok_count: int, bad_count: int, total_notes: int):
|
||||
gauge_length = int(((good_count +
|
||||
(ok_count * self.table[self.difficulty][self.level]["ok_multiplier"] +
|
||||
bad_count * self.table[self.difficulty][self.level]["bad_multiplier"])) / total_notes) * (100 * (self.clear_start[self.difficulty] / self.table[self.difficulty][self.level]["clear_rate"])))
|
||||
previous_length = self.gauge_length
|
||||
self.gauge_length = min(87, gauge_length)
|
||||
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)
|
||||
if self.gauge_length > previous_length:
|
||||
self.gauge_update_anim = Animation.create_fade(450)
|
||||
|
||||
if self.gauge_update_anim is not None:
|
||||
self.gauge_update_anim.update(current_ms)
|
||||
@@ -1314,12 +1337,13 @@ class Gauge:
|
||||
def draw(self, textures: list[ray.Texture]):
|
||||
ray.draw_texture(textures[0], 327, 132, ray.WHITE)
|
||||
ray.draw_texture(textures[1], 483, 124, ray.WHITE)
|
||||
if self.gauge_length == 87 and self.rainbow_fade_in is not None and self.rainbow_animation is not None:
|
||||
gauge_length = int(self.gauge_length)
|
||||
if gauge_length == 87 and self.rainbow_fade_in is not None and self.rainbow_animation is not None:
|
||||
if 0 < self.rainbow_animation.attribute < 8:
|
||||
ray.draw_texture(textures[1 + int(self.rainbow_animation.attribute)], 483, 124, ray.fade(ray.WHITE, self.rainbow_fade_in.attribute))
|
||||
ray.draw_texture(textures[2 + int(self.rainbow_animation.attribute)], 483, 124, ray.fade(ray.WHITE, self.rainbow_fade_in.attribute))
|
||||
if self.rainbow_fade_in is None or not self.rainbow_fade_in.is_finished:
|
||||
for i in range(self.gauge_length):
|
||||
for i in range(gauge_length):
|
||||
if i == 68:
|
||||
ray.draw_texture(textures[16], 491 + (i*textures[13].width), 160 - 24, ray.WHITE)
|
||||
elif i > 68:
|
||||
@@ -1327,15 +1351,15 @@ class Gauge:
|
||||
ray.draw_texture(textures[20], 491 + (i*textures[13].width) + 2, 160, ray.WHITE)
|
||||
else:
|
||||
ray.draw_texture(textures[13], 491 + (i*textures[13].width), 160, ray.WHITE)
|
||||
if self.gauge_update_anim is not None and self.gauge_length < 88:
|
||||
if self.gauge_length == 69:
|
||||
ray.draw_texture(textures[17], 491 + (self.gauge_length*textures[13].width) - 13, 160 - 8 - 24, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
elif self.gauge_length > 69:
|
||||
ray.draw_texture(textures[21], 491 + (self.gauge_length*textures[13].width) - 13, 160 - 8 - 22, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
if self.gauge_update_anim is not None and gauge_length < 88 and gauge_length != self.previous_length:
|
||||
if gauge_length == 69:
|
||||
ray.draw_texture(textures[17], 491 + (gauge_length*textures[13].width) - 13, 160 - 8 - 24, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
elif gauge_length > 69:
|
||||
ray.draw_texture(textures[21], 491 + (gauge_length*textures[13].width) - 13, 160 - 8 - 22, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
else:
|
||||
ray.draw_texture(textures[14], 491 + (self.gauge_length*textures[13].width) - 13, 160 - 8, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
ray.draw_texture(textures[14], 491 + (gauge_length*textures[13].width) - 13, 160 - 8, ray.fade(ray.WHITE, self.gauge_update_anim.attribute))
|
||||
ray.draw_texture(textures[10], 483, 124, ray.fade(ray.WHITE, 0.15))
|
||||
if self.gauge_length >= 69:
|
||||
if gauge_length >= 69:
|
||||
ray.draw_texture(textures[18], 1038, 141, ray.WHITE)
|
||||
ray.draw_texture(textures[19], 1187, 130, ray.WHITE)
|
||||
else:
|
||||
|
||||
@@ -8,9 +8,10 @@ from libs.audio import audio
|
||||
from libs.utils import (
|
||||
OutlinedText,
|
||||
draw_scaled_texture,
|
||||
get_config,
|
||||
get_current_ms,
|
||||
global_data,
|
||||
is_l_don_pressed,
|
||||
is_r_don_pressed,
|
||||
load_all_textures_from_zip,
|
||||
session_data,
|
||||
)
|
||||
@@ -60,6 +61,7 @@ class ResultScreen:
|
||||
['max_combo', session_data.result_max_combo]]
|
||||
self.update_index = 0
|
||||
self.is_skipped = False
|
||||
self.start_ms = get_current_ms()
|
||||
|
||||
def on_screen_end(self):
|
||||
self.screen_init = False
|
||||
@@ -94,6 +96,14 @@ class ResultScreen:
|
||||
self.score_animator = ScoreAnimator(self.update_list[self.update_index][1])
|
||||
self.score_delay += 16.67 * 3
|
||||
|
||||
def handle_input(self):
|
||||
if is_r_don_pressed() or is_l_don_pressed():
|
||||
if not self.is_skipped:
|
||||
self.is_skipped = True
|
||||
else:
|
||||
if self.fade_out is None:
|
||||
self.fade_out = FadeOut()
|
||||
audio.play_sound(self.sound_don)
|
||||
|
||||
def update(self):
|
||||
self.on_screen_start()
|
||||
@@ -108,16 +118,9 @@ class ResultScreen:
|
||||
if self.gauge.is_finished and self.score_delay is None:
|
||||
self.score_delay = get_current_ms() + 1883
|
||||
|
||||
left_dons = get_config()["keybinds"]["left_don"]
|
||||
right_dons = get_config()["keybinds"]["right_don"]
|
||||
for don in left_dons + right_dons:
|
||||
if ray.is_key_pressed(ord(don)):
|
||||
if not self.is_skipped:
|
||||
self.is_skipped = True
|
||||
else:
|
||||
if self.fade_out is None:
|
||||
self.fade_out = FadeOut()
|
||||
audio.play_sound(self.sound_don)
|
||||
if get_current_ms() >= self.start_ms + 5000:
|
||||
self.handle_input()
|
||||
|
||||
self.update_score_animation(self.is_skipped)
|
||||
|
||||
if self.fade_out is not None:
|
||||
@@ -263,12 +266,13 @@ class Gauge:
|
||||
def draw(self, textures: list[ray.Texture]):
|
||||
color = ray.fade(ray.WHITE, self.gauge_fade_in.attribute)
|
||||
draw_scaled_texture(textures[217], 554, 109, (10/11), color)
|
||||
if self.gauge_length == 87 and self.rainbow_animation is not None:
|
||||
gauge_length = int(self.gauge_length)
|
||||
if gauge_length == 87 and self.rainbow_animation is not None:
|
||||
if 0 < self.rainbow_animation.attribute < 8:
|
||||
draw_scaled_texture(textures[217 + int(self.rainbow_animation.attribute)], 554, 109, (10/11), color)
|
||||
draw_scaled_texture(textures[218 + int(self.rainbow_animation.attribute)], 554, 109, (10/11), color)
|
||||
else:
|
||||
for i in range(self.gauge_length+1):
|
||||
for i in range(gauge_length+1):
|
||||
width = int(i * 7.2)
|
||||
if i == 69:
|
||||
draw_scaled_texture(textures[192], 562 + width, 142 - 22, (10/11), color)
|
||||
@@ -285,7 +289,7 @@ class Gauge:
|
||||
draw_scaled_texture(textures[226], 554, 109, (10/11), ray.fade(ray.WHITE, min(0.15, self.gauge_fade_in.attribute)))
|
||||
draw_scaled_texture(textures[176], 1185, 116, (10/11), color)
|
||||
|
||||
if self.gauge_length >= 69:
|
||||
if gauge_length >= 69:
|
||||
draw_scaled_texture(textures[194], 1058, 124, (10/11), color)
|
||||
draw_scaled_texture(textures[195], 1182, 115, (10/11), color)
|
||||
else:
|
||||
|
||||
235
scenes/settings.py
Normal file
235
scenes/settings.py
Normal file
@@ -0,0 +1,235 @@
|
||||
import pyray as ray
|
||||
import sounddevice as sd
|
||||
|
||||
from libs.utils import (
|
||||
get_config,
|
||||
is_l_don_pressed,
|
||||
is_l_kat_pressed,
|
||||
is_r_don_pressed,
|
||||
is_r_kat_pressed,
|
||||
save_config,
|
||||
)
|
||||
|
||||
|
||||
class SettingsScreen:
|
||||
def __init__(self, width: int, height: int):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.screen_init = False
|
||||
self.config = get_config()
|
||||
self.headers = list(self.config.keys())
|
||||
self.headers.append('Exit')
|
||||
self.header_index = 0
|
||||
self.setting_index = 0
|
||||
self.in_setting_edit = False
|
||||
self.editing_key = False
|
||||
self.temp_key_input = ""
|
||||
|
||||
def on_screen_start(self):
|
||||
if not self.screen_init:
|
||||
self.screen_init = True
|
||||
|
||||
def on_screen_end(self):
|
||||
self.screen_init = False
|
||||
save_config(self.config)
|
||||
return "ENTRY"
|
||||
|
||||
def get_current_settings(self):
|
||||
"""Get the current section's settings as a list"""
|
||||
current_header = self.headers[self.header_index]
|
||||
if current_header == 'Exit' or current_header not in self.config:
|
||||
return []
|
||||
return list(self.config[current_header].items())
|
||||
|
||||
def handle_boolean_toggle(self, section, key):
|
||||
"""Toggle boolean values"""
|
||||
self.config[section][key] = not self.config[section][key]
|
||||
|
||||
def handle_numeric_change(self, section, key, increment):
|
||||
"""Handle numeric value changes"""
|
||||
current_value = self.config[section][key]
|
||||
|
||||
# Define step sizes for different settings
|
||||
step_sizes = {
|
||||
'judge_offset': 1,
|
||||
'visual_offset': 1,
|
||||
'buffer_size': 1,
|
||||
'sample_rate': 1000,
|
||||
}
|
||||
|
||||
step = step_sizes.get(key, 1)
|
||||
new_value = current_value + (step * increment)
|
||||
|
||||
# Apply constraints for specific settings
|
||||
if key == 'judge_offset':
|
||||
new_value = max(-50, min(50, new_value))
|
||||
elif key == 'visual_offset':
|
||||
new_value = max(-20, min(20, new_value))
|
||||
elif key == 'buffer_size':
|
||||
new_value = max(1, min(32, new_value))
|
||||
elif key == 'sample_rate':
|
||||
valid_rates = [22050, 44100, 48000, 88200, 96000]
|
||||
current_idx = valid_rates.index(current_value) if current_value in valid_rates else 2
|
||||
new_idx = max(0, min(len(valid_rates) - 1, current_idx + increment))
|
||||
new_value = valid_rates[new_idx]
|
||||
|
||||
self.config[section][key] = new_value
|
||||
|
||||
def handle_string_cycle(self, section, key):
|
||||
"""Cycle through predefined string values"""
|
||||
current_value = self.config[section][key]
|
||||
|
||||
hostapis = sd.query_hostapis()
|
||||
audio_devices = []
|
||||
if isinstance(hostapis, tuple):
|
||||
for api in hostapis:
|
||||
if isinstance(api, dict):
|
||||
audio_devices.append(api['name'])
|
||||
|
||||
options = {
|
||||
'language': ['ja', 'en'],
|
||||
'device_type': audio_devices
|
||||
}
|
||||
|
||||
if key in options:
|
||||
values = options[key]
|
||||
try:
|
||||
current_idx = values.index(current_value)
|
||||
new_idx = (current_idx + 1) % len(values)
|
||||
self.config[section][key] = values[new_idx]
|
||||
except ValueError:
|
||||
self.config[section][key] = values[0]
|
||||
|
||||
def handle_key_binding(self, section, key):
|
||||
"""Handle key binding changes"""
|
||||
self.editing_key = True
|
||||
self.temp_key_input = ""
|
||||
|
||||
def update_key_binding(self):
|
||||
"""Update key binding based on input"""
|
||||
key_pressed = ray.get_key_pressed()
|
||||
if key_pressed != 0:
|
||||
# Convert keycode to character
|
||||
if 65 <= key_pressed <= 90: # A-Z
|
||||
new_key = chr(key_pressed)
|
||||
current_header = self.headers[self.header_index]
|
||||
settings = self.get_current_settings()
|
||||
if settings:
|
||||
setting_key, _ = settings[self.setting_index]
|
||||
self.config[current_header][setting_key] = [new_key]
|
||||
self.editing_key = False
|
||||
elif key_pressed == ray.KeyboardKey.KEY_ESCAPE:
|
||||
self.editing_key = False
|
||||
|
||||
def update(self):
|
||||
self.on_screen_start()
|
||||
|
||||
# Handle key binding editing
|
||||
if self.editing_key:
|
||||
self.update_key_binding()
|
||||
return
|
||||
|
||||
current_header = self.headers[self.header_index]
|
||||
|
||||
# Exit handling
|
||||
if current_header == 'Exit' and (is_l_don_pressed() or is_r_don_pressed()):
|
||||
return self.on_screen_end()
|
||||
|
||||
# Navigation between sections
|
||||
if not self.in_setting_edit:
|
||||
if is_r_kat_pressed():
|
||||
self.header_index = (self.header_index + 1) % len(self.headers)
|
||||
self.setting_index = 0
|
||||
elif is_l_kat_pressed():
|
||||
self.header_index = (self.header_index - 1) % len(self.headers)
|
||||
self.setting_index = 0
|
||||
elif (is_l_don_pressed() or is_r_don_pressed()) and current_header != 'Exit':
|
||||
self.in_setting_edit = True
|
||||
else:
|
||||
# Navigation within settings
|
||||
settings = self.get_current_settings()
|
||||
if not settings:
|
||||
self.in_setting_edit = False
|
||||
return
|
||||
|
||||
if is_r_kat_pressed():
|
||||
self.setting_index = (self.setting_index + 1) % len(settings)
|
||||
elif is_l_kat_pressed():
|
||||
self.setting_index = (self.setting_index - 1) % len(settings)
|
||||
elif is_r_don_pressed():
|
||||
# Modify setting value
|
||||
setting_key, setting_value = settings[self.setting_index]
|
||||
|
||||
if isinstance(setting_value, bool):
|
||||
self.handle_boolean_toggle(current_header, setting_key)
|
||||
elif isinstance(setting_value, (int, float)):
|
||||
self.handle_numeric_change(current_header, setting_key, 1)
|
||||
elif isinstance(setting_value, str):
|
||||
if 'keybinds' in current_header:
|
||||
self.handle_key_binding(current_header, setting_key)
|
||||
else:
|
||||
self.handle_string_cycle(current_header, setting_key)
|
||||
elif isinstance(setting_value, list) and len(setting_value) > 0:
|
||||
if isinstance(setting_value[0], str) and len(setting_value[0]) == 1:
|
||||
# Key binding
|
||||
self.handle_key_binding(current_header, setting_key)
|
||||
elif is_l_don_pressed():
|
||||
# Modify setting value (reverse direction for numeric)
|
||||
setting_key, setting_value = settings[self.setting_index]
|
||||
|
||||
if isinstance(setting_value, bool):
|
||||
self.handle_boolean_toggle(current_header, setting_key)
|
||||
elif isinstance(setting_value, (int, float)):
|
||||
self.handle_numeric_change(current_header, setting_key, -1)
|
||||
elif isinstance(setting_value, str):
|
||||
if 'keybinds' not in current_header:
|
||||
self.handle_string_cycle(current_header, setting_key)
|
||||
|
||||
elif ray.is_key_pressed(ray.KeyboardKey.KEY_ESCAPE):
|
||||
self.in_setting_edit = False
|
||||
|
||||
def draw(self):
|
||||
# Draw title
|
||||
ray.draw_text("SETTINGS", 20, 20, 30, ray.WHITE)
|
||||
|
||||
# Draw section headers
|
||||
current_header = self.headers[self.header_index]
|
||||
for i, key in enumerate(self.headers):
|
||||
color = ray.GREEN
|
||||
if key == current_header:
|
||||
color = ray.YELLOW if not self.in_setting_edit else ray.ORANGE
|
||||
ray.draw_text(f'{key}', 20, i*25 + 70, 20, color)
|
||||
|
||||
# Draw current section settings
|
||||
if current_header != 'Exit' and current_header in self.config:
|
||||
settings = self.get_current_settings()
|
||||
|
||||
# Draw settings list
|
||||
for i, (key, value) in enumerate(settings):
|
||||
color = ray.GREEN
|
||||
if self.in_setting_edit and i == self.setting_index:
|
||||
color = ray.YELLOW
|
||||
|
||||
# Format value display
|
||||
if isinstance(value, list):
|
||||
display_value = ', '.join(map(str, value))
|
||||
else:
|
||||
display_value = str(value)
|
||||
|
||||
ray.draw_text(f'{key}: {display_value}', 250, i*25 + 70, 20, color)
|
||||
|
||||
# Draw instructions
|
||||
y_offset = len(settings) * 25 + 150
|
||||
if not self.in_setting_edit:
|
||||
ray.draw_text("Don/Kat: Navigate sections", 20, y_offset, 16, ray.GRAY)
|
||||
ray.draw_text("L/R Don: Enter section", 20, y_offset + 20, 16, ray.GRAY)
|
||||
else:
|
||||
ray.draw_text("Don/Kat: Navigate settings", 20, y_offset, 16, ray.GRAY)
|
||||
ray.draw_text("L/R Don: Modify value", 20, y_offset + 20, 16, ray.GRAY)
|
||||
ray.draw_text("ESC: Back to sections", 20, y_offset + 40, 16, ray.GRAY)
|
||||
|
||||
if self.editing_key:
|
||||
ray.draw_text("Press a key to bind (ESC to cancel)", 20, y_offset + 60, 16, ray.RED)
|
||||
else:
|
||||
# Draw exit instruction
|
||||
ray.draw_text("Press Don to exit settings", 250, 100, 20, ray.GREEN)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,12 +3,13 @@ from pathlib import Path
|
||||
|
||||
import pyray as ray
|
||||
|
||||
from libs import song_hash
|
||||
from libs.animation import Animation
|
||||
from libs.audio import audio
|
||||
from libs.utils import (
|
||||
get_config,
|
||||
get_current_ms,
|
||||
is_l_don_pressed,
|
||||
is_r_don_pressed,
|
||||
load_all_textures_from_zip,
|
||||
load_texture_from_zip,
|
||||
)
|
||||
@@ -47,9 +48,6 @@ class TitleScreen:
|
||||
if not self.screen_init:
|
||||
self.screen_init = True
|
||||
self.load_textures()
|
||||
|
||||
song_hash.song_hashes = song_hash.build_song_hashes()
|
||||
|
||||
self.scene = 'Opening Video'
|
||||
self.op_video = VideoPlayer(random.choice(self.op_video_list))
|
||||
self.attract_video = VideoPlayer(random.choice(self.attract_video_list))
|
||||
@@ -97,10 +95,8 @@ class TitleScreen:
|
||||
self.on_screen_start()
|
||||
|
||||
self.scene_manager()
|
||||
keys = get_config()["keybinds"]["left_don"] + get_config()["keybinds"]["right_don"]
|
||||
for key in keys:
|
||||
if ray.is_key_pressed(ord(key)):
|
||||
return self.on_screen_end()
|
||||
if is_l_don_pressed() or is_r_don_pressed():
|
||||
return self.on_screen_end()
|
||||
|
||||
def draw(self):
|
||||
if self.scene == 'Opening Video':
|
||||
|
||||
Reference in New Issue
Block a user