mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 11:40:13 +01:00
add modifiers
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
fps_counter = false
|
fps_counter = false
|
||||||
judge_offset = 0
|
judge_offset = 0
|
||||||
visual_offset = 0
|
visual_offset = 0
|
||||||
autoplay = false
|
|
||||||
language = "ja"
|
language = "ja"
|
||||||
hard_judge = 108
|
hard_judge = 108
|
||||||
|
|
||||||
|
|||||||
49
libs/tja.py
49
libs/tja.py
@@ -1,12 +1,13 @@
|
|||||||
import bisect
|
import bisect
|
||||||
import hashlib
|
import hashlib
|
||||||
import math
|
import math
|
||||||
|
import random
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from dataclasses import dataclass, field, fields
|
from dataclasses import dataclass, field, fields
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from libs.utils import get_pixels_per_frame, strip_comments
|
from libs.utils import get_pixels_per_frame, global_data, strip_comments
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=64)
|
@lru_cache(maxsize=64)
|
||||||
@@ -584,6 +585,7 @@ class TJAParser:
|
|||||||
continue
|
continue
|
||||||
note = Note()
|
note = Note()
|
||||||
note.hit_ms = self.current_ms
|
note.hit_ms = self.current_ms
|
||||||
|
note.display = True
|
||||||
note.pixels_per_frame_x = bar_line.pixels_per_frame_x
|
note.pixels_per_frame_x = bar_line.pixels_per_frame_x
|
||||||
note.pixels_per_frame_y = bar_line.pixels_per_frame_y
|
note.pixels_per_frame_y = bar_line.pixels_per_frame_y
|
||||||
pixels_per_ms = get_pixels_per_ms(note.pixels_per_frame_x)
|
pixels_per_ms = get_pixels_per_ms(note.pixels_per_frame_x)
|
||||||
@@ -628,6 +630,7 @@ class TJAParser:
|
|||||||
# Sorting by load_ms is necessary for drawing, as some notes appear on the
|
# Sorting by load_ms is necessary for drawing, as some notes appear on the
|
||||||
# screen slower regardless of when they reach the judge circle
|
# screen slower regardless of when they reach the judge circle
|
||||||
# Bars can be sorted like this because they don't need hit detection
|
# Bars can be sorted like this because they don't need hit detection
|
||||||
|
print(play_note_list[0])
|
||||||
return deque(play_note_list), deque(draw_note_list), deque(bar_list)
|
return deque(play_note_list), deque(draw_note_list), deque(bar_list)
|
||||||
|
|
||||||
def hash_note_data(self, play_notes: deque[Note | Drumroll | Balloon], bars: deque[Note]):
|
def hash_note_data(self, play_notes: deque[Note | Drumroll | Balloon], bars: deque[Note]):
|
||||||
@@ -650,3 +653,47 @@ class TJAParser:
|
|||||||
n.update(item.get_hash().encode('utf-8'))
|
n.update(item.get_hash().encode('utf-8'))
|
||||||
|
|
||||||
return n.hexdigest()
|
return n.hexdigest()
|
||||||
|
|
||||||
|
def modifier_speed(notes: deque[Note | Balloon | Drumroll], bars, value: float):
|
||||||
|
notes = notes.copy()
|
||||||
|
for note in notes:
|
||||||
|
note.pixels_per_frame_x *= value
|
||||||
|
note.load_ms = note.hit_ms - (866 / get_pixels_per_ms(note.pixels_per_frame_x))
|
||||||
|
for bar in bars:
|
||||||
|
bar.pixels_per_frame_x *= value
|
||||||
|
bar.load_ms = bar.hit_ms - (866 / get_pixels_per_ms(bar.pixels_per_frame_x))
|
||||||
|
return notes, bars
|
||||||
|
|
||||||
|
def modifier_display(notes: deque[Note | Balloon | Drumroll]):
|
||||||
|
notes = notes.copy()
|
||||||
|
for note in notes:
|
||||||
|
note.display = False
|
||||||
|
return notes
|
||||||
|
|
||||||
|
def modifier_inverse(notes: deque[Note | Balloon | Drumroll]):
|
||||||
|
notes = notes.copy()
|
||||||
|
type_mapping = {1: 2, 2: 1, 3: 4, 4: 3}
|
||||||
|
for note in notes:
|
||||||
|
if note.type in type_mapping:
|
||||||
|
note.type = type_mapping[note.type]
|
||||||
|
return notes
|
||||||
|
|
||||||
|
def modifier_random(notes: deque[Note | Balloon | Drumroll], value: int):
|
||||||
|
#value: 1 == kimagure, 2 == detarame
|
||||||
|
notes = notes.copy()
|
||||||
|
percentage = int(len(notes) / 5) * value
|
||||||
|
selected_notes = random.sample(range(len(notes)), percentage)
|
||||||
|
type_mapping = {1: 2, 2: 1, 3: 4, 4: 3}
|
||||||
|
for i in selected_notes:
|
||||||
|
if notes[i].type in type_mapping:
|
||||||
|
notes[i].type = type_mapping[notes[i].type]
|
||||||
|
return notes
|
||||||
|
|
||||||
|
def apply_modifiers(notes: deque[Note | Balloon | Drumroll], draw_notes: deque[Note | Balloon | Drumroll], bars: deque[Note]):
|
||||||
|
if global_data.modifiers.display:
|
||||||
|
draw_notes = modifier_display(draw_notes)
|
||||||
|
if global_data.modifiers.inverse:
|
||||||
|
notes = modifier_inverse(notes)
|
||||||
|
notes = modifier_random(notes, global_data.modifiers.random)
|
||||||
|
draw_notes, bars = modifier_speed(draw_notes, bars, global_data.modifiers.speed)
|
||||||
|
return notes, draw_notes, bars
|
||||||
|
|||||||
@@ -197,6 +197,14 @@ def is_r_kat_pressed() -> bool:
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Modifiers:
|
||||||
|
auto: bool = False
|
||||||
|
speed: float = 1.0
|
||||||
|
display: bool = False
|
||||||
|
inverse: bool = False
|
||||||
|
random: int = 0
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SessionData:
|
class SessionData:
|
||||||
selected_difficulty: int = 0
|
selected_difficulty: int = 0
|
||||||
@@ -227,6 +235,7 @@ class GlobalData:
|
|||||||
total_songs: int = 0
|
total_songs: int = 0
|
||||||
hit_sound: int = 0
|
hit_sound: int = 0
|
||||||
player_num: int = 1
|
player_num: int = 1
|
||||||
|
modifiers: Modifiers = field(default_factory=lambda: Modifiers())
|
||||||
|
|
||||||
global_data = GlobalData()
|
global_data = GlobalData()
|
||||||
|
|
||||||
|
|||||||
@@ -10,29 +10,23 @@ class DevScreen:
|
|||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.screen_init = False
|
self.screen_init = False
|
||||||
tex.load_screen_textures('song_select')
|
|
||||||
self.history = ScoreHistory({0: (583892, 0, 0, 0),
|
|
||||||
1: (234941, 0, 0, 0),
|
|
||||||
2: (867847, 0, 0, 0),
|
|
||||||
3: (485589, 0, 0, 0),
|
|
||||||
4: (1584395, 0, 0, 0)}, get_current_ms())
|
|
||||||
|
|
||||||
def on_screen_start(self):
|
def on_screen_start(self):
|
||||||
if not self.screen_init:
|
if not self.screen_init:
|
||||||
self.screen_init = True
|
self.screen_init = True
|
||||||
|
|
||||||
|
|
||||||
def on_screen_end(self, next_screen: str):
|
def on_screen_end(self, next_screen: str):
|
||||||
self.screen_init = False
|
self.screen_init = False
|
||||||
return next_screen
|
return next_screen
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.on_screen_start()
|
self.on_screen_start()
|
||||||
self.history.update(get_current_ms())
|
|
||||||
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
|
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
|
||||||
return self.on_screen_end('RESULT')
|
return self.on_screen_end('GAME')
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
self.history.draw()
|
pass
|
||||||
|
|
||||||
def draw_3d(self):
|
def draw_3d(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -11,7 +11,14 @@ from libs.animation import Animation
|
|||||||
from libs.audio import audio
|
from libs.audio import audio
|
||||||
from libs.backgrounds import Background
|
from libs.backgrounds import Background
|
||||||
from libs.texture import tex
|
from libs.texture import tex
|
||||||
from libs.tja import Balloon, Drumroll, Note, TJAParser, calculate_base_score
|
from libs.tja import (
|
||||||
|
Balloon,
|
||||||
|
Drumroll,
|
||||||
|
Note,
|
||||||
|
TJAParser,
|
||||||
|
apply_modifiers,
|
||||||
|
calculate_base_score,
|
||||||
|
)
|
||||||
from libs.transition import Transition
|
from libs.transition import Transition
|
||||||
from libs.utils import (
|
from libs.utils import (
|
||||||
OutlinedText,
|
OutlinedText,
|
||||||
@@ -34,6 +41,7 @@ class GameScreen:
|
|||||||
self.current_ms = 0
|
self.current_ms = 0
|
||||||
self.screen_init = False
|
self.screen_init = False
|
||||||
self.movie = None
|
self.movie = None
|
||||||
|
self.song_music = None
|
||||||
self.end_ms = 0
|
self.end_ms = 0
|
||||||
self.start_delay = 1000
|
self.start_delay = 1000
|
||||||
self.song_started = False
|
self.song_started = False
|
||||||
@@ -66,15 +74,13 @@ class GameScreen:
|
|||||||
else:
|
else:
|
||||||
self.movie = None
|
self.movie = None
|
||||||
session_data.song_title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
|
session_data.song_title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
|
||||||
if not hasattr(self, 'song_music'):
|
if self.tja.metadata.wave.exists() and self.tja.metadata.wave.is_file():
|
||||||
if self.tja.metadata.wave.exists() and self.tja.metadata.wave.is_file():
|
self.song_music = audio.load_music_stream(self.tja.metadata.wave)
|
||||||
self.song_music = audio.load_music_stream(self.tja.metadata.wave)
|
audio.normalize_music_stream(self.song_music, 0.1935)
|
||||||
audio.normalize_music_stream(self.song_music, 0.1935)
|
|
||||||
else:
|
|
||||||
self.song_music = None
|
|
||||||
self.start_ms = (get_current_ms() - self.tja.metadata.offset*1000)
|
|
||||||
|
|
||||||
self.player_1 = Player(self, global_data.player_num, difficulty)
|
self.player_1 = Player(self, global_data.player_num, difficulty)
|
||||||
|
if self.tja is not None:
|
||||||
|
self.start_ms = (get_current_ms() - self.tja.metadata.offset*1000)
|
||||||
|
|
||||||
def on_screen_start(self):
|
def on_screen_start(self):
|
||||||
if not self.screen_init:
|
if not self.screen_init:
|
||||||
@@ -107,7 +113,7 @@ class GameScreen:
|
|||||||
def write_score(self):
|
def write_score(self):
|
||||||
if self.tja is None:
|
if self.tja is None:
|
||||||
return
|
return
|
||||||
if global_data.config['general']['autoplay']:
|
if global_data.modifiers.auto:
|
||||||
return
|
return
|
||||||
with sqlite3.connect('scores.db') as con:
|
with sqlite3.connect('scores.db') as con:
|
||||||
cursor = con.cursor()
|
cursor = con.cursor()
|
||||||
@@ -210,6 +216,7 @@ class Player:
|
|||||||
|
|
||||||
if game_screen.tja is not None:
|
if game_screen.tja is not None:
|
||||||
self.play_notes, self.draw_note_list, self.draw_bar_list = game_screen.tja.notes_to_position(self.difficulty)
|
self.play_notes, self.draw_note_list, self.draw_bar_list = game_screen.tja.notes_to_position(self.difficulty)
|
||||||
|
self.play_notes, self.draw_note_list, self.draw_bar_list = apply_modifiers(self.play_notes, self.draw_note_list, self.draw_bar_list)
|
||||||
else:
|
else:
|
||||||
self.play_notes, self.draw_note_list, self.draw_bar_list = deque(), deque(), deque()
|
self.play_notes, self.draw_note_list, self.draw_bar_list = deque(), deque(), deque()
|
||||||
self.total_notes = len([note for note in self.play_notes if 0 < note.type < 5])
|
self.total_notes = len([note for note in self.play_notes if 0 < note.type < 5])
|
||||||
@@ -502,7 +509,7 @@ class Player:
|
|||||||
self.input_log[game_screen.current_ms] = (note_type, side)
|
self.input_log[game_screen.current_ms] = (note_type, side)
|
||||||
|
|
||||||
def autoplay_manager(self, game_screen: GameScreen):
|
def autoplay_manager(self, game_screen: GameScreen):
|
||||||
if not global_data.config["general"]["autoplay"]:
|
if not global_data.modifiers.auto:
|
||||||
return
|
return
|
||||||
if len(self.play_notes) == 0:
|
if len(self.play_notes) == 0:
|
||||||
return
|
return
|
||||||
@@ -582,12 +589,13 @@ class Player:
|
|||||||
end_position = self.get_position_x(game_screen.width, game_screen.current_ms, tail.load_ms, tail.pixels_per_frame_x)
|
end_position = self.get_position_x(game_screen.width, game_screen.current_ms, tail.load_ms, tail.pixels_per_frame_x)
|
||||||
length = end_position - start_position
|
length = end_position - start_position
|
||||||
color = ray.Color(255, head.color, head.color, 255)
|
color = ray.Color(255, head.color, head.color, 255)
|
||||||
tex.draw_texture('notes', "8", frame=is_big, x=start_position+64, y=192, x2=length-64-32, color=color)
|
if head.display:
|
||||||
if is_big:
|
tex.draw_texture('notes', "8", frame=is_big, x=start_position+64, y=192, x2=length-64-32, color=color)
|
||||||
tex.draw_texture('notes', "drumroll_big_tail", x=end_position, y=192, color=color)
|
if is_big:
|
||||||
else:
|
tex.draw_texture('notes', "drumroll_big_tail", x=end_position, y=192, color=color)
|
||||||
tex.draw_texture('notes', "drumroll_tail", x=end_position, y=192, color=color)
|
else:
|
||||||
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=192, color=color)
|
tex.draw_texture('notes', "drumroll_tail", x=end_position, y=192, color=color)
|
||||||
|
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=192, color=color)
|
||||||
|
|
||||||
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + 60, y=323, x2=length)
|
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + 60, y=323, x2=length)
|
||||||
tex.draw_texture('notes', 'moji', frame=head.moji, x=(start_position - (168//2)) + 64, y=323)
|
tex.draw_texture('notes', 'moji', frame=head.moji, x=(start_position - (168//2)) + 64, y=323)
|
||||||
@@ -605,7 +613,8 @@ class Player:
|
|||||||
position = pause_position
|
position = pause_position
|
||||||
else:
|
else:
|
||||||
position = start_position
|
position = start_position
|
||||||
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset, y=192)
|
if head.display:
|
||||||
|
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset, y=192)
|
||||||
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+128, y=192)
|
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+128, y=192)
|
||||||
|
|
||||||
def draw_bars(self, game_screen: GameScreen):
|
def draw_bars(self, game_screen: GameScreen):
|
||||||
@@ -650,9 +659,27 @@ class Player:
|
|||||||
self.draw_balloon(game_screen, note, current_eighth)
|
self.draw_balloon(game_screen, note, current_eighth)
|
||||||
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
||||||
else:
|
else:
|
||||||
tex.draw_texture('notes', str(note.type), frame=current_eighth % 2, x=x_position, y=y_position+192, center=True)
|
if note.display:
|
||||||
|
tex.draw_texture('notes', str(note.type), frame=current_eighth % 2, x=x_position, y=y_position+192, center=True)
|
||||||
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
||||||
|
|
||||||
|
def draw_modifiers(self):
|
||||||
|
tex.draw_texture('lane', 'mod_shinuchi')
|
||||||
|
if global_data.modifiers.speed >= 4:
|
||||||
|
tex.draw_texture('lane', 'mod_yonbai')
|
||||||
|
elif global_data.modifiers.speed >= 3:
|
||||||
|
tex.draw_texture('lane', 'mod_sanbai')
|
||||||
|
elif global_data.modifiers.speed > 1:
|
||||||
|
tex.draw_texture('lane', 'mod_baisaku')
|
||||||
|
if global_data.modifiers.display:
|
||||||
|
tex.draw_texture('lane', 'mod_doron')
|
||||||
|
if global_data.modifiers.inverse:
|
||||||
|
tex.draw_texture('lane', 'mod_abekobe')
|
||||||
|
if global_data.modifiers.random == 2:
|
||||||
|
tex.draw_texture('lane', 'mod_detarame')
|
||||||
|
elif global_data.modifiers.random == 1:
|
||||||
|
tex.draw_texture('lane', 'mod_kimagure')
|
||||||
|
|
||||||
def draw(self, game_screen: GameScreen):
|
def draw(self, game_screen: GameScreen):
|
||||||
tex.draw_texture('lane', 'lane_background')
|
tex.draw_texture('lane', 'lane_background')
|
||||||
self.gauge.draw()
|
self.gauge.draw()
|
||||||
@@ -665,7 +692,7 @@ class Player:
|
|||||||
self.draw_notes(game_screen)
|
self.draw_notes(game_screen)
|
||||||
tex.draw_texture('lane', f'{self.player_number}p_lane_cover')
|
tex.draw_texture('lane', f'{self.player_number}p_lane_cover')
|
||||||
tex.draw_texture('lane', 'drum')
|
tex.draw_texture('lane', 'drum')
|
||||||
if global_data.config["general"]["autoplay"]:
|
if global_data.modifiers.auto:
|
||||||
tex.draw_texture('lane', 'auto_icon')
|
tex.draw_texture('lane', 'auto_icon')
|
||||||
for anim in self.draw_drum_hit_list:
|
for anim in self.draw_drum_hit_list:
|
||||||
anim.draw()
|
anim.draw()
|
||||||
@@ -673,6 +700,7 @@ class Player:
|
|||||||
tex.draw_texture('lane', 'lane_score_cover')
|
tex.draw_texture('lane', 'lane_score_cover')
|
||||||
tex.draw_texture('lane', f'{self.player_number}p_icon')
|
tex.draw_texture('lane', f'{self.player_number}p_icon')
|
||||||
tex.draw_texture('lane', 'lane_difficulty', frame=self.difficulty)
|
tex.draw_texture('lane', 'lane_difficulty', frame=self.difficulty)
|
||||||
|
self.draw_modifiers()
|
||||||
if self.drumroll_counter is not None:
|
if self.drumroll_counter is not None:
|
||||||
self.drumroll_counter.draw()
|
self.drumroll_counter.draw()
|
||||||
for anim in self.draw_arc_list:
|
for anim in self.draw_arc_list:
|
||||||
|
|||||||
@@ -391,8 +391,7 @@ class ScoreAnimator:
|
|||||||
if int(ret_val) == 0:
|
if int(ret_val) == 0:
|
||||||
if not (len(self.target_score) - self.digit_index) > (len(self.target_score)):
|
if not (len(self.target_score) - self.digit_index) > (len(self.target_score)):
|
||||||
return '0' * (len(self.target_score) - self.digit_index)
|
return '0' * (len(self.target_score) - self.digit_index)
|
||||||
else:
|
return '0'
|
||||||
return '0'
|
|
||||||
return str(int(ret_val))
|
return str(int(ret_val))
|
||||||
|
|
||||||
class HighScoreIndicator:
|
class HighScoreIndicator:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from dataclasses import fields
|
||||||
import random
|
import random
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
@@ -12,6 +13,7 @@ from libs.texture import tex
|
|||||||
from libs.tja import TJAParser, test_encodings
|
from libs.tja import TJAParser, test_encodings
|
||||||
from libs.transition import Transition
|
from libs.transition import Transition
|
||||||
from libs.utils import (
|
from libs.utils import (
|
||||||
|
Modifiers,
|
||||||
OutlinedText,
|
OutlinedText,
|
||||||
get_current_ms,
|
get_current_ms,
|
||||||
global_data,
|
global_data,
|
||||||
@@ -72,6 +74,7 @@ class SongSelectScreen:
|
|||||||
self.demo_song = None
|
self.demo_song = None
|
||||||
self.diff_sort_selector = None
|
self.diff_sort_selector = None
|
||||||
self.neiro_selector = None
|
self.neiro_selector = None
|
||||||
|
self.modifier_selector = None
|
||||||
self.texture_index = 9
|
self.texture_index = 9
|
||||||
self.last_texture_index = 9
|
self.last_texture_index = 9
|
||||||
self.last_moved = get_current_ms()
|
self.last_moved = get_current_ms()
|
||||||
@@ -169,20 +172,31 @@ class SongSelectScreen:
|
|||||||
def handle_input_selected(self):
|
def handle_input_selected(self):
|
||||||
# Handle song selection confirmation or cancel
|
# Handle song selection confirmation or cancel
|
||||||
if self.neiro_selector is not None:
|
if self.neiro_selector is not None:
|
||||||
if is_l_kat_pressed() or is_r_kat_pressed():
|
if is_l_kat_pressed():
|
||||||
if is_l_kat_pressed():
|
self.neiro_selector.move_left()
|
||||||
self.neiro_selector.move_left()
|
elif is_r_kat_pressed():
|
||||||
elif is_r_kat_pressed():
|
self.neiro_selector.move_right()
|
||||||
self.neiro_selector.move_right()
|
|
||||||
if is_l_don_pressed() or is_r_don_pressed():
|
if is_l_don_pressed() or is_r_don_pressed():
|
||||||
audio.play_sound(self.sound_don)
|
audio.play_sound(self.sound_don)
|
||||||
self.neiro_selector.confirm()
|
self.neiro_selector.confirm()
|
||||||
return
|
return
|
||||||
|
if self.modifier_selector is not None:
|
||||||
|
if is_l_kat_pressed():
|
||||||
|
audio.play_sound(self.sound_kat)
|
||||||
|
self.modifier_selector.left()
|
||||||
|
elif is_r_kat_pressed():
|
||||||
|
audio.play_sound(self.sound_kat)
|
||||||
|
self.modifier_selector.right()
|
||||||
|
if is_l_don_pressed() or is_r_don_pressed():
|
||||||
|
audio.play_sound(self.sound_don)
|
||||||
|
self.modifier_selector.confirm()
|
||||||
|
return
|
||||||
if is_l_don_pressed() or is_r_don_pressed():
|
if is_l_don_pressed() or is_r_don_pressed():
|
||||||
if self.selected_difficulty == -3:
|
if self.selected_difficulty == -3:
|
||||||
self._cancel_selection()
|
self._cancel_selection()
|
||||||
elif self.selected_difficulty == -2:
|
elif self.selected_difficulty == -2:
|
||||||
pass
|
audio.play_sound(self.sound_don)
|
||||||
|
self.modifier_selector = ModifierSelector()
|
||||||
elif self.selected_difficulty == -1:
|
elif self.selected_difficulty == -1:
|
||||||
audio.play_sound(self.sound_don)
|
audio.play_sound(self.sound_don)
|
||||||
self.neiro_selector = NeiroSelector()
|
self.neiro_selector = NeiroSelector()
|
||||||
@@ -378,6 +392,11 @@ class SongSelectScreen:
|
|||||||
if self.neiro_selector.is_finished:
|
if self.neiro_selector.is_finished:
|
||||||
self.neiro_selector = None
|
self.neiro_selector = None
|
||||||
|
|
||||||
|
if self.modifier_selector is not None:
|
||||||
|
self.modifier_selector.update(get_current_ms())
|
||||||
|
if self.modifier_selector.is_finished:
|
||||||
|
self.modifier_selector = None
|
||||||
|
|
||||||
for song in self.navigator.items:
|
for song in self.navigator.items:
|
||||||
song.box.update(self.state == State.SONG_SELECTED)
|
song.box.update(self.state == State.SONG_SELECTED)
|
||||||
song.box.is_open = song.box.position == SongSelectScreen.BOX_CENTER + 150
|
song.box.is_open = song.box.position == SongSelectScreen.BOX_CENTER + 150
|
||||||
@@ -397,7 +416,7 @@ class SongSelectScreen:
|
|||||||
return self.on_screen_end('ENTRY')
|
return self.on_screen_end('ENTRY')
|
||||||
|
|
||||||
def draw_selector(self):
|
def draw_selector(self):
|
||||||
fade = 0.5 if self.neiro_selector is not None else 1.0
|
fade = 0.5 if self.neiro_selector is not None else self.text_fade_in.attribute
|
||||||
direction = 1 if self.diff_select_move_right else -1
|
direction = 1 if self.diff_select_move_right else -1
|
||||||
if self.selected_difficulty <= -1 or self.prev_diff == -1:
|
if self.selected_difficulty <= -1 or self.prev_diff == -1:
|
||||||
if self.prev_diff == -1 and self.selected_difficulty >= 0:
|
if self.prev_diff == -1 and self.selected_difficulty >= 0:
|
||||||
@@ -464,6 +483,9 @@ class SongSelectScreen:
|
|||||||
if self.neiro_selector is not None:
|
if self.neiro_selector is not None:
|
||||||
self.neiro_selector.draw()
|
self.neiro_selector.draw()
|
||||||
|
|
||||||
|
if self.modifier_selector is not None:
|
||||||
|
self.modifier_selector.draw()
|
||||||
|
|
||||||
if self.game_transition is not None:
|
if self.game_transition is not None:
|
||||||
self.game_transition.draw()
|
self.game_transition.draw()
|
||||||
|
|
||||||
@@ -839,7 +861,6 @@ class YellowBox:
|
|||||||
return
|
return
|
||||||
tex.draw_texture('diff_select', 'back', fade=self.fade_in.attribute)
|
tex.draw_texture('diff_select', 'back', fade=self.fade_in.attribute)
|
||||||
tex.draw_texture('diff_select', 'option', fade=self.fade_in.attribute)
|
tex.draw_texture('diff_select', 'option', fade=self.fade_in.attribute)
|
||||||
tex.draw_texture('diff_select', 'disable', fade=min(0.5, self.fade_in.attribute))
|
|
||||||
tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute)
|
tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute)
|
||||||
|
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
@@ -1216,6 +1237,115 @@ class NeiroSelector:
|
|||||||
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((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))
|
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:
|
||||||
|
TEX_MAP = {
|
||||||
|
"auto": "mod_auto",
|
||||||
|
"speed": "mod_baisaku",
|
||||||
|
"display": "mod_doron",
|
||||||
|
"inverse": "mod_abekobe",
|
||||||
|
"random": "mod_kimagure"
|
||||||
|
}
|
||||||
|
NAME_MAP = {
|
||||||
|
"auto": "オート",
|
||||||
|
"speed": "はやさ",
|
||||||
|
"display": "ドロン",
|
||||||
|
"inverse": "あべこべ",
|
||||||
|
"random": "ランダム"
|
||||||
|
}
|
||||||
|
def __init__(self):
|
||||||
|
self.mods = fields(Modifiers)
|
||||||
|
self.current_mod_index = 0
|
||||||
|
self.is_confirmed = False
|
||||||
|
self.is_finished = False
|
||||||
|
self.move = tex.get_animation(28)
|
||||||
|
self.move.start()
|
||||||
|
self.text = [OutlinedText(ModifierSelector.NAME_MAP[mod.name], 30, ray.WHITE, ray.BLACK, outline_thickness=3.5) for mod in self.mods]
|
||||||
|
self.text_true = OutlinedText('する', 30, ray.WHITE, ray.BLACK, outline_thickness=3.5)
|
||||||
|
self.text_false = OutlinedText('じゃない', 30, ray.WHITE, ray.BLACK, outline_thickness=3.5)
|
||||||
|
self.text_speed = OutlinedText(str(global_data.modifiers.speed), 30, ray.WHITE, ray.BLACK, outline_thickness=3.5)
|
||||||
|
|
||||||
|
def update(self, current_ms):
|
||||||
|
self.is_finished = self.is_confirmed and self.move.is_finished
|
||||||
|
if self.is_finished:
|
||||||
|
for text in self.text:
|
||||||
|
text.unload()
|
||||||
|
self.move.update(current_ms)
|
||||||
|
def confirm(self):
|
||||||
|
if self.is_confirmed:
|
||||||
|
return
|
||||||
|
self.current_mod_index += 1
|
||||||
|
if self.current_mod_index == len(self.mods):
|
||||||
|
self.is_confirmed = True
|
||||||
|
self.move.restart()
|
||||||
|
def left(self):
|
||||||
|
if self.is_confirmed:
|
||||||
|
return
|
||||||
|
current_mod = self.mods[self.current_mod_index]
|
||||||
|
current_value = getattr(global_data.modifiers, current_mod.name)
|
||||||
|
if current_mod.type is bool:
|
||||||
|
setattr(global_data.modifiers, current_mod.name, not current_value)
|
||||||
|
elif current_mod.name == 'speed':
|
||||||
|
setattr(global_data.modifiers, current_mod.name, max(0.1, current_value-0.1))
|
||||||
|
self.text_speed.unload()
|
||||||
|
self.text_speed = OutlinedText(str(global_data.modifiers.speed), 30, ray.WHITE, ray.BLACK, outline_thickness=3.5)
|
||||||
|
elif current_mod.name == 'random':
|
||||||
|
setattr(global_data.modifiers, current_mod.name, max(0, current_value-1))
|
||||||
|
def right(self):
|
||||||
|
if self.is_confirmed:
|
||||||
|
return
|
||||||
|
current_mod = self.mods[self.current_mod_index]
|
||||||
|
current_value = getattr(global_data.modifiers, current_mod.name)
|
||||||
|
if current_mod.type is bool:
|
||||||
|
setattr(global_data.modifiers, current_mod.name, not current_value)
|
||||||
|
elif current_mod.name == 'speed':
|
||||||
|
setattr(global_data.modifiers, current_mod.name, current_value+0.1)
|
||||||
|
self.text_speed.unload()
|
||||||
|
self.text_speed = OutlinedText(str(global_data.modifiers.speed), 30, ray.WHITE, ray.BLACK, outline_thickness=3.5)
|
||||||
|
elif current_mod.name == 'random':
|
||||||
|
setattr(global_data.modifiers, current_mod.name, min(2, current_value+1))
|
||||||
|
def draw(self):
|
||||||
|
if self.is_confirmed:
|
||||||
|
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))
|
||||||
|
for i in range(len(self.mods)):
|
||||||
|
tex.draw_texture('modifier', 'background', y=move + (i*50))
|
||||||
|
if i == self.current_mod_index:
|
||||||
|
tex.draw_texture('modifier', 'mod_bg_highlight', y=move + (i*50))
|
||||||
|
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[i].texture.width, self.text[i].texture.height)
|
||||||
|
self.text[i].draw(self.text[i].default_src, dest, ray.Vector2(0, 0), 0, ray.WHITE)
|
||||||
|
|
||||||
|
current_mod = self.mods[i]
|
||||||
|
current_value = getattr(global_data.modifiers, current_mod.name)
|
||||||
|
if current_mod.type is bool:
|
||||||
|
if current_value:
|
||||||
|
tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50))
|
||||||
|
dest = ray.Rectangle(330 - (self.text_true.texture.width//2), 819 + move + (i*50), self.text_true.texture.width, self.text_true.texture.height)
|
||||||
|
self.text_true.draw(self.text_true.default_src, dest, ray.Vector2(0, 0), 0, ray.WHITE)
|
||||||
|
else:
|
||||||
|
dest = ray.Rectangle(330 - (self.text_false.texture.width//2), 819 + move + (i*50), self.text_false.texture.width, self.text_false.texture.height)
|
||||||
|
self.text_false.draw(self.text_false.default_src, dest, ray.Vector2(0, 0), 0, ray.WHITE)
|
||||||
|
elif current_mod.name == 'speed':
|
||||||
|
dest = ray.Rectangle(330 - (self.text_speed.texture.width//2), 819 + move + (i*50), self.text_speed.texture.width, self.text_speed.texture.height)
|
||||||
|
self.text_speed.draw(self.text_speed.default_src, dest, ray.Vector2(0, 0), 0, ray.WHITE)add
|
||||||
|
if current_value > 1.0:
|
||||||
|
tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50))
|
||||||
|
elif current_value >= 3.0:
|
||||||
|
tex.draw_texture('modifier', 'mod_sanbai', y=move + (i*50))
|
||||||
|
elif current_value >= 4.0:
|
||||||
|
tex.draw_texture('modifier', 'mod_yonbai', y=move + (i*50))
|
||||||
|
elif current_mod.name == 'random':
|
||||||
|
if current_value == 1:
|
||||||
|
tex.draw_texture('modifier', ModifierSelector.TEX_MAP[self.mods[i].name], y=move + (i*50))
|
||||||
|
elif current_value == 2:
|
||||||
|
tex.draw_texture('modifier', 'mod_detarame', y=move + (i*50))
|
||||||
|
|
||||||
class ScoreHistory:
|
class ScoreHistory:
|
||||||
def __init__(self, scores: dict[int, tuple[int, int, int, int]], current_ms):
|
def __init__(self, scores: dict[int, tuple[int, int, int, int]], current_ms):
|
||||||
self.scores = {k: v for k, v in scores.items() if v is not None}
|
self.scores = {k: v for k, v in scores.items() if v is not None}
|
||||||
|
|||||||
Reference in New Issue
Block a user