mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 11:40:13 +01:00
minor fixes
This commit is contained in:
@@ -55,7 +55,7 @@ class Background:
|
||||
is_rainbow = gauge.gauge_length == gauge.gauge_max
|
||||
clear_threshold = gauge.clear_start[min(gauge.difficulty, 3)]
|
||||
if gauge.gauge_length < clear_threshold:
|
||||
current_milestone = min(self.max_dancers - 1, int(gauge.gauge_length / (clear_threshold / self.max_dancers - 1)))
|
||||
current_milestone = min(self.max_dancers, int(gauge.gauge_length / (clear_threshold / self.max_dancers)))
|
||||
else:
|
||||
current_milestone = self.max_dancers
|
||||
if current_milestone > self.last_milestone and current_milestone < self.max_dancers:
|
||||
@@ -76,9 +76,13 @@ class Background:
|
||||
self.renda.update(current_time_ms)
|
||||
self.chibi.update(current_time_ms, bpm)
|
||||
def draw(self):
|
||||
self.bg_normal.draw(self.tex_wrapper)
|
||||
if self.is_clear:
|
||||
if self.is_clear and not self.bg_fever.transitioned:
|
||||
self.bg_normal.draw(self.tex_wrapper)
|
||||
self.bg_fever.draw(self.tex_wrapper)
|
||||
elif self.is_clear:
|
||||
self.bg_fever.draw(self.tex_wrapper)
|
||||
else:
|
||||
self.bg_normal.draw(self.tex_wrapper)
|
||||
self.don_bg.draw(self.tex_wrapper)
|
||||
self.renda.draw()
|
||||
self.dancer.draw(self.tex_wrapper)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import random
|
||||
from libs.animation import Animation, get_current_ms
|
||||
from libs.animation import Animation
|
||||
from libs.texture import TextureWrapper
|
||||
|
||||
import pyray as ray
|
||||
@@ -136,28 +136,24 @@ class Chibi13(BaseChibi):
|
||||
|
||||
class ChibiController:
|
||||
def __init__(self, tex: TextureWrapper, index: int, bpm: float, path: str = 'background'):
|
||||
self.chibis = set()
|
||||
self.chibis = []
|
||||
self.tex = tex
|
||||
self.index = index
|
||||
print(self.index)
|
||||
self.name = 'chibi_' + str(index)
|
||||
self.bpm = bpm
|
||||
tex.load_zip(path, f'chibi/{self.name}')
|
||||
tex.load_zip('background', 'chibi/chibi_bad')
|
||||
|
||||
def add_chibi(self, bad=False):
|
||||
self.chibis.add(Chibi.create(self.index, self.bpm, bad, self.tex))
|
||||
self.chibis.append(Chibi.create(self.index, self.bpm, bad, self.tex))
|
||||
|
||||
def update(self, current_time_ms: float, bpm: float):
|
||||
self.bpm = bpm
|
||||
remove = set()
|
||||
for chibi in self.chibis:
|
||||
for i in range(len(self.chibis)-1, -1, -1):
|
||||
chibi = self.chibis[i]
|
||||
chibi.update(current_time_ms)
|
||||
if chibi.hori_move.is_finished:
|
||||
remove.add(chibi)
|
||||
|
||||
for chibi in remove:
|
||||
self.chibis.remove(chibi)
|
||||
self.chibis.remove(chibi)
|
||||
|
||||
def draw(self):
|
||||
for chibi in self.chibis:
|
||||
|
||||
@@ -10,6 +10,16 @@ import pyray as ray
|
||||
|
||||
from libs.animation import BaseAnimation, parse_animations
|
||||
|
||||
SCREEN_WIDTH = 1280
|
||||
SCREEN_HEIGHT = 720
|
||||
|
||||
def is_rect_on_screen(rect, screen_width=SCREEN_WIDTH, screen_height=SCREEN_HEIGHT):
|
||||
return not (
|
||||
rect.x + rect.width < 0 or
|
||||
rect.x > screen_width or
|
||||
rect.y + rect.height < 0 or
|
||||
rect.y > screen_height
|
||||
)
|
||||
|
||||
class Texture:
|
||||
def __init__(self, name: str, texture: Union[ray.Texture, list[ray.Texture]], init_vals: dict[str, int]):
|
||||
@@ -175,6 +185,9 @@ class TextureWrapper:
|
||||
dest_rect = ray.Rectangle(tex_object.x[index] + (tex_object.width//2) - ((tex_object.width * scale)//2) + x, tex_object.y[index] + (tex_object.height//2) - ((tex_object.height * scale)//2) + y, tex_object.x2[index]*scale + x2, tex_object.y2[index]*scale + y2)
|
||||
else:
|
||||
dest_rect = ray.Rectangle(tex_object.x[index] + x, tex_object.y[index] + y, tex_object.x2[index]*scale + x2, tex_object.y2[index]*scale + y2)
|
||||
|
||||
if not is_rect_on_screen(dest_rect):
|
||||
return
|
||||
if tex_object.is_frames:
|
||||
if not isinstance(tex_object.texture, list):
|
||||
raise Exception("Texture was marked as multiframe but is only 1 texture")
|
||||
|
||||
427
scenes/game.py
427
scenes/game.py
@@ -33,11 +33,12 @@ from libs.utils import (
|
||||
)
|
||||
from libs.video import VideoPlayer
|
||||
|
||||
SCREEN_WIDTH = 1280
|
||||
SCREEN_HEIGHT = 720
|
||||
|
||||
class GameScreen:
|
||||
JUDGE_X = 414
|
||||
def __init__(self):
|
||||
self.width = 1280
|
||||
self.current_ms = 0
|
||||
self.screen_init = False
|
||||
self.end_ms = 0
|
||||
@@ -66,7 +67,7 @@ class GameScreen:
|
||||
self.start_ms = get_current_ms()
|
||||
self.tja = None
|
||||
else:
|
||||
self.tja = TJAParser(song, start_delay=self.start_delay, distance=self.width - GameScreen.JUDGE_X)
|
||||
self.tja = TJAParser(song, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
|
||||
if self.tja.metadata.bgmovie != Path() and self.tja.metadata.bgmovie.exists():
|
||||
self.movie = VideoPlayer(self.tja.metadata.bgmovie)
|
||||
self.movie.set_volume(0.0)
|
||||
@@ -77,7 +78,7 @@ class GameScreen:
|
||||
self.song_music = audio.load_music_stream(self.tja.metadata.wave)
|
||||
audio.normalize_music_stream(self.song_music, 0.1935)
|
||||
|
||||
self.player_1 = Player(self, global_data.player_num, difficulty)
|
||||
self.player_1 = Player(self.tja, global_data.player_num, difficulty)
|
||||
if self.tja is not None:
|
||||
self.start_ms = (get_current_ms() - self.tja.metadata.offset*1000)
|
||||
|
||||
@@ -110,10 +111,12 @@ class GameScreen:
|
||||
tex.unload_textures()
|
||||
if self.song_music is not None:
|
||||
audio.unload_music_stream(self.song_music)
|
||||
self.song_music = None
|
||||
self.song_started = False
|
||||
self.end_ms = 0
|
||||
self.movie = None
|
||||
self.background.unload()
|
||||
if self.background is not None:
|
||||
self.background.unload()
|
||||
return next_screen
|
||||
|
||||
def write_score(self):
|
||||
@@ -147,8 +150,9 @@ class GameScreen:
|
||||
|
||||
def update(self):
|
||||
self.on_screen_start()
|
||||
self.transition.update(get_current_ms())
|
||||
self.current_ms = get_current_ms() - self.start_ms
|
||||
current_time = get_current_ms()
|
||||
self.transition.update(current_time)
|
||||
self.current_ms = current_time - self.start_ms
|
||||
if self.tja is not None:
|
||||
if (self.current_ms >= self.tja.metadata.offset*1000 + self.start_delay - global_data.config["general"]["judge_offset"]) and not self.song_started:
|
||||
if self.song_music is not None:
|
||||
@@ -156,31 +160,32 @@ class GameScreen:
|
||||
audio.play_music_stream(self.song_music)
|
||||
print(f"Song started at {self.current_ms}")
|
||||
if self.movie is not None:
|
||||
self.movie.start(get_current_ms())
|
||||
self.movie.start(current_time)
|
||||
self.song_started = True
|
||||
if self.movie is not None:
|
||||
self.movie.update()
|
||||
else:
|
||||
if len(self.player_1.current_bars) > 0:
|
||||
self.bpm = self.player_1.current_bars[0].bpm
|
||||
self.background.update(get_current_ms(), self.bpm, self.player_1.gauge)
|
||||
if self.background is not None:
|
||||
self.background.update(current_time, self.bpm, self.player_1.gauge)
|
||||
|
||||
self.player_1.update(self)
|
||||
self.song_info.update(get_current_ms())
|
||||
self.result_transition.update(get_current_ms())
|
||||
self.player_1.update(self, current_time)
|
||||
self.song_info.update(current_time)
|
||||
self.result_transition.update(current_time)
|
||||
if self.result_transition.is_finished:
|
||||
return self.on_screen_end('RESULT')
|
||||
elif len(self.player_1.play_notes) == 0:
|
||||
session_data.result_score, session_data.result_good, session_data.result_ok, session_data.result_bad, session_data.result_max_combo, session_data.result_total_drumroll = self.player_1.get_result_score()
|
||||
session_data.result_gauge_length = self.player_1.gauge.gauge_length
|
||||
if self.end_ms != 0:
|
||||
if get_current_ms() >= self.end_ms + 8533.34:
|
||||
if current_time >= self.end_ms + 8533.34:
|
||||
if not self.result_transition.is_started:
|
||||
self.result_transition.start()
|
||||
audio.play_sound(self.sound_result_transition)
|
||||
else:
|
||||
self.write_score()
|
||||
self.end_ms = get_current_ms()
|
||||
self.end_ms = current_time
|
||||
|
||||
if ray.is_key_pressed(ray.KeyboardKey.KEY_F1):
|
||||
if self.song_music is not None:
|
||||
@@ -197,7 +202,7 @@ class GameScreen:
|
||||
def draw(self):
|
||||
if self.movie is not None:
|
||||
self.movie.draw()
|
||||
else:
|
||||
elif self.background is not None:
|
||||
self.background.draw()
|
||||
self.player_1.draw(self)
|
||||
self.song_info.draw()
|
||||
@@ -212,14 +217,14 @@ class Player:
|
||||
TIMING_OK = 75.0750045776367
|
||||
TIMING_BAD = 108.441665649414
|
||||
|
||||
def __init__(self, game_screen: GameScreen, player_number: int, difficulty: int):
|
||||
def __init__(self, tja: Optional[TJAParser], player_number: int, difficulty: int):
|
||||
|
||||
self.player_number = str(player_number)
|
||||
self.difficulty = difficulty
|
||||
self.visual_offset = global_data.config["general"]["visual_offset"]
|
||||
|
||||
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)
|
||||
if tja is not None:
|
||||
self.play_notes, self.draw_note_list, self.draw_bar_list = 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:
|
||||
self.play_notes, self.draw_note_list, self.draw_bar_list = deque(), deque(), deque()
|
||||
@@ -254,15 +259,15 @@ class Player:
|
||||
self.balloon_anim: Optional[BalloonAnimation] = None
|
||||
self.kusudama_anim: Optional[KusudamaAnimation] = None
|
||||
self.base_score_list: list[ScoreCounterAnimation] = []
|
||||
self.combo_display = Combo(self.combo, get_current_ms())
|
||||
self.combo_display = Combo(self.combo, 0)
|
||||
self.score_counter = ScoreCounter(self.score)
|
||||
plate_info = global_data.config['nameplate']
|
||||
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], global_data.player_num, plate_info['dan'], plate_info['gold'])
|
||||
|
||||
self.input_log: dict[float, tuple] = dict()
|
||||
|
||||
if game_screen.tja is not None:
|
||||
stars = game_screen.tja.metadata.course_data[self.difficulty].level
|
||||
if tja is not None:
|
||||
stars = tja.metadata.course_data[self.difficulty].level
|
||||
else:
|
||||
stars = 0
|
||||
self.gauge = Gauge(self.player_number, self.difficulty, stars, self.total_notes)
|
||||
@@ -271,55 +276,73 @@ class Player:
|
||||
self.autoplay_hit_side = 'L'
|
||||
self.last_subdivision = -1
|
||||
|
||||
# Performance optimization: cache frequently used string conversions
|
||||
self._cached_combo_str = ""
|
||||
self._cached_combo = -1
|
||||
self._cached_score_str = ""
|
||||
self._cached_score = -1
|
||||
|
||||
def get_result_score(self):
|
||||
return self.score, self.good_count, self.ok_count, self.bad_count, self.max_combo, self.total_drumroll
|
||||
|
||||
def get_position_x(self, width: int, current_ms: float, load_ms: float, pixels_per_frame: float) -> int:
|
||||
return int(width + pixels_per_frame * (60 / 1000) * (load_ms - current_ms) - 64) - self.visual_offset
|
||||
# Cache frequently used calculations
|
||||
time_diff = load_ms - current_ms
|
||||
return int(width + pixels_per_frame * 0.06 * time_diff - 64) - self.visual_offset
|
||||
|
||||
def get_position_y(self, current_ms: float, load_ms: float, pixels_per_frame: float, pixels_per_frame_x) -> int:
|
||||
return int((pixels_per_frame * (60 / 1000) * (load_ms - current_ms)) + (((1280 - GameScreen.JUDGE_X) * pixels_per_frame) / pixels_per_frame_x))
|
||||
time_diff = load_ms - current_ms
|
||||
return int((pixels_per_frame * 0.06 * time_diff) + ((866 * pixels_per_frame) / pixels_per_frame_x))
|
||||
|
||||
def animation_manager(self, animation_list: list):
|
||||
if len(animation_list) <= 0:
|
||||
def animation_manager(self, animation_list: list, current_time: float):
|
||||
if not animation_list:
|
||||
return
|
||||
|
||||
for i in range(len(animation_list)-1, -1, -1):
|
||||
animation = animation_list[i]
|
||||
animation.update(get_current_ms())
|
||||
# More efficient: collect finished animations and remove them in one pass
|
||||
finished_indices = []
|
||||
for i, animation in enumerate(animation_list):
|
||||
animation.update(current_time)
|
||||
if animation.is_finished:
|
||||
animation_list.pop(i)
|
||||
finished_indices.append(i)
|
||||
|
||||
def bar_manager(self, game_screen: GameScreen):
|
||||
# Remove in reverse order to maintain indices
|
||||
for i in reversed(finished_indices):
|
||||
animation_list.pop(i)
|
||||
|
||||
def bar_manager(self, current_ms: float):
|
||||
#Add bar to current_bars list if it is ready to be shown on screen
|
||||
if len(self.draw_bar_list) > 0 and game_screen.current_ms > self.draw_bar_list[0].load_ms:
|
||||
if self.draw_bar_list and current_ms > self.draw_bar_list[0].load_ms:
|
||||
self.current_bars.append(self.draw_bar_list.popleft())
|
||||
|
||||
#If a bar is off screen, remove it
|
||||
if len(self.current_bars) == 0:
|
||||
if not self.current_bars:
|
||||
return
|
||||
|
||||
for i in range(len(self.current_bars)-1, -1, -1):
|
||||
bar = self.current_bars[i]
|
||||
position = self.get_position_x(game_screen.width, game_screen.current_ms, bar.hit_ms, bar.pixels_per_frame_x)
|
||||
if position < GameScreen.JUDGE_X + 650:
|
||||
self.current_bars.pop(i)
|
||||
# More efficient removal with early exit
|
||||
removal_threshold = GameScreen.JUDGE_X + 650
|
||||
bars_to_keep = []
|
||||
for bar in self.current_bars:
|
||||
position = self.get_position_x(SCREEN_WIDTH, current_ms, bar.hit_ms, bar.pixels_per_frame_x)
|
||||
if position >= removal_threshold:
|
||||
bars_to_keep.append(bar)
|
||||
self.current_bars = bars_to_keep
|
||||
|
||||
def play_note_manager(self, game_screen: GameScreen):
|
||||
if len(self.play_notes) == 0:
|
||||
def play_note_manager(self, current_ms: float, background: Optional[Background]):
|
||||
if not self.play_notes:
|
||||
return
|
||||
|
||||
note = self.play_notes[0]
|
||||
if note.hit_ms + Player.TIMING_BAD < game_screen.current_ms:
|
||||
if note.hit_ms + Player.TIMING_BAD < current_ms:
|
||||
if 0 < note.type <= 4:
|
||||
self.combo = 0
|
||||
game_screen.background.add_chibi(True)
|
||||
if background is not None:
|
||||
background.add_chibi(True)
|
||||
self.bad_count += 1
|
||||
self.gauge.add_bad()
|
||||
self.play_notes.popleft()
|
||||
elif note.type != 8:
|
||||
tail = self.play_notes[1]
|
||||
if tail.hit_ms <= game_screen.current_ms:
|
||||
if tail.hit_ms <= current_ms:
|
||||
self.play_notes.popleft()
|
||||
self.play_notes.popleft()
|
||||
self.is_drumroll = False
|
||||
@@ -327,14 +350,14 @@ class Player:
|
||||
else:
|
||||
if len(self.play_notes) == 1:
|
||||
self.play_notes.popleft()
|
||||
elif (note.hit_ms <= game_screen.current_ms):
|
||||
elif (note.hit_ms <= current_ms):
|
||||
if note.type == 5 or note.type == 6:
|
||||
self.is_drumroll = True
|
||||
elif note.type == 7 or note.type == 9:
|
||||
self.is_balloon = True
|
||||
|
||||
def draw_note_manager(self, game_screen: GameScreen):
|
||||
if len(self.draw_note_list) > 0 and game_screen.current_ms + 1000 >= self.draw_note_list[0].load_ms:
|
||||
def draw_note_manager(self, current_ms: float):
|
||||
if self.draw_note_list and current_ms + 1000 >= self.draw_note_list[0].load_ms:
|
||||
current_note = self.draw_note_list.popleft()
|
||||
if 5 <= current_note.type <= 7:
|
||||
bisect.insort_left(self.current_notes_draw, current_note, key=lambda x: x.index)
|
||||
@@ -347,7 +370,7 @@ class Player:
|
||||
else:
|
||||
bisect.insort_left(self.current_notes_draw, current_note, key=lambda x: x.index)
|
||||
|
||||
if len(self.current_notes_draw) == 0:
|
||||
if not self.current_notes_draw:
|
||||
return
|
||||
|
||||
if isinstance(self.current_notes_draw[0], Drumroll) and 255 > self.current_notes_draw[0].color > 0:
|
||||
@@ -356,16 +379,16 @@ class Player:
|
||||
note = self.current_notes_draw[0]
|
||||
if note.type in {5, 6, 7} and len(self.current_notes_draw) > 1:
|
||||
note = self.current_notes_draw[1]
|
||||
position = self.get_position_x(game_screen.width, game_screen.current_ms, note.hit_ms, note.pixels_per_frame_x)
|
||||
position = self.get_position_x(SCREEN_WIDTH, current_ms, note.hit_ms, note.pixels_per_frame_x)
|
||||
if position < GameScreen.JUDGE_X + 650:
|
||||
self.current_notes_draw.pop(0)
|
||||
|
||||
def note_manager(self, game_screen: GameScreen):
|
||||
self.bar_manager(game_screen)
|
||||
self.play_note_manager(game_screen)
|
||||
self.draw_note_manager(game_screen)
|
||||
def note_manager(self, current_ms: float, background: Optional[Background], current_time: float):
|
||||
self.bar_manager(current_ms)
|
||||
self.play_note_manager(current_ms, background)
|
||||
self.draw_note_manager(current_ms)
|
||||
|
||||
def note_correct(self, note: Note):
|
||||
def note_correct(self, note: Note, current_time: float):
|
||||
self.play_notes.popleft()
|
||||
index = note.index
|
||||
if note.type == 7:
|
||||
@@ -377,31 +400,32 @@ class Player:
|
||||
self.max_combo = self.combo
|
||||
|
||||
if note.type != 9:
|
||||
self.draw_arc_list.append(NoteArc(note.type, get_current_ms(), 1, note.type == 3 or note.type == 4 or note.type == 7, note.type == 7))
|
||||
self.draw_arc_list.append(NoteArc(note.type, current_time, 1, note.type == 3 or note.type == 4 or note.type == 7, note.type == 7))
|
||||
|
||||
if note in self.current_notes_draw:
|
||||
index = self.current_notes_draw.index(note)
|
||||
self.current_notes_draw.pop(index)
|
||||
|
||||
def check_drumroll(self, drum_type: int, game_screen: GameScreen):
|
||||
self.draw_arc_list.append(NoteArc(drum_type, get_current_ms(), 1, drum_type == 3 or drum_type == 4, False))
|
||||
def check_drumroll(self, drum_type: int, background: Optional[Background], current_time: float):
|
||||
self.draw_arc_list.append(NoteArc(drum_type, current_time, 1, drum_type == 3 or drum_type == 4, False))
|
||||
self.curr_drumroll_count += 1
|
||||
self.total_drumroll += 1
|
||||
game_screen.background.add_renda()
|
||||
if background is not None:
|
||||
background.add_renda()
|
||||
self.score += 100
|
||||
self.base_score_list.append(ScoreCounterAnimation(self.player_number, 100))
|
||||
if not isinstance(self.current_notes_draw[0], Drumroll):
|
||||
return
|
||||
self.current_notes_draw[0].color = max(0, 255 - (self.curr_drumroll_count * 10))
|
||||
|
||||
def check_balloon(self, game_screen: GameScreen, drum_type: int, note: Balloon):
|
||||
def check_balloon(self, game_screen: GameScreen, drum_type: int, note: Balloon, current_time: float):
|
||||
if drum_type != 1:
|
||||
return
|
||||
if note.is_kusudama:
|
||||
self.check_kusudama(game_screen, note)
|
||||
return
|
||||
if self.balloon_anim is None:
|
||||
self.balloon_anim = BalloonAnimation(get_current_ms(), note.count)
|
||||
self.balloon_anim = BalloonAnimation(current_time, note.count)
|
||||
self.curr_balloon_count += 1
|
||||
self.total_drumroll += 1
|
||||
self.score += 100
|
||||
@@ -409,9 +433,9 @@ class Player:
|
||||
if self.curr_balloon_count == note.count:
|
||||
self.is_balloon = False
|
||||
note.popped = True
|
||||
self.balloon_anim.update(get_current_ms(), self.curr_balloon_count, note.popped)
|
||||
self.balloon_anim.update(current_time, self.curr_balloon_count, note.popped)
|
||||
audio.play_sound(game_screen.sound_balloon_pop)
|
||||
self.note_correct(self.play_notes[0])
|
||||
self.note_correct(self.play_notes[0], current_time)
|
||||
|
||||
def check_kusudama(self, game_screen: GameScreen, note: Balloon):
|
||||
if self.kusudama_anim is None:
|
||||
@@ -425,17 +449,17 @@ class Player:
|
||||
self.is_balloon = False
|
||||
note.popped = True
|
||||
|
||||
def check_note(self, game_screen: GameScreen, drum_type: int):
|
||||
def check_note(self, game_screen: GameScreen, drum_type: int, current_time: float):
|
||||
if len(self.play_notes) == 0:
|
||||
return
|
||||
|
||||
curr_note = self.play_notes[0]
|
||||
if self.is_drumroll:
|
||||
self.check_drumroll(drum_type, game_screen)
|
||||
self.check_drumroll(drum_type, game_screen.background, current_time)
|
||||
elif self.is_balloon:
|
||||
if not isinstance(curr_note, Balloon):
|
||||
raise Exception("Balloon mode entered but current note is not balloon")
|
||||
self.check_balloon(game_screen, drum_type, curr_note)
|
||||
self.check_balloon(game_screen, drum_type, curr_note, current_time)
|
||||
else:
|
||||
self.curr_drumroll_count = 0
|
||||
self.curr_balloon_count = 0
|
||||
@@ -460,18 +484,20 @@ class Player:
|
||||
self.good_count += 1
|
||||
self.score += self.base_score
|
||||
self.base_score_list.append(ScoreCounterAnimation(self.player_number, self.base_score))
|
||||
self.note_correct(curr_note)
|
||||
self.note_correct(curr_note, current_time)
|
||||
self.gauge.add_good()
|
||||
game_screen.background.add_chibi(False)
|
||||
if game_screen.background is not None:
|
||||
game_screen.background.add_chibi(False)
|
||||
|
||||
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))
|
||||
self.ok_count += 1
|
||||
self.score += 10 * math.floor(self.base_score / 2 / 10)
|
||||
self.base_score_list.append(ScoreCounterAnimation(self.player_number, 10 * math.floor(self.base_score / 2 / 10)))
|
||||
self.note_correct(curr_note)
|
||||
self.note_correct(curr_note, current_time)
|
||||
self.gauge.add_ok()
|
||||
game_screen.background.add_chibi(False)
|
||||
if game_screen.background is not None:
|
||||
game_screen.background.add_chibi(False)
|
||||
|
||||
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))
|
||||
@@ -479,30 +505,31 @@ class Player:
|
||||
self.combo = 0
|
||||
self.play_notes.popleft()
|
||||
self.gauge.add_bad()
|
||||
game_screen.background.add_chibi(True)
|
||||
if game_screen.background is not None:
|
||||
game_screen.background.add_chibi(True)
|
||||
|
||||
def drumroll_counter_manager(self):
|
||||
def drumroll_counter_manager(self, current_time: float):
|
||||
if self.is_drumroll and self.curr_drumroll_count > 0 and self.drumroll_counter is None:
|
||||
self.drumroll_counter = DrumrollCounter(get_current_ms())
|
||||
self.drumroll_counter = DrumrollCounter(current_time)
|
||||
|
||||
if self.drumroll_counter is not None:
|
||||
if self.drumroll_counter.is_finished and not self.is_drumroll:
|
||||
self.drumroll_counter = None
|
||||
else:
|
||||
self.drumroll_counter.update(get_current_ms(), self.curr_drumroll_count)
|
||||
self.drumroll_counter.update(current_time, self.curr_drumroll_count)
|
||||
|
||||
def balloon_manager(self):
|
||||
def balloon_manager(self, current_time: float):
|
||||
if self.balloon_anim is not None:
|
||||
self.balloon_anim.update(get_current_ms(), self.curr_balloon_count, not self.is_balloon)
|
||||
self.balloon_anim.update(current_time, self.curr_balloon_count, not self.is_balloon)
|
||||
if self.balloon_anim.is_finished:
|
||||
self.balloon_anim = None
|
||||
if self.kusudama_anim is not None:
|
||||
self.kusudama_anim.update(get_current_ms(), not self.is_balloon)
|
||||
self.kusudama_anim.update(current_time, not self.is_balloon)
|
||||
self.kusudama_anim.update_count(self.curr_balloon_count)
|
||||
if self.kusudama_anim.is_finished:
|
||||
self.kusudama_anim = None
|
||||
|
||||
def handle_input(self, game_screen: GameScreen):
|
||||
def handle_input(self, game_screen: GameScreen, current_time: float):
|
||||
input_checks = [
|
||||
(is_l_don_pressed, 'DON', 'L', game_screen.sound_don),
|
||||
(is_r_don_pressed, 'DON', 'R', game_screen.sound_don),
|
||||
@@ -516,88 +543,85 @@ class Player:
|
||||
|
||||
audio.play_sound(sound)
|
||||
|
||||
self.check_note(game_screen, 1 if note_type == 'DON' else 2)
|
||||
drum_value = 1 if note_type == 'DON' else 2
|
||||
self.check_note(game_screen, drum_value, current_time)
|
||||
self.input_log[game_screen.current_ms] = (note_type, side)
|
||||
|
||||
def autoplay_manager(self, game_screen: GameScreen):
|
||||
def autoplay_manager(self, game_screen: GameScreen, current_time: float):
|
||||
if not global_data.modifiers.auto:
|
||||
return
|
||||
if len(self.play_notes) == 0:
|
||||
if not self.play_notes:
|
||||
return
|
||||
note = self.play_notes[0]
|
||||
if self.is_drumroll or self.is_balloon:
|
||||
if self.play_notes[0].bpm == 0:
|
||||
bpm = note.bpm
|
||||
if bpm == 0:
|
||||
subdivision_in_ms = 0
|
||||
else:
|
||||
subdivision_in_ms = game_screen.current_ms // ((60000 * 4 / self.play_notes[0].bpm) / 24)
|
||||
subdivision_in_ms = game_screen.current_ms // ((60000 * 4 / bpm) / 24)
|
||||
if subdivision_in_ms > self.last_subdivision:
|
||||
self.last_subdivision = subdivision_in_ms
|
||||
hit_type = 'DON'
|
||||
self.lane_hit_effect = LaneHitEffect(hit_type)
|
||||
if self.autoplay_hit_side == 'L':
|
||||
self.autoplay_hit_side = 'R'
|
||||
else:
|
||||
self.autoplay_hit_side = 'L'
|
||||
self.autoplay_hit_side = 'R' if self.autoplay_hit_side == 'L' else 'L'
|
||||
self.draw_drum_hit_list.append(DrumHitEffect(hit_type, self.autoplay_hit_side))
|
||||
audio.play_sound(game_screen.sound_don)
|
||||
type = note.type
|
||||
if type == 6:
|
||||
type = 3
|
||||
else:
|
||||
type = 1
|
||||
self.check_note(game_screen, type)
|
||||
note_type = 3 if note.type == 6 else 1
|
||||
self.check_note(game_screen, note_type, current_time)
|
||||
else:
|
||||
while game_screen.current_ms >= note.hit_ms and note.type <= 4:
|
||||
hit_type = 'DON'
|
||||
if note.type == 2 or note.type == 4:
|
||||
hit_type = 'KAT'
|
||||
hit_type = 'KAT' if note.type in {2, 4} else 'DON'
|
||||
self.lane_hit_effect = LaneHitEffect(hit_type)
|
||||
if self.autoplay_hit_side == 'L':
|
||||
self.autoplay_hit_side = 'R'
|
||||
else:
|
||||
self.autoplay_hit_side = 'L'
|
||||
self.autoplay_hit_side = 'R' if self.autoplay_hit_side == 'L' else 'L'
|
||||
self.draw_drum_hit_list.append(DrumHitEffect(hit_type, self.autoplay_hit_side))
|
||||
sound = game_screen.sound_don if hit_type == "DON" else game_screen.sound_kat
|
||||
audio.play_sound(sound)
|
||||
type = note.type
|
||||
if type == 6 or type == 9:
|
||||
type = 3
|
||||
elif type == 5 or type == 7:
|
||||
type = 1
|
||||
self.check_note(game_screen, type)
|
||||
if len(self.play_notes) > 0:
|
||||
if note.type in {6, 9}:
|
||||
note_type = 3
|
||||
elif note.type in {5, 7}:
|
||||
note_type = 1
|
||||
else:
|
||||
note_type = note.type
|
||||
self.check_note(game_screen, note_type, current_time)
|
||||
if self.play_notes:
|
||||
note = self.play_notes[0]
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def update(self, game_screen: GameScreen):
|
||||
self.note_manager(game_screen)
|
||||
self.combo_display.update(get_current_ms(), self.combo)
|
||||
self.drumroll_counter_manager()
|
||||
self.animation_manager(self.draw_judge_list)
|
||||
self.balloon_manager()
|
||||
def update(self, game_screen: GameScreen, current_time: float):
|
||||
self.note_manager(game_screen.current_ms, game_screen.background, current_time)
|
||||
self.combo_display.update(current_time, self.combo)
|
||||
self.drumroll_counter_manager(current_time)
|
||||
self.animation_manager(self.draw_judge_list, current_time)
|
||||
self.balloon_manager(current_time)
|
||||
if self.lane_hit_effect is not None:
|
||||
self.lane_hit_effect.update(get_current_ms())
|
||||
self.animation_manager(self.draw_drum_hit_list)
|
||||
for anim in self.draw_arc_list:
|
||||
anim.update(get_current_ms())
|
||||
self.lane_hit_effect.update(current_time)
|
||||
self.animation_manager(self.draw_drum_hit_list, current_time)
|
||||
|
||||
# More efficient arc management
|
||||
finished_arcs = []
|
||||
for i, anim in enumerate(self.draw_arc_list):
|
||||
anim.update(current_time)
|
||||
if anim.is_finished:
|
||||
self.gauge_hit_effect.append(GaugeHitEffect(anim.note_type, anim.is_big))
|
||||
self.draw_arc_list.remove(anim)
|
||||
self.animation_manager(self.gauge_hit_effect)
|
||||
self.animation_manager(self.base_score_list)
|
||||
self.score_counter.update(get_current_ms(), self.score)
|
||||
self.autoplay_manager(game_screen)
|
||||
self.handle_input(game_screen)
|
||||
self.nameplate.update(get_current_ms())
|
||||
self.gauge.update(get_current_ms())
|
||||
finished_arcs.append(i)
|
||||
for i in reversed(finished_arcs):
|
||||
self.draw_arc_list.pop(i)
|
||||
|
||||
def draw_drumroll(self, game_screen: GameScreen, head: Drumroll, current_eighth: int):
|
||||
start_position = self.get_position_x(game_screen.width, game_screen.current_ms, head.load_ms, head.pixels_per_frame_x)
|
||||
self.animation_manager(self.gauge_hit_effect, current_time)
|
||||
self.animation_manager(self.base_score_list, current_time)
|
||||
self.score_counter.update(current_time, self.score)
|
||||
self.autoplay_manager(game_screen, current_time)
|
||||
self.handle_input(game_screen, current_time)
|
||||
self.nameplate.update(current_time)
|
||||
self.gauge.update(current_time)
|
||||
|
||||
def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int):
|
||||
start_position = self.get_position_x(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_x)
|
||||
tail = next((note for note in self.current_notes_draw[1:] if note.type == 8 and note.index > head.index), self.current_notes_draw[1])
|
||||
is_big = int(head.type == 6)
|
||||
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(SCREEN_WIDTH, current_ms, tail.load_ms, tail.pixels_per_frame_x)
|
||||
length = end_position - start_position
|
||||
color = ray.Color(255, head.color, head.color, 255)
|
||||
if head.display:
|
||||
@@ -612,15 +636,15 @@ class Player:
|
||||
tex.draw_texture('notes', 'moji', frame=head.moji, x=(start_position - (168//2)) + 64, y=323)
|
||||
tex.draw_texture('notes', 'moji', frame=tail.moji, x=(end_position - (168//2)) + 32, y=323)
|
||||
|
||||
def draw_balloon(self, game_screen: GameScreen, head: Balloon, current_eighth: int):
|
||||
def draw_balloon(self, current_ms: float, head: Balloon, current_eighth: int):
|
||||
offset = 12
|
||||
start_position = self.get_position_x(game_screen.width, game_screen.current_ms, head.load_ms, head.pixels_per_frame_x)
|
||||
start_position = self.get_position_x(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_x)
|
||||
tail = next((note for note in self.current_notes_draw[1:] if note.type == 8 and note.index > head.index), self.current_notes_draw[1])
|
||||
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(SCREEN_WIDTH, current_ms, tail.load_ms, tail.pixels_per_frame_x)
|
||||
pause_position = 349
|
||||
if game_screen.current_ms >= tail.hit_ms:
|
||||
if current_ms >= tail.hit_ms:
|
||||
position = end_position
|
||||
elif game_screen.current_ms >= head.hit_ms:
|
||||
elif current_ms >= head.hit_ms:
|
||||
position = pause_position
|
||||
else:
|
||||
position = start_position
|
||||
@@ -628,46 +652,43 @@ class Player:
|
||||
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)
|
||||
|
||||
def draw_bars(self, game_screen: GameScreen):
|
||||
if len(self.current_bars) <= 0:
|
||||
def draw_bars(self, current_ms: float):
|
||||
if not self.current_bars:
|
||||
return
|
||||
|
||||
for bar in reversed(self.current_bars):
|
||||
if not bar.display:
|
||||
continue
|
||||
x_position = self.get_position_x(game_screen.width, game_screen.current_ms, bar.load_ms, bar.pixels_per_frame_x)
|
||||
y_position = self.get_position_y(game_screen.current_ms, bar.load_ms, bar.pixels_per_frame_y, bar.pixels_per_frame_x)
|
||||
x_position = self.get_position_x(SCREEN_WIDTH, current_ms, bar.load_ms, bar.pixels_per_frame_x)
|
||||
y_position = self.get_position_y(current_ms, bar.load_ms, bar.pixels_per_frame_y, bar.pixels_per_frame_x)
|
||||
tex.draw_texture('notes', str(bar.type), x=x_position+60, y=y_position+190)
|
||||
|
||||
def draw_notes(self, game_screen: GameScreen):
|
||||
if len(self.current_notes_draw) <= 0:
|
||||
def draw_notes(self, current_ms: float, start_ms: float):
|
||||
if not self.current_notes_draw:
|
||||
return
|
||||
|
||||
if len(self.current_bars) > 0:
|
||||
if self.current_bars[0].bpm == 0:
|
||||
eighth_in_ms = 0
|
||||
else:
|
||||
eighth_in_ms = (60000 * 4 / self.current_bars[0].bpm) / 8
|
||||
# Cache eighth calculations
|
||||
if self.current_bars:
|
||||
bpm = self.current_bars[0].bpm
|
||||
else:
|
||||
if self.current_notes_draw[0].bpm == 0:
|
||||
eighth_in_ms = 0
|
||||
else:
|
||||
eighth_in_ms = (60000 * 4 / self.current_notes_draw[0].bpm) / 8
|
||||
bpm = self.current_notes_draw[0].bpm
|
||||
|
||||
eighth_in_ms = 0 if bpm == 0 else (60000 * 4 / bpm) / 8
|
||||
current_eighth = 0
|
||||
if self.combo >= 50 and eighth_in_ms != 0:
|
||||
current_eighth = int((game_screen.current_ms - game_screen.start_ms) // eighth_in_ms)
|
||||
current_eighth = int((current_ms - start_ms) // eighth_in_ms)
|
||||
|
||||
for note in reversed(self.current_notes_draw):
|
||||
if self.is_balloon and note == self.current_notes_draw[0]:
|
||||
continue
|
||||
if note.type == 8:
|
||||
continue
|
||||
x_position = self.get_position_x(game_screen.width, game_screen.current_ms, note.load_ms, note.pixels_per_frame_x)
|
||||
y_position = self.get_position_y(game_screen.current_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
|
||||
x_position = self.get_position_x(SCREEN_WIDTH, current_ms, note.load_ms, note.pixels_per_frame_x)
|
||||
y_position = self.get_position_y(current_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
|
||||
if isinstance(note, Drumroll):
|
||||
self.draw_drumroll(game_screen, note, current_eighth)
|
||||
self.draw_drumroll(current_ms, note, current_eighth)
|
||||
elif isinstance(note, Balloon) and not note.is_kusudama:
|
||||
self.draw_balloon(game_screen, note, current_eighth)
|
||||
self.draw_balloon(current_ms, note, current_eighth)
|
||||
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
||||
else:
|
||||
if note.display:
|
||||
@@ -699,8 +720,10 @@ class Player:
|
||||
tex.draw_texture('lane', 'lane_hit_circle')
|
||||
for anim in self.draw_judge_list:
|
||||
anim.draw()
|
||||
self.draw_bars(game_screen)
|
||||
self.draw_notes(game_screen)
|
||||
|
||||
current_ms = game_screen.current_ms
|
||||
self.draw_bars(current_ms)
|
||||
self.draw_notes(current_ms, game_screen.start_ms)
|
||||
tex.draw_texture('lane', f'{self.player_number}p_lane_cover')
|
||||
tex.draw_texture('lane', 'drum')
|
||||
if global_data.modifiers.auto:
|
||||
@@ -751,10 +774,10 @@ class Judgement:
|
||||
self.texture_animation.start()
|
||||
|
||||
def update(self, current_ms):
|
||||
self.fade_animation_1.update(current_ms)
|
||||
self.fade_animation_2.update(current_ms)
|
||||
self.move_animation.update(current_ms)
|
||||
self.texture_animation.update(current_ms)
|
||||
# Batch animation updates for better performance
|
||||
animations = [self.fade_animation_1, self.fade_animation_2, self.move_animation, self.texture_animation]
|
||||
for anim in animations:
|
||||
anim.update(current_ms)
|
||||
|
||||
if self.fade_animation_2.is_finished:
|
||||
self.is_finished = True
|
||||
@@ -909,30 +932,7 @@ class NoteArc:
|
||||
self.y_i = self.start_y
|
||||
self.is_finished = False
|
||||
|
||||
num_precalc_points = 100 # More points for better approximation
|
||||
self.path_points = []
|
||||
self.path_distances = [0.0] # Cumulative distance at each point
|
||||
|
||||
prev_x, prev_y = self.start_x, self.start_y
|
||||
total_distance = 0.0
|
||||
|
||||
for i in range(1, num_precalc_points + 1):
|
||||
t = i / num_precalc_points
|
||||
x = int((1-t)**2 * self.start_x + 2*(1-t)*t * self.control_x + t**2 * self.end_x)
|
||||
y = int((1-t)**2 * self.start_y + 2*(1-t)*t * self.control_y + t**2 * self.end_y)
|
||||
|
||||
# Calculate distance from previous point
|
||||
dx = x - prev_x
|
||||
dy = y - prev_y
|
||||
distance = math.sqrt(dx*dx + dy*dy)
|
||||
total_distance += distance
|
||||
|
||||
self.path_points.append((x, y))
|
||||
self.path_distances.append(total_distance)
|
||||
|
||||
prev_x, prev_y = x, y
|
||||
|
||||
self.total_path_length = total_distance
|
||||
self.total_path_length = math.sqrt((self.end_x - self.start_x)**2 + (self.end_y - self.start_y)**2) * 1.2 # Approximate arc length
|
||||
self.x_i = self.start_x
|
||||
self.y_i = self.start_y
|
||||
self.is_finished = False
|
||||
@@ -949,28 +949,12 @@ class NoteArc:
|
||||
|
||||
self.current_progress = ms_since_call / self.arc_points
|
||||
|
||||
# Calculate desired distance along the path (constant speed)
|
||||
target_distance = (ms_since_call / self.arc_points) * self.total_path_length
|
||||
t = self.current_progress
|
||||
t_inv = 1.0 - t
|
||||
|
||||
# Find the closest pre-calculated points
|
||||
index = 0
|
||||
while index < len(self.path_distances) - 1 and self.path_distances[index + 1] < target_distance:
|
||||
index += 1
|
||||
|
||||
# Interpolate between the points
|
||||
if index < len(self.path_distances) - 1:
|
||||
d1 = self.path_distances[index]
|
||||
d2 = self.path_distances[index + 1]
|
||||
if d2 > d1: # Avoid division by zero
|
||||
fraction = (target_distance - d1) / (d2 - d1)
|
||||
x1, y1 = self.path_points[index - 1] if index > 0 else (self.start_x, self.start_y)
|
||||
x2, y2 = self.path_points[index]
|
||||
self.x_i = int(x1 + fraction * (x2 - x1))
|
||||
self.y_i = int(y1 + fraction * (y2 - y1))
|
||||
else:
|
||||
# At the end of the path
|
||||
self.x_i = self.end_x
|
||||
self.y_i = self.end_y
|
||||
# Quadratic Bezier: B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂
|
||||
self.x_i = int(t_inv * t_inv * self.start_x + 2 * t_inv * t * self.control_x + t * t * self.end_x)
|
||||
self.y_i = int(t_inv * t_inv * self.start_y + 2 * t_inv * t * self.control_y + t * t * self.end_y)
|
||||
|
||||
def draw(self, game_screen: GameScreen):
|
||||
if self.is_balloon:
|
||||
@@ -1021,8 +1005,8 @@ class DrumrollCounter:
|
||||
tex.draw_texture('drumroll_counter', 'bubble', color=color)
|
||||
counter = str(self.drumroll_count)
|
||||
total_width = len(counter) * 52
|
||||
for i in range(len(counter)):
|
||||
tex.draw_texture('drumroll_counter', 'counter', color=color, frame=int(counter[i]), x=-(total_width//2)+(i*52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
for i, digit in enumerate(counter):
|
||||
tex.draw_texture('drumroll_counter', 'counter', color=color, frame=int(digit), x=-(total_width//2)+(i*52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
|
||||
class BalloonAnimation:
|
||||
def __init__(self, current_ms: float, balloon_total: int):
|
||||
@@ -1067,8 +1051,8 @@ class BalloonAnimation:
|
||||
tex.draw_texture('balloon', 'bubble')
|
||||
counter = str(max(0, self.balloon_total - self.balloon_count + 1))
|
||||
total_width = len(counter) * 52
|
||||
for i in range(len(counter)):
|
||||
tex.draw_texture('balloon', 'counter', frame=int(counter[i]), color=self.color, x=-(total_width // 2) + (i * 52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
for i, digit in enumerate(counter):
|
||||
tex.draw_texture('balloon', 'counter', frame=int(digit), color=self.color, x=-(total_width // 2) + (i * 52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
|
||||
class KusudamaAnimation:
|
||||
def __init__(self, balloon_total: int):
|
||||
@@ -1132,8 +1116,8 @@ class KusudamaAnimation:
|
||||
if counter == '0':
|
||||
return
|
||||
total_width = len(counter) * 150
|
||||
for i in range(len(counter)):
|
||||
tex.draw_texture('kusudama', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * 150), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
for i, digit in enumerate(counter):
|
||||
tex.draw_texture('kusudama', 'counter', frame=int(digit), x=-(total_width // 2) + (i * 150), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
|
||||
class Combo:
|
||||
def __init__(self, combo: int, current_ms: float):
|
||||
@@ -1177,21 +1161,27 @@ class Combo:
|
||||
self.color[i] = ray.fade(ray.WHITE, fade)
|
||||
|
||||
def draw(self):
|
||||
counter = str(self.combo)
|
||||
if self.combo < 3:
|
||||
return
|
||||
|
||||
# Cache string conversion
|
||||
if self.combo != getattr(self, '_cached_combo_value', -1):
|
||||
self._cached_combo_value = self.combo
|
||||
self._cached_combo_str = str(self.combo)
|
||||
counter = self._cached_combo_str
|
||||
|
||||
if self.combo < 100:
|
||||
margin = 30
|
||||
total_width = len(counter) * margin
|
||||
tex.draw_texture('combo', 'combo')
|
||||
for i in range(len(counter)):
|
||||
tex.draw_texture('combo', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * margin), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
for i, digit in enumerate(counter):
|
||||
tex.draw_texture('combo', 'counter', frame=int(digit), x=-(total_width // 2) + (i * margin), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
else:
|
||||
margin = 35
|
||||
total_width = len(counter) * margin
|
||||
tex.draw_texture('combo', 'combo_100')
|
||||
for i in range(len(counter)):
|
||||
tex.draw_texture('combo', 'counter_100', frame=int(counter[i]), x=-(total_width // 2) + (i * margin), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
for i, digit in enumerate(counter):
|
||||
tex.draw_texture('combo', 'counter_100', frame=int(digit), x=-(total_width // 2) + (i * margin), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||
glimmer_positions = [(225, 210), (200, 230), (250, 230)]
|
||||
for j, (x, y) in enumerate(glimmer_positions):
|
||||
for i in range(3):
|
||||
@@ -1213,13 +1203,18 @@ class ScoreCounter:
|
||||
self.stretch.update(current_ms)
|
||||
|
||||
def draw(self):
|
||||
counter = str(self.score)
|
||||
# Cache string conversion
|
||||
if self.score != getattr(self, '_cached_score_value', -1):
|
||||
self._cached_score_value = self.score
|
||||
self._cached_score_str = str(self.score)
|
||||
counter = self._cached_score_str
|
||||
|
||||
x, y = 150, 185
|
||||
margin = 20
|
||||
total_width = len(counter) * margin
|
||||
start_x = x - total_width
|
||||
for i in range(len(counter)):
|
||||
tex.draw_texture('lane', 'score_number', frame=int(counter[i]), x=start_x + (i * margin), y=y - self.stretch.attribute, y2=self.stretch.attribute)
|
||||
for i, digit in enumerate(counter):
|
||||
tex.draw_texture('lane', 'score_number', frame=int(digit), x=start_x + (i * margin), y=y - self.stretch.attribute, y2=self.stretch.attribute)
|
||||
|
||||
class ScoreCounterAnimation:
|
||||
def __init__(self, player_num: str, counter: int):
|
||||
@@ -1273,14 +1268,14 @@ class ScoreCounterAnimation:
|
||||
margin = 20
|
||||
total_width = len(counter) * margin
|
||||
start_x = x - total_width
|
||||
for i in range(len(counter)):
|
||||
for i, digit in enumerate(counter):
|
||||
if self.move_animation_3.is_finished:
|
||||
y = self.y_pos_list[i]
|
||||
elif self.move_animation_2.is_finished:
|
||||
y = self.move_animation_3.attribute
|
||||
else:
|
||||
y = 148
|
||||
tex.draw_texture('lane', 'score_number', frame=int(counter[i]), x=start_x + (i * margin), y=y, color=self.color)
|
||||
tex.draw_texture('lane', 'score_number', frame=int(digit), x=start_x + (i * margin), y=y, color=self.color)
|
||||
|
||||
class SongInfo:
|
||||
def __init__(self, song_name: str, genre: int):
|
||||
|
||||
Reference in New Issue
Block a user