cleaning up

This commit is contained in:
Anthony Samms
2025-12-02 15:23:23 -05:00
parent d543a594af
commit f5896c7d63
6 changed files with 442 additions and 1322 deletions

View File

@@ -135,7 +135,7 @@ class GameScreen(Screen):
def init_tja(self, song: Path):
"""Initialize the TJA file"""
self.tja = TJAParser(song, start_delay=self.start_delay, distance=tex.screen_width - GameScreen.JUDGE_X)
self.tja = TJAParser(song, start_delay=self.start_delay)
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)
@@ -460,8 +460,8 @@ class Player:
self.draw_note_list.extend(branch_section.draw_notes)
self.draw_bar_list.extend(branch_section.bars)
self.play_notes = deque(sorted(self.play_notes))
self.draw_note_list = deque(sorted(self.draw_note_list, key=lambda x: x.load_ms))
self.draw_bar_list = deque(sorted(self.draw_bar_list, key=lambda x: x.load_ms))
self.draw_note_list = deque(sorted(self.draw_note_list, key=lambda x: x.hit_ms))
self.draw_bar_list = deque(sorted(self.draw_bar_list, key=lambda x: x.hit_ms))
total_don = [note for note in self.play_notes if note.type in {NoteType.DON, NoteType.DON_L}]
total_kat = [note for note in self.play_notes if note.type in {NoteType.KAT, NoteType.KAT_L}]
total_other = [note for note in self.play_notes if note.type not in {NoteType.DON, NoteType.DON_L, NoteType.KAT, NoteType.KAT_L}]
@@ -474,24 +474,16 @@ class Player:
"""Returns the score, good count, ok count, bad count, max combo, and total drumroll"""
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:
"""Calculates the x-coordinate of a note based on its load time and current time"""
# Override if delay active
if self.delay_start:
current_ms = self.delay_start
time_diff = load_ms - current_ms
return int(width + pixels_per_frame * 0.06 * time_diff - (tex.textures["notes"]["1"].width//2)) - self.visual_offset
def get_position_x(self, note, current_ms):
speedx = note.bpm / 240000 * note.scroll_x * (tex.screen_width - GameScreen.JUDGE_X) * tex.screen_scale
return GameScreen.JUDGE_X + (note.hit_ms - current_ms) * speedx
def get_position_y(self, current_ms: float, load_ms: float, pixels_per_frame: float, pixels_per_frame_x) -> int:
"""Calculates the y-coordinate of a note based on its load time and current time"""
# Override if delay active
if self.delay_start:
current_ms = self.delay_start
time_diff = load_ms - current_ms
if pixels_per_frame_x == 0:
return int(pixels_per_frame * 0.06 * time_diff)
return int((pixels_per_frame * 0.06 * time_diff) + ((self.tja.distance * pixels_per_frame) / pixels_per_frame_x))
def get_position_y(self, note, current_ms):
speedy = note.bpm / 240000 * note.scroll_y * (tex.screen_width - GameScreen.JUDGE_Y) * tex.screen_scale
return (note.hit_ms - current_ms) * speedy
'''
def handle_tjap3_extended_commands(self, current_ms: float):
if not self.timeline or self.timeline_index >= len(self.timeline):
return
@@ -531,6 +523,7 @@ class Player:
if should_advance:
self.timeline_index += 1
'''
def get_judge_position(self, current_ms: float):
"""Get the current judgment circle position based on bar data with on-demand interpolation"""
@@ -539,7 +532,7 @@ class Player:
timeline_object = self.timeline[self.timeline_index]
if hasattr(timeline_object, 'delta_x'):
if hasattr(timeline_object, 'judge_pos_x'):
if timeline_object.load_ms <= current_ms <= timeline_object.hit_ms:
duration = timeline_object.hit_ms - timeline_object.load_ms
if duration > 0:
@@ -567,6 +560,7 @@ class Player:
timeline_object = self.timeline[self.timeline_index]
should_advance = False
'''
if hasattr(timeline_object, 'bpmchange') and timeline_object.hit_ms <= current_ms:
hit_ms = timeline_object.hit_ms
bpmchange = timeline_object.bpmchange
@@ -584,6 +578,7 @@ class Player:
note.pixels_per_frame_y *= bpmchange
self.bpm *= bpmchange
should_advance = True
'''
if hasattr(timeline_object, 'delay') and timeline_object.hit_ms <= current_ms:
hit_ms = timeline_object.hit_ms
@@ -624,7 +619,7 @@ class Player:
"""Manages the bars and removes if necessary
Also sets branch conditions"""
#Add bar to current_bars list if it is ready to be shown on screen
if self.draw_bar_list and current_ms > self.draw_bar_list[0].load_ms:
if self.draw_bar_list and current_ms >= self.draw_bar_list[0].hit_ms - 10000:
self.current_bars.append(self.draw_bar_list.popleft())
#If a bar is off screen, remove it
@@ -632,10 +627,10 @@ class Player:
return
# More efficient removal with early exit
removal_threshold = GameScreen.JUDGE_X + (650 * tex.screen_scale)
removal_threshold = GameScreen.JUDGE_X - (650 * tex.screen_scale)
bars_to_keep = []
for bar in self.current_bars:
position = self.get_position_x(tex.screen_width, current_ms, bar.hit_ms, bar.pixels_per_frame_x)
position = self.get_position_x(bar, current_ms)
if position >= removal_threshold:
bars_to_keep.append(bar)
self.current_bars = bars_to_keep
@@ -647,6 +642,7 @@ class Player:
logger.info(f'branch condition measures started with conditions {self.branch_condition}, {e_req}, {m_req}, {self.current_bars[-1].hit_ms}')
if not self.is_branch:
self.is_branch = True
'''
if self.branch_condition == 'r':
end_time = self.branch_m[0].bars[0].load_ms
end_roll = -1
@@ -686,6 +682,7 @@ class Player:
seen_notes.add(note)
self.curr_branch_reqs = [e_req, m_req, branch_start_time, max(len(seen_notes), 1)]
'''
def play_note_manager(self, current_ms: float, background: Optional[Background]):
"""Manages the play_notes and removes if necessary"""
if self.don_notes and self.don_notes[0].hit_ms + Player.TIMING_BAD < current_ms:
@@ -745,7 +742,7 @@ class Player:
def draw_note_manager(self, current_ms: float):
"""Manages the draw_notes and removes if necessary"""
if self.draw_note_list and current_ms + 1000 >= self.draw_note_list[0].load_ms:
if self.draw_note_list and current_ms >= self.draw_note_list[0].hit_ms - 10000:
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)
@@ -767,16 +764,14 @@ class Player:
note = self.current_notes_draw[0]
if note.type in {NoteType.ROLL_HEAD, NoteType.ROLL_HEAD_L, NoteType.BALLOON_HEAD, NoteType.KUSUDAMA} and len(self.current_notes_draw) > 1:
note = self.current_notes_draw[1]
if current_ms > note.hit_ms + 200:
if note.type == NoteType.TAIL:
self.current_notes_draw.pop(0)
if self.get_position_x(note, current_ms) < GameScreen.JUDGE_X:
self.current_notes_draw.pop(0)
def note_manager(self, current_ms: float, background: Optional[Background]):
self.bar_manager(current_ms)
self.play_note_manager(current_ms, background)
self.draw_note_manager(current_ms)
self.handle_tjap3_extended_commands(current_ms)
#self.handle_tjap3_extended_commands(current_ms)
def note_correct(self, note: Note, current_time: float):
"""Removes a note from the appropriate separated list"""
@@ -880,8 +875,8 @@ class Player:
if self.is_drumroll:
self.check_drumroll(drum_type, background, current_time)
elif self.is_balloon:
#if not isinstance(curr_note, Balloon):
#raise Exception("Balloon mode entered but current note is not balloon")
if not isinstance(curr_note, Balloon):
raise Exception("Balloon mode entered but current note is not balloon")
self.check_balloon(drum_type, curr_note, current_time)
else:
self.curr_drumroll_count = 0
@@ -1082,8 +1077,8 @@ class Player:
self.lane_hit_effect.update(current_time)
self.animation_manager(self.draw_drum_hit_list, current_time)
self.get_judge_position(ms_from_start)
self.handle_tjap3_extended_commands(ms_from_start)
self.handle_scroll_type_commands(ms_from_start)
'''
if self.delay_start is not None and self.delay_end is not None:
# Currently, a delay is active: notes should be frozen at ms = delay_start
# Check if it ended
@@ -1093,6 +1088,7 @@ class Player:
note.load_ms += delay
self.delay_start = None
self.delay_end = None
'''
self.update_bpm(ms_from_start)
# More efficient arc management
@@ -1123,30 +1119,6 @@ class Player:
if self.is_branch:
self.evaluate_branch(ms_from_start)
# Get the next note from any of the three lists for BPM and gogo time updates
'''
next_note = None
candidates = []
if self.don_notes:
candidates.append(self.don_notes[0])
if self.kat_notes:
candidates.append(self.kat_notes[0])
if self.other_notes:
candidates.append(self.other_notes[0])
if candidates:
next_note = min(candidates, key=lambda note: note.load_ms)
if next_note:
if next_note.gogo_time and not self.is_gogo_time:
self.is_gogo_time = True
self.gogo_time = GogoTime(self.is_2p)
self.chara.set_animation('gogo_start')
if not next_note.gogo_time and self.is_gogo_time:
self.is_gogo_time = False
self.gogo_time = None
self.chara.set_animation('gogo_stop')
'''
if self.gauge is None:
self.chara.update(current_time, self.bpm, False, False)
else:
@@ -1154,25 +1126,22 @@ class Player:
def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int):
"""Draws a drumroll in the player's lane"""
start_position = self.get_position_x(tex.screen_width, current_ms, head.load_ms, head.pixels_per_frame_x)
start_position += self.judge_x
start_position = self.get_position_x(head, current_ms)
tail = next((note for note in self.current_notes_draw[1:] if note.type == NoteType.TAIL and note.index > head.index), self.current_notes_draw[1])
is_big = int(head.type == NoteType.ROLL_HEAD_L)
end_position = self.get_position_x(tex.screen_width, current_ms, tail.load_ms, tail.pixels_per_frame_x)
end_position += self.judge_x
end_position = self.get_position_x(tail, current_ms)
length = end_position - start_position
color = ray.Color(255, head.color, head.color, 255)
y = tex.skin_config["notes"].y + self.get_position_y(current_ms, head.load_ms, head.pixels_per_frame_y, head.pixels_per_frame_x)
y = tex.skin_config["notes"].y + self.get_position_y(head, current_ms)
moji_y = tex.skin_config["moji"].y
moji_x = -(tex.textures["notes"]["moji"].width//2) + (tex.textures["notes"]["1"].width//2)
if head.display:
if length > 0:
tex.draw_texture('notes', "8", frame=is_big, x=start_position+(tex.textures["notes"]["5"].width//2), y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, x2=length+tex.skin_config["drumroll_width_offset"].width, color=color)
if is_big:
tex.draw_texture('notes', "drumroll_big_tail", x=end_position+tex.textures["notes"]["5"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
else:
tex.draw_texture('notes', "drumroll_tail", x=end_position+tex.textures["notes"]["5"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
tex.draw_texture('notes', "8", frame=is_big, x=start_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, x2=length+tex.skin_config["drumroll_width_offset"].width, color=color)
if is_big:
tex.draw_texture('notes', "drumroll_big_tail", x=end_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
else:
tex.draw_texture('notes', "drumroll_tail", x=end_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position - tex.textures["notes"]["1"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + tex.textures["notes"]["1"].width//2, y=moji_y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, x2=length)
tex.draw_texture('notes', 'moji', frame=head.moji, x=start_position + moji_x, y=moji_y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
@@ -1181,13 +1150,11 @@ class Player:
def draw_balloon(self, current_ms: float, head: Balloon, current_eighth: int):
"""Draws a balloon in the player's lane"""
offset = tex.skin_config["balloon_offset"].x
start_position = self.get_position_x(tex.screen_width, current_ms, head.load_ms, head.pixels_per_frame_x)
start_position += self.judge_x
start_position = self.get_position_x(head, current_ms)
tail = next((note for note in self.current_notes_draw[1:] if note.type == NoteType.TAIL and note.index > head.index), self.current_notes_draw[1])
end_position = self.get_position_x(tex.screen_width, current_ms, tail.load_ms, tail.pixels_per_frame_x)
end_position += self.judge_x
pause_position = tex.skin_config["balloon_pause_position"].x + self.judge_x
y = tex.skin_config["notes"].y + self.get_position_y(current_ms, head.load_ms, head.pixels_per_frame_y, head.pixels_per_frame_x)
end_position = self.get_position_x(tail, current_ms)
pause_position = GameScreen.JUDGE_X
y = tex.skin_config["notes"].y + self.get_position_y(head, current_ms)
if current_ms >= tail.hit_ms:
position = end_position
elif current_ms >= head.hit_ms:
@@ -1195,8 +1162,8 @@ class Player:
else:
position = start_position
if head.display:
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+tex.textures["notes"]["10"].width, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset - tex.textures["notes"]["1"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+tex.textures["notes"]["10"].width - tex.textures["notes"]["1"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
def draw_bars(self, current_ms: float):
"""Draw bars in the player's lane"""
@@ -1206,29 +1173,19 @@ class Player:
for bar in reversed(self.current_bars):
if not bar.display:
continue
x_position = self.get_position_x(tex.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)
x_position += self.judge_x
y_position += self.judge_y
if hasattr(bar, 'is_branch_start'):
frame = 1
else:
frame = 0
x_position = self.get_position_x(bar, current_ms)
y_position = self.get_position_y(bar, current_ms)
if y_position != 0:
angle = math.degrees(math.atan2(bar.pixels_per_frame_y, bar.pixels_per_frame_x))
angle = math.degrees(math.atan2(bar.scroll_y, bar.scroll_x))
else:
angle = 0
tex.draw_texture('notes', str(bar.type), frame=frame, x=x_position+tex.skin_config["moji_drumroll"].x, y=y_position+tex.skin_config["moji_drumroll"].y+(self.is_2p*tex.skin_config["2p_offset"].y), rotation=angle)
tex.draw_texture('notes', str(bar.type), x=x_position+tex.skin_config["moji_drumroll"].x- (tex.textures["notes"]["1"].width//2), y=y_position+tex.skin_config["moji_drumroll"].y+(self.is_2p*tex.skin_config["2p_offset"].y), rotation=angle)
def draw_notes(self, current_ms: float, start_ms: float):
def draw_notes(self, current_ms: float):
"""Draw notes in the player's lane"""
if not self.current_notes_draw:
return
eighth_in_ms = 0 if self.bpm == 0 else (60000 * 4 / self.bpm) / 8
current_eighth = 0
if self.combo >= 50 and eighth_in_ms != 0:
current_eighth = int((current_ms - start_ms) // eighth_in_ms)
for note in reversed(self.current_notes_draw):
if self.balloon_anim is not None and note == self.current_notes_draw[0]:
@@ -1236,6 +1193,7 @@ class Player:
if note.type == NoteType.TAIL:
continue
current_eighth = 0
if hasattr(note, 'sudden_appear_ms') and hasattr(note, 'sudden_moving_ms'):
appear_ms = note.hit_ms - note.sudden_appear_ms
moving_start_ms = note.hit_ms - note.sudden_moving_ms
@@ -1247,14 +1205,11 @@ class Player:
effective_ms = moving_start_ms
else:
effective_ms = current_ms
x_position = self.get_position_x(tex.screen_width, effective_ms, note.load_ms, note.pixels_per_frame_x)
y_position = self.get_position_y(effective_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
x_position = self.get_position_x(note, effective_ms)
y_position = self.get_position_y(note, effective_ms)
else:
x_position = self.get_position_x(tex.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)
x_position += self.judge_x
y_position += self.judge_y
x_position = self.get_position_x(note, current_ms)
y_position = self.get_position_y(note, current_ms)
if isinstance(note, Drumroll):
self.draw_drumroll(current_ms, note, current_eighth)
elif isinstance(note, Balloon) and not note.is_kusudama:
@@ -1262,10 +1217,8 @@ class Player:
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position, y=tex.skin_config["moji"].y + y_position+(self.is_2p*tex.skin_config["2p_offset"].y))
else:
if note.display:
tex.draw_texture('notes', str(note.type), frame=current_eighth % 2, x=x_position, y=y_position+tex.skin_config["notes"].y+(self.is_2p*tex.skin_config["2p_offset"].y), center=True)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (tex.textures["notes"]["moji"].width//2) + (tex.textures["notes"]["1"].width//2), y=tex.skin_config["moji"].y + y_position+(self.is_2p*tex.skin_config["2p_offset"].y))
ray.draw_text(self.current_notes_draw[0].lyric, tex.screen_width//2 - (ray.measure_text(self.current_notes_draw[0].lyric, int(40 * tex.screen_scale))//2), tex.screen_height - int(50 * tex.screen_scale), int(40 * tex.screen_scale), ray.BLUE)
tex.draw_texture('notes', str(note.type), frame=current_eighth % 2, x=x_position - (tex.textures["notes"]["1"].width//2), y=y_position+tex.skin_config["notes"].y+(self.is_2p*tex.skin_config["2p_offset"].y), center=True)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (tex.textures["notes"]["moji"].width//2), y=tex.skin_config["moji"].y + y_position+(self.is_2p*tex.skin_config["2p_offset"].y))
def draw_modifiers(self):
@@ -1367,7 +1320,7 @@ class Player:
# Group 3: Notes and bars (game content)
self.draw_bars(ms_from_start)
self.draw_notes(ms_from_start, start_ms)
self.draw_notes(ms_from_start)
if dan_transition is not None:
dan_transition.draw()

View File

@@ -1,218 +0,0 @@
from collections import deque
from libs.tja2 import TJAParser2
import bisect
from enum import IntEnum
import math
import logging
from pathlib import Path
import pyray as ray
from libs.audio import audio
from libs.texture import tex
from libs.tja import calculate_base_score, NoteType
from libs.tja2 import (
Balloon,
Drumroll,
Note,
)
from libs.utils import (
get_current_ms,
global_data,
)
from libs.video import VideoPlayer
from scenes.game import GameScreen, Player
logger = logging.getLogger(__name__)
class DrumType(IntEnum):
DON = 1
KAT = 2
class Side(IntEnum):
LEFT = 1
RIGHT = 2
class Judgments(IntEnum):
GOOD = 0
OK = 1
BAD = 2
class GameScreen2(GameScreen):
def init_tja(self, song: Path):
"""Initialize the TJA file"""
self.tja = TJAParser2(song, start_delay=self.start_delay, distance=tex.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)
else:
self.movie = None
global_data.session_data[global_data.player_num].song_title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
if self.tja.metadata.wave.exists() and self.tja.metadata.wave.is_file() and self.song_music is None:
self.song_music = audio.load_music_stream(self.tja.metadata.wave, 'song')
self.player_1 = Player2(self.tja, global_data.player_num, global_data.session_data[global_data.player_num].selected_difficulty, False, global_data.modifiers[global_data.player_num])
self.start_ms = get_current_ms() - self.tja.metadata.offset*1000
class Player2(Player):
def reset_chart(self):
notes, self.branch_m, self.branch_e, self.branch_n = self.tja.notes_to_position(self.difficulty)
self.play_notes, self.draw_note_list, self.draw_bar_list = deque(notes.play_notes), deque(notes.draw_notes), deque(notes.bars)
self.don_notes = deque([note for note in self.play_notes if note.type in {NoteType.DON, NoteType.DON_L}])
self.kat_notes = deque([note for note in self.play_notes if note.type in {NoteType.KAT, NoteType.KAT_L}])
self.other_notes = deque([note for note in self.play_notes if note.type not in {NoteType.DON, NoteType.DON_L, NoteType.KAT, NoteType.KAT_L}])
self.total_notes = len([note for note in self.play_notes if 0 < note.type < 5])
total_notes = notes
if self.branch_m:
for section in self.branch_m:
self.total_notes += len([note for note in section.play_notes if 0 < note.type < 5])
total_notes += section
self.base_score = calculate_base_score(total_notes)
#Note management
self.timeline = notes.timeline
self.timeline_index = 0 # Range: [0, len(timeline)]
self.current_bars: list[Note] = []
self.current_notes_draw: list[Note | Drumroll | Balloon] = []
self.is_drumroll = False
self.curr_drumroll_count = 0
self.is_balloon = False
self.curr_balloon_count = 0
self.is_branch = False
self.curr_branch_reqs = []
self.branch_condition_count = 0
self.branch_condition = ''
self.balloon_index = 0
self.bpm = 120
if self.timeline and hasattr(self.timeline[self.timeline_index], 'bpm'):
self.bpm = self.timeline[self.timeline_index].bpm
self.end_time = 0
if self.play_notes:
self.end_time = self.play_notes[-1].hit_ms
def get_position_x(self, note, current_ms):
speedx = note.bpm / 240000 * note.scroll_x * (tex.screen_width - GameScreen.JUDGE_X) * tex.screen_scale
return GameScreen.JUDGE_X + (note.hit_ms - current_ms) * speedx
def get_position_y(self, note, current_ms):
speedy = note.bpm / 240000 * note.scroll_y * (tex.screen_width - GameScreen.JUDGE_Y) * tex.screen_scale
return (note.hit_ms - current_ms) * speedy
def bar_manager(self, current_ms: float):
"""Manages the bars and removes if necessary
Also sets branch conditions"""
#Add bar to current_bars list if it is ready to be shown on screen
if self.draw_bar_list and current_ms >= self.draw_bar_list[0].hit_ms - 10000:
self.current_bars.append(self.draw_bar_list.popleft())
def draw_note_manager(self, current_ms: float):
"""Manages the draw_notes and removes if necessary"""
if self.draw_note_list and current_ms >= self.draw_note_list[0].hit_ms - 10000:
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)
try:
tail_note = next((note for note in self.draw_note_list if note.type == NoteType.TAIL))
bisect.insort_left(self.current_notes_draw, tail_note, key=lambda x: x.index)
self.draw_note_list.remove(tail_note)
except Exception as e:
raise(e)
else:
bisect.insort_left(self.current_notes_draw, current_note, key=lambda x: x.index)
if not self.current_notes_draw:
return
if isinstance(self.current_notes_draw[0], Drumroll):
self.current_notes_draw[0].color = min(255, self.current_notes_draw[0].color + 1)
note = self.current_notes_draw[0]
if note.type in {NoteType.ROLL_HEAD, NoteType.ROLL_HEAD_L, NoteType.BALLOON_HEAD, NoteType.KUSUDAMA} and len(self.current_notes_draw) > 1:
note = self.current_notes_draw[1]
if self.get_position_x(note, current_ms) < GameScreen.JUDGE_X:
self.current_notes_draw.pop(0)
def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int):
"""Draws a drumroll in the player's lane"""
start_position = self.get_position_x(head, current_ms)
tail = next((note for note in self.current_notes_draw[1:] if note.type == NoteType.TAIL and note.index > head.index), self.current_notes_draw[1])
is_big = int(head.type == NoteType.ROLL_HEAD_L)
end_position = self.get_position_x(tail, current_ms)
length = end_position - start_position
color = ray.Color(255, head.color, head.color, 255)
y = tex.skin_config["notes"].y + self.get_position_y(head, current_ms)
moji_y = tex.skin_config["moji"].y
moji_x = -(tex.textures["notes"]["moji"].width//2) + (tex.textures["notes"]["1"].width//2)
if head.display:
tex.draw_texture('notes', "8", frame=is_big, x=start_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, x2=length+tex.skin_config["drumroll_width_offset"].width, color=color)
if is_big:
tex.draw_texture('notes', "drumroll_big_tail", x=end_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
else:
tex.draw_texture('notes', "drumroll_tail", x=end_position, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position - tex.textures["notes"]["1"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, color=color)
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + tex.textures["notes"]["1"].width//2, y=moji_y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y, x2=length)
tex.draw_texture('notes', 'moji', frame=head.moji, x=start_position + moji_x, y=moji_y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
tex.draw_texture('notes', 'moji', frame=tail.moji, x=end_position + moji_x, y=moji_y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
def draw_balloon(self, current_ms: float, head: Balloon, current_eighth: int):
"""Draws a balloon in the player's lane"""
offset = tex.skin_config["balloon_offset"].x
start_position = self.get_position_x(head, current_ms)
tail = next((note for note in self.current_notes_draw[1:] if note.type == NoteType.TAIL and note.index > head.index), self.current_notes_draw[1])
end_position = self.get_position_x(tail, current_ms)
pause_position = GameScreen.JUDGE_X
y = tex.skin_config["notes"].y + self.get_position_y(head, current_ms)
if current_ms >= tail.hit_ms:
position = end_position
elif current_ms >= head.hit_ms:
position = pause_position
else:
position = start_position
if head.display:
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset - tex.textures["notes"]["1"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+tex.textures["notes"]["10"].width - tex.textures["notes"]["1"].width//2, y=y+(self.is_2p*tex.skin_config["2p_offset"].y)+self.judge_y)
def draw_bars(self, current_ms: float):
"""Draw bars in the player's lane"""
if not self.current_bars:
return
for bar in reversed(self.current_bars):
if not bar.display:
continue
x_position = self.get_position_x(bar, current_ms)
y_position = self.get_position_y(bar, current_ms)
if y_position != 0:
angle = math.degrees(math.atan2(bar.scroll_y, bar.scroll_x))
else:
angle = 0
tex.draw_texture('notes', str(bar.type), x=x_position+tex.skin_config["moji_drumroll"].x- (tex.textures["notes"]["1"].width//2), y=y_position+tex.skin_config["moji_drumroll"].y+(self.is_2p*tex.skin_config["2p_offset"].y), rotation=angle)
def draw_notes(self, current_ms: float, start_ms: float):
"""Draw notes in the player's lane"""
if not self.current_notes_draw:
return
for note in reversed(self.current_notes_draw):
if self.balloon_anim is not None and note == self.current_notes_draw[0]:
continue
if note.type == NoteType.TAIL:
continue
current_eighth = 0
x_position = self.get_position_x(note, current_ms)
y_position = self.get_position_y(note, current_ms)
if isinstance(note, Drumroll):
self.draw_drumroll(current_ms, note, current_eighth)
elif isinstance(note, Balloon) and not note.is_kusudama:
self.draw_balloon(current_ms, note, current_eighth)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position, y=tex.skin_config["moji"].y + y_position+(self.is_2p*tex.skin_config["2p_offset"].y))
else:
if note.display:
tex.draw_texture('notes', str(note.type), frame=current_eighth % 2, x=x_position - (tex.textures["notes"]["1"].width//2), y=y_position+tex.skin_config["notes"].y+(self.is_2p*tex.skin_config["2p_offset"].y), center=True)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (tex.textures["notes"]["moji"].width//2), y=tex.skin_config["moji"].y + y_position+(self.is_2p*tex.skin_config["2p_offset"].y))

View File

@@ -345,7 +345,7 @@ class PracticePlayer(Player):
# Group 3: Notes and bars (game content)
if not self.paused:
self.draw_bars(ms_from_start)
self.draw_notes(ms_from_start, start_ms)
self.draw_notes(ms_from_start)
class PracticeDrumHitEffect(DrumHitEffect):
def __init__(self, type, side, is_2p, player_num: PlayerNum = PlayerNum.P1):