add 1080p and more support

This commit is contained in:
Anthony Samms
2025-11-20 02:07:46 -05:00
parent 802d9c5b37
commit 1fae2ebd18
31 changed files with 631 additions and 602 deletions

View File

@@ -28,13 +28,13 @@ class DanResultScreen(Screen):
self.coin_overlay = CoinOverlay()
self.allnet_indicator = AllNetIcon()
self.start_ms = get_current_ms()
self.background = Background(PlayerNum.DAN, 1280)
self.background = Background(PlayerNum.DAN, tex.screen_width)
self.player = DanResultPlayer(global_data.player_num)
self.is_result_2 = False
self.result_2_fade_in = tex.get_animation(1)
self.gauge = DanGauge(global_data.player_num, global_data.session_data[global_data.player_num].dan_result_data.gauge_length)
self.song_names = [OutlinedText(song.song_title, 40, ray.WHITE) for song in global_data.session_data[global_data.player_num].dan_result_data.songs]
self.hori_name = OutlinedText(global_data.session_data[global_data.player_num].dan_result_data.dan_title, 40, ray.WHITE)
self.song_names = [OutlinedText(song.song_title, tex.skin_config["dan_title"].font_size, ray.WHITE) for song in global_data.session_data[global_data.player_num].dan_result_data.songs]
self.hori_name = OutlinedText(global_data.session_data[global_data.player_num].dan_result_data.dan_title, tex.skin_config["dan_title"].font_size, ray.WHITE)
self.exam_info = global_data.session_data[global_data.player_num].dan_result_data.exams
self.exam_data = global_data.session_data[global_data.player_num].dan_result_data.exam_data
print(global_data.session_data[global_data.player_num].dan_result_data.songs)
@@ -67,29 +67,29 @@ class DanResultScreen(Screen):
return self.on_screen_end("DAN_SELECT")
def draw_overlay(self):
ray.draw_rectangle(0, 0, 1280, 720, ray.fade(ray.BLACK, self.fade_out.attribute))
ray.draw_rectangle(0, 0, tex.screen_width, tex.screen_height, ray.fade(ray.BLACK, self.fade_out.attribute))
self.coin_overlay.draw()
self.allnet_indicator.draw()
def draw_song_info_1(self):
result_data = global_data.session_data[global_data.player_num].dan_result_data
height = 191
height = tex.skin_config["dan_result_info_height"].y
for i in range(len(result_data.songs)):
song = result_data.songs[i]
tex.draw_texture('background', 'genre_banner', y=i*height, frame=song.genre_index)
self.song_names[i].draw(x=1230 - self.song_names[i].texture.width, y=i*height + 90)
self.song_names[i].draw(x=tex.skin_config["dan_result_song_name"].x - self.song_names[i].texture.width, y=i*height + tex.skin_config["dan_result_song_name"].y)
tex.draw_texture('result_info', 'song_num', frame=i, y=i*height)
tex.draw_texture('result_info', 'difficulty', frame=song.selected_difficulty, y=i*height)
tex.draw_texture('result_info', 'diff_star', y=i*height)
tex.draw_texture('result_info', 'diff_x', y=i*height)
counter = str(song.diff_level)[::-1]
margin = 12
margin = tex.skin_config["dan_result_diff_num_margin"].x
for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'diff_num', frame=int(digit), x=-(j*margin), y=i*height)
tex.draw_texture('result_info', 'good', y=i*height)
margin = 24
margin = tex.skin_config["score_info_counter_margin"].x
counter = str(song.good)[::-1]
for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'counter', index=0, frame=int(digit), x=-(j*margin), y=i*height)
@@ -113,11 +113,11 @@ class DanResultScreen(Screen):
tex.draw_texture('background', 'result_2_divider', fade=fade, x=i*240)
tex.draw_texture('background', 'result_2_pullout', fade=fade)
tex.draw_texture('result_info', 'dan_emblem', fade=fade, frame=result_data.dan_color)
self.hori_name.draw(outline_color=ray.BLACK, x=276 - (self.hori_name.texture.width//2),
y=123, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width, color=ray.fade(ray.WHITE, fade))
self.hori_name.draw(outline_color=ray.BLACK, x=tex.skin_config["dan_result_hori_name"].x - (self.hori_name.texture.width//2),
y=tex.skin_config["dan_result_hori_name"].y, x2=min(self.hori_name.texture.width, tex.skin_config["dan_result_hori_name"].width)-self.hori_name.texture.width, color=ray.fade(ray.WHITE, fade))
tex.draw_texture('result_info', 'good', index=1, fade=fade)
margin = 24
margin = tex.skin_config["score_info_counter_margin"].x
counter = str(sum(song.good for song in result_data.songs))[::-1]
for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'counter', index=4, frame=int(digit), x=-(j*margin), fade=fade)
@@ -144,7 +144,7 @@ class DanResultScreen(Screen):
tex.draw_texture('result_info', 'exam_header', fade=fade)
tex.draw_texture('result_info', 'score_box', fade=fade)
margin = 22
margin = tex.skin_config['dan_score_box_margin'].x
counter = str(result_data.score)[::-1]
for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'score_counter', frame=int(digit), x=-(j*margin), fade=fade)
@@ -164,14 +164,14 @@ class DanResultScreen(Screen):
# Draw exam info
for i, exam in enumerate(self.exam_info):
exam_data = self.exam_data[i]
y_offset = i * 94 * scale # Scale the y offset
y_offset = i * tex.skin_config["dan_exam_info"].y * scale # Scale the y offset
tex.draw_texture('exam_info', 'exam_bg', y=y_offset, fade=fade, scale=scale)
tex.draw_texture('exam_info', 'exam_overlay_1', y=y_offset, fade=fade, scale=scale)
# Draw progress bar
tex.draw_texture('exam_info', exam_data.bar_texture, x2=940*exam_data.progress*scale, y=y_offset, fade=fade, scale=scale)
tex.draw_texture('exam_info', exam_data.bar_texture, x2=tex.skin_config["dan_exam_info"].width *exam_data.progress*scale, y=y_offset, fade=fade, scale=scale)
# Draw exam type and red value counter
red_counter = str(exam.red)
self._draw_counter(red_counter, margin=22*scale, texture='value_counter', index=0, y=y_offset, fade=fade, scale=scale)
self._draw_counter(red_counter, margin=tex.skin_config["dan_exam_info"].x*scale, texture='value_counter', index=0, y=y_offset, fade=fade, scale=scale)
tex.draw_texture('exam_info', f'exam_{exam.type}', y=y_offset, x=-len(red_counter)*20*scale, fade=fade, scale=scale)
# Draw range indicator
if exam.range == 'less':
@@ -181,7 +181,7 @@ class DanResultScreen(Screen):
# Draw current value counter
tex.draw_texture('exam_info', 'exam_overlay_2', y=y_offset, fade=fade, scale=scale)
value_counter = str(exam_data.counter_value)
self._draw_counter(value_counter, margin=22*scale, texture='value_counter', index=1, y=y_offset, fade=fade, scale=scale)
self._draw_counter(value_counter, margin=tex.skin_config["dan_exam_info"].x*scale, texture='value_counter', index=1, y=y_offset, fade=fade, scale=scale)
if exam.type == 'gauge':
tex.draw_texture('exam_info', 'exam_percent', y=y_offset, index=1, fade=fade, scale=scale)
if exam_data.failed:
@@ -207,15 +207,15 @@ class DanResultPlayer:
def __init__(self, player_num: PlayerNum):
plate_info = global_data.config[f'nameplate_{player_num}p']
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], player_num, plate_info['dan'], plate_info['gold'], plate_info['rainbow'], plate_info['title_bg'])
self.chara = Chara2D(player_num-1, 100)
self.chara = Chara2D(player_num-1)
def update(self, current_time_ms: float):
self.nameplate.update(current_time_ms)
self.chara.update(current_time_ms, 100, False, False)
def draw(self):
self.nameplate.draw(10, 585)
self.chara.draw(0, 405)
self.nameplate.draw(tex.skin_config['dan_result_nameplate'].x, tex.skin_config['dan_result_nameplate'].y)
self.chara.draw(tex.skin_config['dan_result_chara'].x, tex.skin_config['dan_result_chara'].y)
class DanGauge(Gauge):
"""The player's gauge"""

View File

@@ -4,7 +4,7 @@ import pyray as ray
from libs.audio import audio
from libs.global_data import PlayerNum, global_data
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex
from libs.texture import tex
from libs.chara_2d import Chara2D
from libs.global_objects import AllNetIcon, CoinOverlay, Indicator, Nameplate, Timer
from libs.screen import Screen
@@ -103,15 +103,15 @@ class DanSelectScreen(Screen):
tex.draw_texture('global', 'footer')
for item in self.navigator.items:
box = item.box
if -156 <= box.position <= SCREEN_WIDTH + 144:
if box.position <= 500:
box.draw(box.position, 95, False)
if (-156 * tex.screen_scale) <= box.position <= tex.screen_width + (144 * tex.screen_scale):
if box.position <= (500 * tex.screen_scale):
box.draw(box.position, tex.skin_config["boxes"].y, False)
else:
box.draw(box.position, 95, False)
box.draw(box.position, tex.skin_config["boxes"].y, False)
if self.state == State.SONG_SELECTED:
ray.draw_rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ray.fade(ray.BLACK, min(0.5, self.player.confirmation_window.fade_in.attribute)))
ray.draw_rectangle(0, 0, tex.screen_width, tex.screen_height, ray.fade(ray.BLACK, min(0.5, self.player.confirmation_window.fade_in.attribute)))
self.player.draw()
self.indicator.draw(410, 575)
self.indicator.draw(tex.skin_config["dan_select_indicator"].x, tex.skin_config["dan_select_indicator"].y)
self.timer.draw()
self.coin_overlay.draw()
tex.draw_texture('global', 'dan_select')
@@ -133,7 +133,7 @@ class DanSelectPlayer:
self.confirmation_window = ConfirmationWindow()
# Player-specific objects
self.chara = Chara2D(int(self.player_num) - 1, 100)
self.chara = Chara2D(int(self.player_num) - 1)
plate_info = global_data.config[f'nameplate_{self.player_num}p']
self.nameplate = Nameplate(plate_info['name'], plate_info['title'],
self.player_num, plate_info['dan'], plate_info['gold'], plate_info['rainbow'], plate_info['title_bg'])
@@ -212,11 +212,11 @@ class DanSelectPlayer:
def draw(self):
if self.player_num == PlayerNum.P1:
self.nameplate.draw(30, 640)
self.chara.draw(x=-50, y=410)
self.nameplate.draw(tex.skin_config["dan_select_nameplate_1p"].x, tex.skin_config["dan_select_nameplate_1p"].y)
self.chara.draw(x=tex.skin_config["dan_select_chara_1p"].x, y=tex.skin_config["dan_select_chara_1p"].y)
else:
self.nameplate.draw(950, 640)
self.chara.draw(mirror=True, x=950, y=410)
self.nameplate.draw(tex.skin_config["dan_select_nameplate_2p"].x, tex.skin_config["dan_select_nameplate_2p"].y)
self.chara.draw(mirror=True, x=tex.skin_config["dan_select_chara_2p"].x, y=tex.skin_config["dan_select_chara_2p"].y)
self.confirmation_window.draw()

View File

@@ -1,5 +1,5 @@
import copy
from typing import override
from typing import Optional, override
import pyray as ray
import logging
from libs.animation import Animation
@@ -11,7 +11,7 @@ from libs.global_objects import AllNetIcon
from libs.tja import TJAParser
from libs.transition import Transition
from libs.utils import OutlinedText, get_current_ms
from libs.texture import SCREEN_WIDTH, tex
from libs.texture import tex
from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, Gauge, ResultTransition, SongInfo
logger = logging.getLogger(__name__)
@@ -87,7 +87,7 @@ class DanGameScreen(GameScreen):
song, genre_index, difficulty, level = songs[self.song_index]
session_data.selected_difficulty = difficulty
self.player_1.difficulty = difficulty
self.tja = TJAParser(song.file_path, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
self.tja = TJAParser(song.file_path, start_delay=self.start_delay, distance=tex.screen_width - GameScreen.JUDGE_X)
if self.song_music is not None:
audio.unload_music_stream(self.song_music)
self.song_music = None
@@ -281,22 +281,22 @@ class DanGameScreen(GameScreen):
# Draw total notes counter
tex.draw_texture('dan_info', 'total_notes')
counter = str(cache['remaining_notes'])
self._draw_counter(counter, margin=45, texture='total_notes_counter')
self._draw_counter(counter, margin=tex.skin_config["dan_total_notes_margin"].x, texture='total_notes_counter')
# Draw exam info
for i, exam_info in enumerate(cache['exam_data']):
y_offset = i * 94
y_offset = i * tex.skin_config["dan_exam_info"].y
exam = exam_info['exam']
tex.draw_texture('dan_info', 'exam_bg', y=y_offset)
tex.draw_texture('dan_info', 'exam_overlay_1', y=y_offset)
# Draw progress bar
tex.draw_texture('dan_info', exam_info['bar_texture'], x2=940*exam_info['progress'], y=y_offset)
tex.draw_texture('dan_info', exam_info['bar_texture'], x2=tex.skin_config["dan_exam_info"].width*exam_info['progress'], y=y_offset)
# Draw exam type and red value counter
red_counter = str(exam_info['red_value'])
self._draw_counter(red_counter, margin=22, texture='value_counter', index=0, y=y_offset)
self._draw_counter(red_counter, margin=tex.skin_config["dan_score_box_margin"].x, texture='value_counter', index=0, y=y_offset)
tex.draw_texture('dan_info', f'exam_{exam.type}', y=y_offset, x=-len(red_counter)*20)
# Draw range indicator
@@ -308,7 +308,7 @@ class DanGameScreen(GameScreen):
# Draw current value counter
tex.draw_texture('dan_info', 'exam_overlay_2', y=y_offset)
value_counter = str(exam_info['counter_value'])
self._draw_counter(value_counter, margin=22, texture='value_counter', index=1, y=y_offset)
self._draw_counter(value_counter, margin=tex.skin_config["dan_score_box_margin"].x, texture='value_counter', index=1, y=y_offset)
if exam.type == 'gauge':
tex.draw_texture('dan_info', 'exam_percent', y=y_offset, index=1)
@@ -320,10 +320,10 @@ class DanGameScreen(GameScreen):
# Draw frame and title
tex.draw_texture('dan_info', 'frame', frame=self.color)
if self.hori_name is not None:
self.hori_name.draw(outline_color=ray.BLACK, x=154 - (self.hori_name.texture.width//2),
y=392, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width)
self.hori_name.draw(outline_color=ray.BLACK, x=tex.skin_config["dan_game_hori_name"].x - (self.hori_name.texture.width//2),
y=tex.skin_config["dan_game_hori_name"].y, x2=min(self.hori_name.texture.width, tex.skin_config["dan_game_hori_name"].width)-self.hori_name.texture.width)
def _draw_counter(self, counter, margin, texture, index=None, y=0):
def _draw_counter(self, counter: str, margin: float, texture: str, index: Optional[int] = None, y: float = 0):
"""Helper to draw digit counters"""
for j in range(len(counter)):
kwargs = {'frame': int(counter[j]), 'x': -(len(counter) - j) * margin, 'y': y}

View File

@@ -6,7 +6,7 @@ from libs.audio import audio
from libs.chara_2d import Chara2D
from libs.global_data import PlayerNum
from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, EntryOverlay, Timer
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex
from libs.texture import tex
from libs.screen import Screen
from libs.utils import (
OutlinedText,
@@ -212,7 +212,7 @@ class EntryScreen(Screen):
tex.draw_texture('global', 'player_entry')
if self.box_manager.is_finished():
ray.draw_rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ray.BLACK)
ray.draw_rectangle(0, 0, tex.screen_width, tex.screen_height, ray.BLACK)
self.timer.draw()
self.entry_overlay.draw(y=tex.skin_config['entry_overlay_entry'].y)
@@ -452,7 +452,7 @@ class BoxManager:
spacing = tex.skin_config["entry_box_spacing"].x
box_width = self.boxes[0].texture.width
total_width = self.num_boxes * box_width + (self.num_boxes - 1) * spacing
start_x = SCREEN_WIDTH//2 - total_width//2
start_x = tex.screen_width//2 - total_width//2
for i, box in enumerate(self.boxes):
box.set_positions(start_x + i * (box_width + spacing))
if i > 0:

View File

@@ -16,7 +16,7 @@ from libs.chara_2d import Chara2D
from libs.global_data import Crown, Difficulty, Modifiers, PlayerNum
from libs.global_objects import AllNetIcon, Nameplate
from libs.screen import Screen
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex
from libs.texture import tex
from libs.tja import (
Balloon,
Drumroll,
@@ -57,7 +57,7 @@ class Judgments(IntEnum):
BAD = 2
class GameScreen(Screen):
JUDGE_X = 414
JUDGE_X = 414 * tex.screen_scale
def on_screen_start(self):
super().on_screen_start()
self.mask_shader = ray.load_shader("shader/outline.vs", "shader/mask.fs")
@@ -133,7 +133,7 @@ class GameScreen(Screen):
def init_tja(self, song: Path):
"""Initialize the TJA file"""
self.tja = TJAParser(song, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
self.tja = TJAParser(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)
@@ -447,12 +447,12 @@ class Player:
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"""
time_diff = load_ms - current_ms
return int(width + pixels_per_frame * 0.06 * time_diff - 64) - self.visual_offset
return int(width + pixels_per_frame * 0.06 * time_diff - (tex.textures["notes"]["1"].width//2)) - self.visual_offset
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"""
time_diff = load_ms - current_ms
return int((pixels_per_frame * 0.06 * time_diff) + ((866 * pixels_per_frame) / pixels_per_frame_x))
return int((pixels_per_frame * 0.06 * time_diff) + ((self.tja.distance * pixels_per_frame) / pixels_per_frame_x))
def get_judge_position(self, current_ms: float):
"""Get the current judgment circle position based on bar data"""
@@ -462,8 +462,8 @@ class Player:
# Find the most recent bar with judge position data
for bar in self.current_bars:
if hasattr(bar, 'judge_pos_x') and bar.hit_ms <= current_ms:
judge_x = bar.judge_pos_x
judge_y = bar.judge_pos_y
judge_x = bar.judge_pos_x * tex.screen_scale
judge_y = bar.judge_pos_y * tex.screen_scale
elif bar.hit_ms > current_ms:
break
@@ -495,10 +495,10 @@ class Player:
return
# More efficient removal with early exit
removal_threshold = GameScreen.JUDGE_X + 650
removal_threshold = GameScreen.JUDGE_X + (650 * tex.screen_scale)
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)
position = self.get_position_x(tex.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
@@ -630,8 +630,8 @@ 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]
position = self.get_position_x(SCREEN_WIDTH, current_ms, note.hit_ms, note.pixels_per_frame_x)
if position < GameScreen.JUDGE_X + 650:
position = self.get_position_x(tex.screen_width, current_ms, note.hit_ms, note.pixels_per_frame_x)
if position < GameScreen.JUDGE_X + (650 * tex.screen_scale):
self.current_notes_draw.pop(0)
def note_manager(self, current_ms: float, background: Optional[Background]):
@@ -1000,36 +1000,39 @@ 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(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_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
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(SCREEN_WIDTH, current_ms, tail.load_ms, tail.pixels_per_frame_x)
end_position = self.get_position_x(tex.screen_width, current_ms, tail.load_ms, tail.pixels_per_frame_x)
end_position += self.judge_x
length = end_position - start_position
color = ray.Color(255, head.color, head.color, 255)
y = tex.skin_config["notes"].y
moji_y = tex.skin_config["moji"].y
moji_x = tex.skin_config["moji"].x
if head.display:
if length > 0:
tex.draw_texture('notes', "8", frame=is_big, x=start_position+64, y=192+(self.is_2p*176)+self.judge_y, x2=length-47, color=color)
tex.draw_texture('notes', "8", frame=is_big, x=start_position+(tex.textures["notes"]["8"].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+64, y=192+(self.is_2p*176)+self.judge_y, color=color)
tex.draw_texture('notes', "drumroll_big_tail", x=end_position+tex.textures["notes"]["drumroll_big_tail"].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+64, y=192+(self.is_2p*176)+self.judge_y, color=color)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=192+(self.is_2p*176)+self.judge_y, color=color)
tex.draw_texture('notes', "drumroll_tail", x=end_position+tex.textures["notes"]["drumroll_tail"].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', 'moji_drumroll_mid', x=start_position + 60, y=323+(self.is_2p*176)+self.judge_y, x2=length)
tex.draw_texture('notes', 'moji', frame=head.moji, x=(start_position - (168//2)) + 64, y=323+(self.is_2p*176)+self.judge_y)
tex.draw_texture('notes', 'moji', frame=tail.moji, x=(end_position - (168//2)) + 32, y=323+(self.is_2p*176)+self.judge_y)
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + tex.skin_config["moji_drumroll"].x, 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 - tex.skin_config["moji_drumroll"].width, 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 = 12
start_position = self.get_position_x(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_x)
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
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(SCREEN_WIDTH, current_ms, tail.load_ms, tail.pixels_per_frame_x)
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 = 349 + self.judge_x
pause_position = tex.skin_config["balloon_pause_position"].x + self.judge_x
if current_ms >= tail.hit_ms:
position = end_position
elif current_ms >= head.hit_ms:
@@ -1037,8 +1040,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=192+(self.is_2p*176)+self.judge_y)
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+128, y=192+(self.is_2p*176)+self.judge_y)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset, y=tex.skin_config["notes"].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=tex.skin_config["notes"].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"""
@@ -1048,7 +1051,7 @@ class Player:
for bar in reversed(self.current_bars):
if not bar.display:
continue
x_position = self.get_position_x(SCREEN_WIDTH, current_ms, bar.load_ms, bar.pixels_per_frame_x)
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
@@ -1060,7 +1063,7 @@ class Player:
angle = math.degrees(math.atan2(bar.pixels_per_frame_y, bar.pixels_per_frame_x))
else:
angle = 0
tex.draw_texture('notes', str(bar.type), frame=frame, x=x_position+60, y=y_position+190+(self.is_2p*176), rotation=angle)
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)
def draw_notes(self, current_ms: float, start_ms: float):
@@ -1090,10 +1093,10 @@ class Player:
else:
effective_ms = current_ms
x_position = self.get_position_x(SCREEN_WIDTH, effective_ms, note.load_ms, note.pixels_per_frame_x)
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)
else:
x_position = self.get_position_x(SCREEN_WIDTH, current_ms, note.load_ms, note.pixels_per_frame_x)
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
@@ -1101,13 +1104,13 @@ class Player:
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 - (168//2) + 64, y=323 + y_position+(self.is_2p*176))
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+192+(self.is_2p*176), center=True)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position+(self.is_2p*176))
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, SCREEN_WIDTH//2 - (ray.measure_text(self.current_notes_draw[0].lyric, 40)//2), SCREEN_HEIGHT - 50, 40, ray.BLUE)
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)
def draw_modifiers(self):
@@ -1171,13 +1174,13 @@ class Player:
# Group 7: Player-specific elements
if not self.modifiers.auto:
if self.is_2p:
self.nameplate.draw(-62, 371)
self.nameplate.draw(tex.skin_config["game_nameplate_1p"].x, tex.skin_config["game_nameplate_1p"].y)
else:
self.nameplate.draw(-62, 285)
self.nameplate.draw(tex.skin_config["game_nameplate_2p"].x, tex.skin_config["game_nameplate_2p"].y)
else:
tex.draw_texture('lane', 'auto_icon', index=self.is_2p)
self.draw_modifiers()
self.chara.draw(y=(self.is_2p*536))
self.chara.draw(y=(self.is_2p*tex.skin_config["game_2p_offset"].y))
# Group 8: Special animations and counters
if self.drumroll_counter is not None:
@@ -1334,13 +1337,15 @@ class GaugeHitEffect:
self.color = ray.fade(ray.YELLOW, self.circle_fadein.attribute)
self.is_finished = False
self.width = tex.textures["gauge"]["hit_effect"].width
self.texture_color = ray.WHITE
self.dest_width = 152
self.dest_height = 152
self.origin = ray.Vector2(76, 76) # 152/2
self.dest_width = self.width * tex.screen_scale
self.dest_height = self.width * tex.screen_scale
self.origin = ray.Vector2(self.width//2, self.width//2)
self.rotation_angle = 0
self.x2_pos = -152
self.y2_pos = -152
self.x2_pos = -self.width
self.y2_pos = -self.width
# Cache for texture selection
self.circle_texture = 'hit_effect_circle_big' if self.is_big else 'hit_effect_circle'
@@ -1385,11 +1390,11 @@ class GaugeHitEffect:
if abs(resize_val - getattr(self, '_last_resize_calc', -1)) > 0.005:
self._last_resize_calc = resize_val
self.texture_color = self._get_texture_color_for_resize(resize_val)
self.dest_width = 152 * resize_val
self.dest_height = 152 * resize_val
self.dest_width = self.width * resize_val
self.dest_height = self.width * resize_val
self.origin = ray.Vector2(self.dest_width / 2, self.dest_height / 2)
self.x2_pos = -152 + (152 * resize_val)
self.y2_pos = -152 + (152 * resize_val)
self.x2_pos = -self.width + (self.width * resize_val)
self.y2_pos = -self.width + (self.width * resize_val)
self.rotation_angle = self.rotation.attribute * 100
@@ -1412,8 +1417,9 @@ class GaugeHitEffect:
center=True)
# Note type texture
pos_data = tex.skin_config["gauge_hit_effect_note"]
tex.draw_texture('notes', str(self.note_type),
x=1158, y=101+(self.is_2p*(435-32)),
x=pos_data.x, y=pos_data.y+(self.is_2p*(pos_data.height)),
fade=fade_value)
# Circle effect texture (use cached texture name)
@@ -1434,12 +1440,12 @@ class NoteArc:
self.explosion_point_index = 0
self.points_per_explosion = 5
curve_height = 425
self.start_x, self.start_y = start_x + 350, start_y + 192
self.end_x, self.end_y = 1158, 101
curve_height = 425 * tex.screen_scale
self.start_x, self.start_y = start_x + (350 * tex.screen_scale), start_y + (192 * tex.screen_scale)
self.end_x, self.end_y = 1158 * tex.screen_scale, 101 * tex.screen_scale
if self.player_num == PlayerNum.P2:
self.start_y += 176
self.end_y += 372
self.start_y += (176 * tex.screen_scale)
self.end_y += (372 * tex.screen_scale)
self.explosion_x = self.start_x
self.explosion_y = self.start_y
@@ -1511,12 +1517,12 @@ class NoteArc:
if crop_width > 0:
src = ray.Rectangle(crop_start_x, 0, crop_width, rainbow_height)
mirror = 'vertical' if self.player_num == PlayerNum.P2 else ''
y = 435 if self.player_num == PlayerNum.P2 else 0
y = (435 * tex.screen_scale) if self.player_num == PlayerNum.P2 else 0
ray.begin_shader_mode(mask_shader)
tex.draw_texture('balloon', 'rainbow_mask', src=src, x=crop_start_x, x2=-rainbow.width + crop_width, mirror=mirror, y=y)
ray.end_shader_mode()
tex.draw_texture('balloon', 'explosion', x=self.explosion_x, y=self.explosion_y-30, frame=self.explosion_anim.attribute)
tex.draw_texture('balloon', 'explosion', x=self.explosion_x, y=self.explosion_y-(30 * tex.screen_scale), frame=self.explosion_anim.attribute)
'''
elif self.is_big:
tex.draw_texture('hit_effect', 'explosion', x=self.explosion_x, y=self.explosion_y-30, frame=self.explosion_anim.attribute)
@@ -1552,9 +1558,9 @@ class DrumrollCounter:
color = ray.fade(ray.WHITE, self.fade_animation.attribute)
tex.draw_texture('drumroll_counter', 'bubble', color=color, index=self.is_2p)
counter = str(self.drumroll_count)
total_width = len(counter) * 52
total_width = len(counter) * tex.skin_config["drumroll_counter_margin"].x
for i, digit in enumerate(counter):
tex.draw_texture('drumroll_counter', 'counter', color=color, index=self.is_2p, frame=int(digit), x=-(total_width//2)+(i*52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
tex.draw_texture('drumroll_counter', 'counter', color=color, index=self.is_2p, frame=int(digit), x=-(total_width//2)+(i*tex.skin_config["drumroll_counter_margin"].x), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
class BalloonAnimation:
"""Draws a Balloon"""
@@ -1594,16 +1600,16 @@ class BalloonAnimation:
def draw(self):
if self.is_popped:
tex.draw_texture('balloon', 'pop', frame=7, color=self.color, y=self.is_2p*176)
tex.draw_texture('balloon', 'pop', frame=7, color=self.color, y=self.is_2p*tex.skin_config["2p_offset"].y)
elif self.balloon_count >= 1:
balloon_index = min(6, (self.balloon_count - 1) * 6 // self.balloon_total)
tex.draw_texture('balloon', 'pop', frame=balloon_index, color=self.color, index=self.player_num-1, y=self.is_2p*176)
tex.draw_texture('balloon', 'pop', frame=balloon_index, color=self.color, index=self.player_num-1, y=self.is_2p*tex.skin_config["2p_offset"].y)
if self.balloon_count > 0:
tex.draw_texture('balloon', 'bubble', y=self.is_2p*410, mirror='vertical' if self.is_2p else '')
tex.draw_texture('balloon', 'bubble', y=self.is_2p*(410 * tex.screen_scale), mirror='vertical' if self.is_2p else '')
counter = str(max(0, self.balloon_total - self.balloon_count + 1))
total_width = len(counter) * 52
total_width = len(counter) * tex.skin_config["drumroll_counter_margin"].x
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+(self.is_2p*435), y2=self.stretch_animation.attribute)
tex.draw_texture('balloon', 'counter', frame=int(digit), color=self.color, x=-(total_width // 2) + (i * tex.skin_config["drumroll_counter_margin"].x), y=-self.stretch_animation.attribute+(self.is_2p*435), y2=self.stretch_animation.attribute)
class KusudamaAnimation:
"""Draws a Kusudama"""
@@ -1667,9 +1673,9 @@ class KusudamaAnimation:
counter = str(max(0, self.balloon_total - self.balloon_count))
if counter == '0':
return
total_width = len(counter) * 150
total_width = len(counter) * tex.skin_config["kusudama_counter_margin"].x
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)
tex.draw_texture('kusudama', 'counter', frame=int(digit), x=-(total_width // 2) + (i * tex.skin_config["kusudama_counter_margin"].x), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
class Combo:
"""Displays the current combo"""
@@ -1725,21 +1731,21 @@ class Combo:
counter = self._cached_combo_str
if self.combo < 100:
margin = 30
margin = tex.skin_config["combo_margin"].x
total_width = len(counter) * margin
tex.draw_texture('combo', 'combo', index=self.is_2p)
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, index=self.is_2p)
else:
margin = 35
margin = tex.skin_config["combo_margin"].y
total_width = len(counter) * margin
tex.draw_texture('combo', 'combo_100', index=self.is_2p)
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, index=self.is_2p)
glimmer_positions = [(225, 210), (200, 230), (250, 230)]
glimmer_positions = [(225 * tex.screen_scale, 210 * tex.screen_scale), (200 * tex.screen_scale, 230 * tex.screen_scale), (250 * tex.screen_scale, 230 * tex.screen_scale)]
for j, (x, y) in enumerate(glimmer_positions):
for i in range(3):
tex.draw_texture('combo', 'gleam', x=x+(i*30), y=y+self.glimmer_dict[j] + (self.is_2p*176), color=self.color[j])
tex.draw_texture('combo', 'gleam', x=x+(i*tex.skin_config["combo_margin"].x), y=y+self.glimmer_dict[j] + (self.is_2p*tex.skin_config["2p_offset"].y), color=self.color[j])
class ScoreCounter:
"""Displays the total score"""
@@ -1765,8 +1771,8 @@ class ScoreCounter:
self._cached_score_str = str(self.score)
counter = self._cached_score_str
x, y = 150, 185 + (self.is_2p*310)
margin = 20
x, y = 150 * tex.screen_scale, (185 * tex.screen_scale) + (self.is_2p*310*tex.screen_scale)
margin = tex.skin_config["score_counter_margin"].x
total_width = len(counter) * margin
start_x = x - total_width
for i, digit in enumerate(counter):
@@ -1800,7 +1806,7 @@ class ScoreCounterAnimation:
# Cache string and layout calculations
self.counter_str = str(counter)
self.margin = 20
self.margin = tex.skin_config["score_counter_margin"].x
self.total_width = len(self.counter_str) * self.margin
self.y_pos_list = []
@@ -1834,14 +1840,14 @@ class ScoreCounterAnimation:
elif self.move_animation_2.is_finished:
y = self.move_animation_3.attribute
else:
y = 148
y = 148 * tex.screen_scale
y_offset = y * self.direction
tex.draw_texture('lane', 'score_number',
frame=int(digit),
x=start_x + (i * self.margin),
y=y_offset + (self.is_2p * 680),
y=y_offset + (self.is_2p * 680 * tex.screen_scale),
color=self.color)
class SongInfo:
@@ -1849,7 +1855,7 @@ class SongInfo:
def __init__(self, song_name: str, genre: int):
self.song_name = song_name
self.genre = genre
self.song_title = OutlinedText(song_name, 40, ray.WHITE, outline_thickness=5)
self.song_title = OutlinedText(song_name, tex.skin_config["song_info"].font_size, ray.WHITE, outline_thickness=5)
self.fade = tex.get_animation(3)
def update(self, current_ms: float):
@@ -1858,8 +1864,8 @@ class SongInfo:
def draw(self):
tex.draw_texture('song_info', 'song_num', fade=self.fade.attribute, frame=global_data.songs_played % 4)
text_x = 1252 - self.song_title.texture.width
text_y = 50 - self.song_title.texture.height//2
text_x = tex.skin_config["song_info"].x - self.song_title.texture.width
text_y = tex.skin_config["song_info"].y - self.song_title.texture.height//2
self.song_title.draw(outline_color=ray.BLACK, x=text_x, y=text_y, color=ray.fade(ray.WHITE, 1 - self.fade.attribute))
if self.genre < 9:
@@ -1884,19 +1890,19 @@ class ResultTransition:
def draw(self):
x = 0
screen_width = 1280
while x < screen_width:
while x < tex.screen_width:
tex_height = global_tex.textures['result_transition']['1p_shutter_footer'].height
if self.player_num == PlayerNum.TWO_PLAYER:
global_tex.draw_texture('result_transition', '1p_shutter', frame=0, x=x, y=-720 + self.move.attribute)
global_tex.draw_texture('result_transition', '2p_shutter', frame=0, x=x, y=720 - self.move.attribute)
global_tex.draw_texture('result_transition', '1p_shutter_footer', x=x, y=-432 + self.move.attribute)
global_tex.draw_texture('result_transition', '2p_shutter_footer', x=x, y=1008 - self.move.attribute)
global_tex.draw_texture('result_transition', '1p_shutter', frame=0, x=x, y=-tex.screen_height + self.move.attribute)
global_tex.draw_texture('result_transition', '2p_shutter', frame=0, x=x, y=tex.screen_height - self.move.attribute)
global_tex.draw_texture('result_transition', '1p_shutter_footer', x=x, y=-tex_height + self.move.attribute)
global_tex.draw_texture('result_transition', '2p_shutter_footer', x=x, y=tex.screen_height + tex_height - self.move.attribute)
else:
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter', frame=0, x=x, y=-720 + self.move.attribute)
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter', frame=0, x=x, y=720 - self.move.attribute)
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter_footer', x=x, y=-432 + self.move.attribute)
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter_footer', x=x, y=1008 - self.move.attribute)
x += 256
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter', frame=0, x=x, y=-tex.screen_height + self.move.attribute)
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter', frame=0, x=x, y=tex.screen_height - self.move.attribute)
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter_footer', x=x, y=-tex_height + self.move.attribute)
global_tex.draw_texture('result_transition', f'{self.player_num}p_shutter_footer', x=x, y=tex.screen_height + tex_height - self.move.attribute)
x += tex.screen_width // 5
class GogoTime:
"""Displays the Gogo Time fire and fireworks"""
@@ -1957,14 +1963,14 @@ class ComboAnnounce:
thousands_offset = -110
hundreds_offset = 20
if self.combo % 1000 == 0:
tex.draw_texture('combo', 'announce_number', frame=thousands-1, x=-23, fade=fade, index=self.is_2p)
tex.draw_texture('combo', 'announce_add', frame=0, x=435, fade=fade, index=self.is_2p)
tex.draw_texture('combo', 'announce_number', frame=thousands-1, x=-23 * tex.screen_scale, fade=fade, index=self.is_2p)
tex.draw_texture('combo', 'announce_add', frame=0, x=435 * tex.screen_scale, fade=fade, index=self.is_2p)
else:
if thousands <= 5:
tex.draw_texture('combo', 'announce_add', frame=thousands, x=429 + thousands_offset, fade=fade, index=self.is_2p)
tex.draw_texture('combo', 'announce_add', frame=thousands, x=429 * tex.screen_scale + thousands_offset, fade=fade, index=self.is_2p)
if remaining_hundreds > 0:
tex.draw_texture('combo', 'announce_number', frame=remaining_hundreds-1, x=hundreds_offset, fade=fade, index=self.is_2p)
text_offset = -30
text_offset = -30 * tex.screen_scale
else:
text_offset = 0
tex.draw_texture('combo', 'announce_number', frame=self.combo // 100 - 1, x=0, fade=fade, index=self.is_2p)
@@ -2016,7 +2022,7 @@ class BranchIndicator:
else:
tex.draw_texture('branch', 'level_up', scale=self.level_scale.attribute, fade=self.level_fade.attribute, center=True, index=self.is_2p)
tex.draw_texture('branch', self.diff_2, y=(self.diff_down.attribute - self.diff_up.attribute) * self.direction, fade=self.diff_fade.attribute, index=self.is_2p)
tex.draw_texture('branch', self.difficulty, y=(self.diff_up.attribute * (self.direction*-1)) - (70*self.direction*-1), fade=1 - self.diff_fade.attribute, index=self.is_2p)
tex.draw_texture('branch', self.difficulty, y=(self.diff_up.attribute * (self.direction*-1)) - ((70 * tex.screen_scale)*self.direction*-1), fade=1 - self.diff_fade.attribute, index=self.is_2p)
class FailAnimation:
"""Animates the fail effect"""
@@ -2062,8 +2068,8 @@ class FailAnimation:
tex.draw_texture('ending_anim', 'fail', fade=self.text_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_l_' + self.name, x=-self.bachio_move_out.attribute - (self.bachio_up.attribute/2), y=self.bachio_down.attribute - self.bachio_up.attribute, frame=self.frame, fade=self.bachio_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_r_' + self.name, x=self.bachio_move_out.attribute + (self.bachio_up.attribute/2), y=self.bachio_down.attribute - self.bachio_up.attribute, frame=self.frame, fade=self.bachio_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_boom', index=0, fade=self.bachio_boom_fade_in.attribute, center=True, scale=self.bachio_boom_scale.attribute, y=(self.is_2p*176))
tex.draw_texture('ending_anim', 'bachio_boom', index=1, fade=self.bachio_boom_fade_in.attribute, center=True, scale=self.bachio_boom_scale.attribute, y=(self.is_2p*176))
tex.draw_texture('ending_anim', 'bachio_boom', index=0, fade=self.bachio_boom_fade_in.attribute, center=True, scale=self.bachio_boom_scale.attribute, y=(self.is_2p*tex.skin_config["2p_offset"].y))
tex.draw_texture('ending_anim', 'bachio_boom', index=1, fade=self.bachio_boom_fade_in.attribute, center=True, scale=self.bachio_boom_scale.attribute, y=(self.is_2p*tex.skin_config["2p_offset"].y))
class ClearAnimation:
"""Animates the clear effect"""
@@ -2112,7 +2118,7 @@ class ClearAnimation:
tex.draw_texture('ending_anim', 'clear', index=self.is_2p)
else:
for i in range(4, -1, -1):
tex.draw_texture('ending_anim', 'clear_separated', frame=i, fade=self.clear_separate_fade_in[i].attribute, x=i*60, y=-self.clear_separate_stretch[i].attribute, y2=self.clear_separate_stretch[i].attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'clear_separated', frame=i, fade=self.clear_separate_fade_in[i].attribute, x=i*60 * tex.screen_scale, y=-self.clear_separate_stretch[i].attribute, y2=self.clear_separate_stretch[i].attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'clear_highlight', fade=self.clear_highlight_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_l_' + self.name, x=-self.bachio_move_out.attribute, frame=self.frame, fade=self.bachio_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_r_' + self.name, x=self.bachio_move_out.attribute, frame=self.frame, fade=self.bachio_fade_in.attribute, index=self.is_2p)
@@ -2188,7 +2194,7 @@ class FCAnimation:
tex.draw_texture('ending_anim', 'fan_r', frame=self.fan_texture_change.attribute, fade=self.fan_fade_in.attribute, index=self.is_2p)
else:
for i in range(4, -1, -1):
tex.draw_texture('ending_anim', 'clear_separated', frame=i, fade=self.clear_separate_fade_in[i].attribute, x=i*60, y=-self.clear_separate_stretch[i].attribute, y2=self.clear_separate_stretch[i].attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'clear_separated', frame=i, fade=self.clear_separate_fade_in[i].attribute, x=i*60 * tex.screen_scale, y=-self.clear_separate_stretch[i].attribute, y2=self.clear_separate_stretch[i].attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'clear_highlight', fade=self.clear_highlight_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_l_' + self.name, x=(-self.bachio_move_out.attribute - self.bachio_move_out_2.attribute)*1.15, y=-self.bachio_move_up.attribute, frame=self.frame, fade=self.bachio_fade_in.attribute, index=self.is_2p)
tex.draw_texture('ending_anim', 'bachio_r_' + self.name, x=(self.bachio_move_out.attribute + self.bachio_move_out_2.attribute)*1.15, y=-self.bachio_move_up.attribute, frame=self.frame, fade=self.bachio_fade_in.attribute, index=self.is_2p)
@@ -2207,7 +2213,7 @@ class JudgeCounter:
self.ok = ok
self.bad = bad
self.drumrolls = drumrolls
def draw_counter(self, counter: float, x: int, y: int, margin: int, color: ray.Color):
def draw_counter(self, counter: float, x: float, y: float, margin: float, color: ray.Color):
counter_str = str(rounded(counter))
counter_len = len(counter_str)
for i, digit in enumerate(counter_str):
@@ -2224,14 +2230,15 @@ class JudgeCounter:
total_notes = self.good + self.ok + self.bad
if total_notes == 0:
total_notes = 1
self.draw_counter(self.good / total_notes * 100, 260, 440, 23, self.orange)
self.draw_counter(self.ok / total_notes * 100, 260, 477, 23, self.orange)
self.draw_counter(self.bad / total_notes * 100, 260, 515, 23, self.orange)
self.draw_counter((self.good + self.ok) / total_notes * 100, 270, 388, 23, self.orange)
self.draw_counter(self.good, 180, 440, 23, self.white)
self.draw_counter(self.ok, 180, 477, 23, self.white)
self.draw_counter(self.bad, 180, 515, 23, self.white)
self.draw_counter(self.drumrolls, 180, 577, 23, self.white)
margin = tex.skin_config["judge_counter_margin"].x
self.draw_counter(self.good / total_notes * 100, tex.skin_config["judge_counter_1"].x, tex.skin_config["judge_counter_1"].y, margin, self.orange)
self.draw_counter(self.ok / total_notes * 100, tex.skin_config["judge_counter_1"].x, tex.skin_config["judge_counter_3"].y, margin, self.orange)
self.draw_counter(self.bad / total_notes * 100, tex.skin_config["judge_counter_1"].x, tex.skin_config["judge_counter_4"].x, margin, self.orange)
self.draw_counter((self.good + self.ok) / total_notes * 100, tex.skin_config["judge_counter_3"].x, tex.skin_config["judge_counter_4"].y, margin, self.orange)
self.draw_counter(self.good, tex.skin_config["judge_counter_2"].x, tex.skin_config["judge_counter_1"].y, margin, self.white)
self.draw_counter(self.ok, tex.skin_config["judge_counter_2"].x, tex.skin_config["judge_counter_3"].y, margin, self.white)
self.draw_counter(self.bad, tex.skin_config["judge_counter_2"].x, tex.skin_config["judge_counter_4"].x, margin, self.white)
self.draw_counter(self.drumrolls, tex.skin_config["judge_counter_2"].x, tex.skin_config["judge_counter_4"].width, margin, self.white)
class Gauge:
"""The player's gauge"""
@@ -2342,12 +2349,13 @@ class Gauge:
tex.draw_texture('gauge', f'{self.player_num}p_unfilled' + self.string_diff, index=self.is_2p, mirror=mirror)
gauge_length = int(self.gauge_length)
clear_point = self.clear_start[self.difficulty]
tex.draw_texture('gauge', f'{self.player_num}p_bar', x2=min(gauge_length*8, (clear_point - 1)*8)-8, index=self.is_2p)
bar_width = tex.textures["gauge"][f"{self.player_num}p_bar"].width
tex.draw_texture('gauge', f'{self.player_num}p_bar', x2=min(gauge_length*bar_width, (clear_point - 1)*bar_width)-bar_width, index=self.is_2p)
if gauge_length >= clear_point - 1:
tex.draw_texture('gauge', 'bar_clear_transition', x=(clear_point - 1)*8, index=self.is_2p, mirror=mirror)
tex.draw_texture('gauge', 'bar_clear_transition', x=(clear_point - 1)*bar_width, index=self.is_2p, mirror=mirror)
if gauge_length > clear_point:
tex.draw_texture('gauge', 'bar_clear_top', x=(clear_point) * 8, x2=(gauge_length-clear_point)*8, index=self.is_2p, mirror=mirror)
tex.draw_texture('gauge', 'bar_clear_bottom', x=(clear_point) * 8, x2=(gauge_length-clear_point)*8, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_top', x=(clear_point) * bar_width, x2=(gauge_length-clear_point)*bar_width, index=self.is_2p, mirror=mirror)
tex.draw_texture('gauge', 'bar_clear_bottom', x=(clear_point) * bar_width, x2=(gauge_length-clear_point)*bar_width, index=self.is_2p)
# Rainbow effect for full gauge
if gauge_length == self.gauge_max and self.rainbow_fade_in is not None:
@@ -2356,11 +2364,11 @@ class Gauge:
tex.draw_texture('gauge', 'rainbow' + self.string_diff, frame=self.rainbow_animation.attribute, fade=self.rainbow_fade_in.attribute, index=self.is_2p, mirror=mirror)
if self.gauge_update_anim is not None and gauge_length <= self.gauge_max and gauge_length > self.previous_length:
if gauge_length == self.clear_start[self.difficulty]:
tex.draw_texture('gauge', 'bar_clear_transition_fade', x=gauge_length*8, fade=self.gauge_update_anim.attribute, index=self.is_2p, mirror=mirror)
tex.draw_texture('gauge', 'bar_clear_transition_fade', x=gauge_length*bar_width, fade=self.gauge_update_anim.attribute, index=self.is_2p, mirror=mirror)
elif gauge_length > self.clear_start[self.difficulty]:
tex.draw_texture('gauge', 'bar_clear_fade', x=gauge_length*8, fade=self.gauge_update_anim.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_fade', x=gauge_length*bar_width, fade=self.gauge_update_anim.attribute, index=self.is_2p)
else:
tex.draw_texture('gauge', f'{self.player_num}p_bar_fade', x=gauge_length*8, fade=self.gauge_update_anim.attribute, index=self.is_2p)
tex.draw_texture('gauge', f'{self.player_num}p_bar_fade', x=gauge_length*bar_width, fade=self.gauge_update_anim.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'overlay' + self.string_diff, fade=0.15, index=self.is_2p, mirror=mirror)
# Draw clear status indicators

View File

@@ -7,7 +7,7 @@ from libs.animation import Animation
from libs.global_objects import AllNetIcon
from libs.screen import Screen
from libs.song_hash import build_song_hashes
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex
from libs.texture import tex
from libs.utils import get_current_ms, global_data
from libs.file_navigator import navigator
@@ -17,8 +17,8 @@ logger = logging.getLogger(__name__)
class LoadScreen(Screen):
def __init__(self, name: str):
super().__init__(name)
self.width = SCREEN_WIDTH
self.height = SCREEN_HEIGHT
self.width = tex.screen_width
self.height = tex.screen_height
self.songs_loaded = False
self.navigator_started = False
self.loading_complete = False

View File

@@ -12,7 +12,7 @@ from libs.global_data import Modifiers, PlayerNum, global_data
from libs.tja import Balloon, Drumroll, Note, NoteType, TJAParser, apply_modifiers
from libs.utils import get_current_ms
from libs.texture import tex
from scenes.game import DrumHitEffect, DrumType, GameScreen, JudgeCounter, LaneHitEffect, Player, SCREEN_WIDTH, Side
from scenes.game import DrumHitEffect, DrumType, GameScreen, JudgeCounter, LaneHitEffect, Player, Side
logger = logging.getLogger(__name__)
@@ -23,8 +23,8 @@ class PracticeGameScreen(GameScreen):
def init_tja(self, song: Path):
"""Initialize the TJA file"""
self.tja = TJAParser(song, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
self.scrobbling_tja = TJAParser(song, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
self.tja = TJAParser(song, start_delay=self.start_delay, distance=tex.screen_width - GameScreen.JUDGE_X)
self.scrobbling_tja = TJAParser(song, start_delay=self.start_delay, distance=tex.screen_width - GameScreen.JUDGE_X)
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')
@@ -155,41 +155,44 @@ class PracticeGameScreen(GameScreen):
time_diff = load_ms - self.scrobble_time - self.scrobble_move.attribute
else:
time_diff = load_ms - current_ms
return int(width + pixels_per_frame * 0.06 * time_diff - 64)
return int(width + pixels_per_frame * 0.06 * time_diff - (tex.textures["notes"]["1"].width//2))
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"""
time_diff = load_ms - current_ms
return int((pixels_per_frame * 0.06 * time_diff) + ((866 * pixels_per_frame) / pixels_per_frame_x))
return int((pixels_per_frame * 0.06 * time_diff) + ((self.tja.distance * pixels_per_frame) / pixels_per_frame_x))
def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int, index: int):
"""Draws a drumroll in the player's lane"""
start_position = self.get_position_x(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_x)
start_position = self.get_position_x(tex.screen_width, current_ms, head.load_ms, head.pixels_per_frame_x)
tail = next((note for note in self.scrobble_note_list if note.index == index+1), self.scrobble_note_list[index+1])
is_big = int(head.type == NoteType.ROLL_HEAD_L)
end_position = self.get_position_x(SCREEN_WIDTH, current_ms, tail.load_ms, tail.pixels_per_frame_x)
end_position = self.get_position_x(tex.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)
y = tex.skin_config["notes"].y
moji_y = tex.skin_config["moji"].y
moji_x = tex.skin_config["moji"].x
if head.display:
if length > 0:
tex.draw_texture('notes', "8", frame=is_big, x=start_position+64, y=192, x2=length-47, color=color)
tex.draw_texture('notes', "8", frame=is_big, x=start_position+(tex.textures["notes"]["8"].width//2), y=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+64, y=192, color=color)
tex.draw_texture('notes', "drumroll_big_tail", x=end_position+tex.textures["notes"]["drumroll_big_tail"].width//2, y=y, color=color)
else:
tex.draw_texture('notes', "drumroll_tail", x=end_position+64, 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', "drumroll_tail", x=end_position+tex.textures["notes"]["drumroll_tail"].width//2, y=y, color=color)
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=y, color=color)
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=tail.moji, x=(end_position - (168//2)) + 32, y=323)
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + tex.skin_config["moji_drumroll"].x, y=moji_y, x2=length)
tex.draw_texture('notes', 'moji', frame=head.moji, x=start_position - moji_x, y=moji_y)
tex.draw_texture('notes', 'moji', frame=tail.moji, x=end_position - tex.skin_config["moji_drumroll"].width, y=moji_y)
def draw_balloon(self, current_ms: float, head: Balloon, current_eighth: int, index: int):
"""Draws a balloon in the player's lane"""
offset = 12
start_position = self.get_position_x(SCREEN_WIDTH, current_ms, head.load_ms, head.pixels_per_frame_x)
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)
tail = next((note for note in self.scrobble_note_list if note.index == index+1), self.scrobble_note_list[index+1])
end_position = self.get_position_x(SCREEN_WIDTH, current_ms, tail.load_ms, tail.pixels_per_frame_x)
pause_position = 349
end_position = self.get_position_x(tex.screen_width, current_ms, tail.load_ms, tail.pixels_per_frame_x)
pause_position = tex.skin_config["balloon_pause_position"].x
if current_ms >= tail.hit_ms:
position = end_position
elif current_ms >= head.hit_ms:
@@ -197,23 +200,23 @@ class PracticeGameScreen(GameScreen):
else:
position = start_position
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', str(head.type), frame=current_eighth % 2, x=position-offset, y=tex.skin_config["notes"].y)
tex.draw_texture('notes', '10', frame=current_eighth % 2, x=position-offset+tex.textures["notes"]["10"].width, y=tex.skin_config["notes"].y)
def draw_scrobble_list(self):
bar_draws = []
for bar in reversed(self.bars):
if not bar.display:
continue
x_position = self.get_position_x(SCREEN_WIDTH, self.current_ms, bar.load_ms, bar.pixels_per_frame_x)
x_position = self.get_position_x(tex.screen_width, self.current_ms, bar.load_ms, bar.pixels_per_frame_x)
y_position = self.get_position_y(self.current_ms, bar.load_ms, bar.pixels_per_frame_y, bar.pixels_per_frame_x)
if x_position < 236 or x_position > SCREEN_WIDTH:
if x_position < tex.skin_config["past_judge_circle"].x or x_position > tex.screen_width:
continue
if hasattr(bar, 'is_branch_start'):
frame = 1
else:
frame = 0
bar_draws.append((str(bar.type), frame, x_position+60, y_position+190))
bar_draws.append((str(bar.type), frame, x_position + tex.skin_config["moji_drumroll"].x, y_position+tex.skin_config["moji_drumroll"].y))
for bar_type, frame, x, y in bar_draws:
tex.draw_texture('notes', bar_type, frame=frame, x=x, y=y)
@@ -225,27 +228,27 @@ class PracticeGameScreen(GameScreen):
if isinstance(note, Drumroll):
self.draw_drumroll(self.current_ms, note, 0, note.index)
elif isinstance(note, Balloon) and not note.is_kusudama:
x_position = self.get_position_x(SCREEN_WIDTH, self.current_ms, note.load_ms, note.pixels_per_frame_x)
x_position = self.get_position_x(tex.screen_width, self.current_ms, note.load_ms, note.pixels_per_frame_x)
y_position = self.get_position_y(self.current_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
if x_position < 236 or x_position > SCREEN_WIDTH:
if x_position < tex.skin_config["past_judge_circle"].x or x_position > tex.screen_width:
continue
self.draw_balloon(self.current_ms, note, 0, note.index)
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 - tex.skin_config["moji"].x, y=tex.skin_config["moji"].y + y_position)
else:
x_position = self.get_position_x(SCREEN_WIDTH, self.current_ms, note.load_ms, note.pixels_per_frame_x)
x_position = self.get_position_x(tex.screen_width, self.current_ms, note.load_ms, note.pixels_per_frame_x)
y_position = self.get_position_y(self.current_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
if x_position < 236 or x_position > SCREEN_WIDTH:
if x_position < tex.skin_config["past_judge_circle"].x or x_position > tex.screen_width:
continue
if note.display:
tex.draw_texture('notes', str(note.type), x=x_position, y=y_position+192, center=True)
tex.draw_texture('notes', str(note.type), x=x_position, y=y_position+tex.skin_config["notes"].y, center=True)
color = ray.WHITE
if note.index in self.player_1.input_log:
if self.player_1.input_log[note.index] == 'GOOD':
color = ray.Color(255, 233, 0, 255)
elif self.player_1.input_log[note.index] == 'BAD':
color = ray.Color(34, 189, 243, 255)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position, color=color)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - tex.skin_config["moji"].x, y=tex.skin_config["moji"].y + y_position, color=color)
def draw(self):
self.background.draw()
@@ -263,9 +266,9 @@ class PracticeGameScreen(GameScreen):
progress = min((self.scrobble_time + self.scrobble_move.attribute - self.bars[0].hit_ms) / self.player_1.end_time, 1)
else:
progress = min(self.current_ms / self.player_1.end_time, 1)
tex.draw_texture('practice', 'progress_bar', x2=progress * 890)
tex.draw_texture('practice', 'progress_bar', x2=progress * tex.skin_config["practice_progress_bar_width"].width)
for marker in self.markers:
tex.draw_texture('practice', 'gogo_marker', x=((marker - self.bars[0].hit_ms) / self.player_1.end_time) * 890)
tex.draw_texture('practice', 'gogo_marker', x=((marker - self.bars[0].hit_ms) / self.player_1.end_time) * tex.skin_config["practice_progress_bar_width"].width)
self.draw_overlay()
@@ -276,9 +279,9 @@ class PracticePlayer(Player):
self.gauge = None
self.paused = False
def spawn_hit_effects(self, note_type: DrumType, side: Side):
self.lane_hit_effect = LaneHitEffect(note_type, self.is_2p)
self.draw_drum_hit_list.append(PracticeDrumHitEffect(note_type, side, self.is_2p, player_num=self.player_num))
def spawn_hit_effects(self, drum_type: DrumType, side: Side):
self.lane_hit_effect = LaneHitEffect(drum_type, self.is_2p)
self.draw_drum_hit_list.append(PracticeDrumHitEffect(drum_type, side, self.is_2p, player_num=self.player_num))
def draw_overlays(self, mask_shader: ray.Shader):
# Group 4: Lane covers and UI elements (batch similar textures)
@@ -306,13 +309,13 @@ class PracticePlayer(Player):
# Group 7: Player-specific elements
if not self.modifiers.auto:
if self.is_2p:
self.nameplate.draw(-62, 371)
self.nameplate.draw(tex.skin_config["game_nameplate_1p"].x, tex.skin_config["game_nameplate_1p"].y)
else:
self.nameplate.draw(-62, 285)
self.nameplate.draw(tex.skin_config["game_nameplate_2p"].x, tex.skin_config["game_nameplate_2p"].y)
else:
tex.draw_texture('lane', 'auto_icon', index=self.is_2p)
self.draw_modifiers()
self.chara.draw(y=(self.is_2p*536))
self.chara.draw(y=(self.is_2p*tex.skin_config["game_2p_offset"].y))
# Group 8: Special animations and counters
if self.drumroll_counter is not None:
@@ -321,7 +324,6 @@ class PracticePlayer(Player):
self.balloon_anim.draw()
if self.kusudama_anim is not None:
self.kusudama_anim.draw()
#ray.draw_circle(game_screen.width//2, game_screen.height, 300, ray.ORANGE)
def draw(self, ms_from_start: float, start_ms: float, mask_shader: ray.Shader, dan_transition = None):
# Group 1: Background and lane elements

View File

@@ -26,7 +26,7 @@ class State:
class ResultScreen(Screen):
def on_screen_start(self):
super().on_screen_start()
self.song_info = OutlinedText(global_data.session_data[global_data.player_num].song_title, 40, ray.WHITE, outline_thickness=5)
self.song_info = OutlinedText(global_data.session_data[global_data.player_num].song_title, tex.skin_config["song_info_result"].font_size, ray.WHITE, outline_thickness=5)
audio.play_sound('bgm', 'music')
self.fade_in = FadeIn(global_data.player_num)
self.fade_out = tex.get_animation(0)
@@ -34,7 +34,7 @@ class ResultScreen(Screen):
self.allnet_indicator = AllNetIcon()
self.start_ms = get_current_ms()
self.is_skipped = False
self.background = Background(global_data.player_num, 1280)
self.background = Background(global_data.player_num, tex.screen_width)
self.player_1 = ResultPlayer(global_data.player_num, False, False)
def on_screen_end(self, next_screen: str):
@@ -66,13 +66,13 @@ class ResultScreen(Screen):
def draw_overlay(self):
self.fade_in.draw()
ray.draw_rectangle(0, 0, 1280, 720, ray.fade(ray.BLACK, self.fade_out.attribute))
ray.draw_rectangle(0, 0, tex.screen_width, tex.screen_height, ray.fade(ray.BLACK, self.fade_out.attribute))
self.coin_overlay.draw()
self.allnet_indicator.draw()
def draw_song_info(self):
tex.draw_texture('song_info', 'song_num', frame=global_data.songs_played%4)
self.song_info.draw(outline_color=ray.BLACK, x=1252 - self.song_info.texture.width, y=35 - self.song_info.texture.height / 2)
self.song_info.draw(outline_color=ray.BLACK, x=tex.skin_config["song_info_result"].x - self.song_info.texture.width, y=tex.skin_config["song_info_result"].y - self.song_info.texture.height / 2)
def draw(self):
self.background.draw()
@@ -82,25 +82,26 @@ class ResultScreen(Screen):
class Background:
def __init__(self, player_num: PlayerNum, width: int):
def __init__(self, player_num: PlayerNum, width: float):
self.player_num = player_num
self.width = width
def draw(self):
x = 0
footer_height = tex.textures["background"]["footer_1p"].height
if self.player_num == PlayerNum.TWO_PLAYER:
while x < self.width:
tex.draw_texture('background', 'background_1p', x=x, y=-360)
tex.draw_texture('background', 'background_2p', x=x, y=360)
tex.draw_texture('background', 'footer_1p', x=x, y=-72)
tex.draw_texture('background', 'footer_2p', x=x, y=648)
x += 256
tex.draw_texture('background', 'background_1p', x=x, y=-(tex.screen_height//2))
tex.draw_texture('background', 'background_2p', x=x, y=tex.screen_height//2)
tex.draw_texture('background', 'footer_1p', x=x, y=-footer_height)
tex.draw_texture('background', 'footer_2p', x=x, y=tex.screen_height-footer_height)
x += tex.screen_width // 5
else:
while x < self.width:
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=-360)
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=360)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=-72)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=648)
x += 256
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=-(tex.screen_height//2))
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=(tex.screen_height//2))
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=-footer_height)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=tex.screen_height-footer_height)
x += tex.screen_width // 5
tex.draw_texture('background', 'result_text')
class ResultPlayer:
@@ -116,7 +117,7 @@ class ResultPlayer:
self.crown = None
self.state = None
self.high_score_indicator = None
self.chara = Chara2D(int(self.player_num) - 1, 100)
self.chara = Chara2D(int(self.player_num) - 1)
session_data = global_data.session_data[self.player_num]
self.score_animator = ScoreAnimator(session_data.result_data.score)
plate_info = global_data.config[f'nameplate_{self.player_num}p']
@@ -206,7 +207,7 @@ class ResultPlayer:
continue
score_str = str(score)[::-1]
for i, digit in enumerate(score_str):
tex.draw_texture('score', 'judge_num', frame=int(digit), x=-(i*24), index=j+(self.is_2p*5))
tex.draw_texture('score', 'judge_num', frame=int(digit), x=-(i*tex.skin_config["score_info_counter_margin"].x), index=j+(self.is_2p*5))
def draw_total_score(self):
"""
@@ -217,7 +218,7 @@ class ResultPlayer:
tex.draw_texture('score', 'score_shinuchi', index=self.is_2p)
if self.score != '':
for i in range(len(str(self.score))):
tex.draw_texture('score', 'score_num', x=-(i*21), frame=int(str(self.score)[::-1][i]), index=self.is_2p)
tex.draw_texture('score', 'score_num', x=-(i*tex.skin_config["result_score_margin"].x), frame=int(str(self.score)[::-1][i]), index=self.is_2p)
def draw_modifiers(self):
"""Draw the modifiers if enabled."""
@@ -243,7 +244,7 @@ class ResultPlayer:
elif self.state == State.CLEAR:
tex.draw_texture('background', 'gradient_clear', fade=min(0.4, self.fade_in_bottom.attribute))
else:
y = -288 if self.has_2p else 0
y = tex.skin_config["result_2p_offset"].y if self.has_2p else 0
if self.state == State.FAIL:
tex.draw_texture('background', 'gradient_fail', fade=min(0.4, self.fade_in_bottom.attribute), y=y)
elif self.state == State.CLEAR:
@@ -270,10 +271,10 @@ class ResultPlayer:
if self.high_score_indicator is not None:
self.high_score_indicator.draw()
self.chara.draw(y=100+(self.is_2p*360))
self.chara.draw(y=tex.skin_config["result_chara"].y+(self.is_2p*tex.screen_height//2))
if self.gauge is not None:
self.gauge.draw()
self.nameplate.draw(265, 80+(self.is_2p*300))
self.nameplate.draw(tex.skin_config["result_nameplate"].x, tex.skin_config["result_nameplate"].y+(self.is_2p*tex.skin_config["result_nameplate"].height))
class Crown:
"""Represents a crown animation"""
@@ -375,7 +376,7 @@ class BottomCharacters:
def draw_flowers(self):
tex.draw_texture('bottom','flowers', y=-self.flower_up.attribute, frame=self.flower_index)
tex.draw_texture('bottom','flowers', y=-self.flower_up.attribute, frame=self.flower_index, x=792, mirror='horizontal')
tex.draw_texture('bottom','flowers', y=-self.flower_up.attribute, frame=self.flower_index, x=tex.skin_config["result_flowers_offset"].x, mirror='horizontal')
def draw(self):
self.draw_flowers()
@@ -402,20 +403,21 @@ class FadeIn:
def draw(self):
x = 0
footer_height = tex.textures["background"]["footer_1p"].height
if self.player_num == PlayerNum.TWO_PLAYER:
while x < 1280:
tex.draw_texture('background', 'background_1p', x=x, y=-360, fade=self.fadein.attribute)
tex.draw_texture('background', 'background_2p', x=x, y=360, fade=self.fadein.attribute)
tex.draw_texture('background', 'footer_1p', x=x, y=-72, fade=self.fadein.attribute)
tex.draw_texture('background', 'footer_2p', x=x, y=648, fade=self.fadein.attribute)
x += 256
while x < tex.screen_width:
tex.draw_texture('background', 'background_1p', x=x, y=-tex.screen_height//2, fade=self.fadein.attribute)
tex.draw_texture('background', 'background_2p', x=x, y=tex.screen_height//2, fade=self.fadein.attribute)
tex.draw_texture('background', 'footer_1p', x=x, y=-footer_height, fade=self.fadein.attribute)
tex.draw_texture('background', 'footer_2p', x=x, y=tex.screen_height - footer_height, fade=self.fadein.attribute)
x += tex.screen_width // 5
else:
while x < 1280:
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=-360, fade=self.fadein.attribute)
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=360, fade=self.fadein.attribute)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=-72, fade=self.fadein.attribute)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=648, fade=self.fadein.attribute)
x += 256
while x < tex.screen_width:
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=-tex.screen_height//2, fade=self.fadein.attribute)
tex.draw_texture('background', f'background_{self.player_num}p', x=x, y=tex.screen_height//2, fade=self.fadein.attribute)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=-footer_height, fade=self.fadein.attribute)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=tex.screen_height - footer_height, fade=self.fadein.attribute)
x += tex.screen_width // 5
class ScoreAnimator:
"""Animates a number from left to right"""
@@ -461,7 +463,7 @@ class HighScoreIndicator:
def draw(self):
tex.draw_texture('score', 'high_score', y=self.move.attribute, fade=self.fade.attribute, index=self.is_2p)
for i in range(len(str(self.score_diff))):
tex.draw_texture('score', 'high_score_num', x=-(i*14), frame=int(str(self.score_diff)[::-1][i]), y=self.move.attribute, fade=self.fade.attribute, index=self.is_2p)
tex.draw_texture('score', 'high_score_num', x=-(i*tex.skin_config['high_score_indicator_margin'].x), frame=int(str(self.score_diff)[::-1][i]), y=self.move.attribute, fade=self.fade.attribute, index=self.is_2p)
class Gauge:
@@ -504,16 +506,17 @@ class Gauge:
scale = 10/11
tex.draw_texture('gauge', f'{self.player_num}p_unfilled' + self.string_diff, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
gauge_length = int(self.gauge_length)
bar_width = tex.textures["gauge"][f"{self.player_num}p_bar"].width
if gauge_length == self.gauge_max:
if 0 < self.rainbow_animation.attribute < 8:
tex.draw_texture('gauge', 'rainbow' + self.string_diff, frame=self.rainbow_animation.attribute-1, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'rainbow' + self.string_diff, frame=self.rainbow_animation.attribute, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
else:
tex.draw_texture('gauge', f'{self.player_num}p_bar', x2=(gauge_length*8)-48, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', f'{self.player_num}p_bar', x2=(gauge_length*bar_width)-(bar_width*6), scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
if gauge_length >= self.clear_start[self.difficulty] - 1:
tex.draw_texture('gauge', 'bar_clear_transition', x=(self.clear_start[self.difficulty]*8)-56, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_top', x=(self.clear_start[self.difficulty]*8)-48, x2=(gauge_length - self.clear_start[self.difficulty])*8, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_bottom', x=(self.clear_start[self.difficulty]*8)-48, x2=(gauge_length - self.clear_start[self.difficulty])*8, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_transition', x=(self.clear_start[self.difficulty]*bar_width)-(bar_width*7), scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_top', x=(self.clear_start[self.difficulty]*bar_width)-(bar_width*6), x2=(gauge_length - self.clear_start[self.difficulty])*bar_width, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'bar_clear_bottom', x=(self.clear_start[self.difficulty]*bar_width)-(bar_width*6), x2=(gauge_length - self.clear_start[self.difficulty])*bar_width, scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)
tex.draw_texture('gauge', 'overlay' + self.string_diff, scale=scale, fade=min(0.15, self.gauge_fade_in.attribute), index=self.is_2p)
tex.draw_texture('gauge', 'footer', scale=scale, fade=self.gauge_fade_in.attribute, index=self.is_2p)

View File

@@ -9,8 +9,8 @@ from libs.utils import (
is_l_kat_pressed,
is_r_don_pressed,
is_r_kat_pressed,
save_config,
)
from libs.config import save_config
logger = logging.getLogger(__name__)

View File

@@ -12,7 +12,7 @@ from libs.file_navigator import Directory, SongBox, SongFile
from libs.global_data import Difficulty, Modifiers, PlayerNum
from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, Timer
from libs.screen import Screen
from libs.texture import SCREEN_WIDTH, tex
from libs.texture import tex
from libs.transition import Transition
from libs.utils import (
OutlinedText,
@@ -329,15 +329,15 @@ class SongSelectScreen(Screen):
self.draw_background_diffs()
if self.navigator.genre_bg is not None and self.state == State.BROWSING:
self.navigator.genre_bg.draw(95)
self.navigator.genre_bg.draw(tex.skin_config["boxes"].y)
for i, item in enumerate(self.navigator.items):
box = item.box
if -156 <= box.position <= SCREEN_WIDTH + 144:
if box.position <= 500:
box.draw(box.position - int(self.move_away.attribute), 95, self.player_1.is_ura, fade_override=self.diff_fade_out.attribute)
if (-156 * tex.screen_scale) <= box.position <= (tex.screen_width + 144) * tex.screen_scale:
if box.position <= (500 * tex.screen_scale):
box.draw(box.position - int(self.move_away.attribute), tex.skin_config["boxes"].y, self.player_1.is_ura, fade_override=self.diff_fade_out.attribute)
else:
box.draw(box.position + int(self.move_away.attribute), 95, self.player_1.is_ura, fade_override=self.diff_fade_out.attribute)
box.draw(box.position + int(self.move_away.attribute), tex.skin_config["boxes"].y, self.player_1.is_ura, fade_override=self.diff_fade_out.attribute)
if self.state == State.BROWSING:
tex.draw_texture('global', 'arrow', index=0, x=-(self.blue_arrow_move.attribute*2), fade=self.blue_arrow_fade.attribute)
@@ -363,7 +363,7 @@ class SongSelectScreen(Screen):
if isinstance(curr_item, SongFile):
curr_item.box.draw_score_history()
self.indicator.draw(410, 575)
self.indicator.draw(tex.skin_config['song_select_indicator'].x, tex.skin_config['song_select_indicator'].y)
tex.draw_texture('global', 'song_num_bg', fade=0.75)
tex.draw_texture('global', 'song_num', frame=global_data.songs_played % 4)
@@ -403,7 +403,7 @@ class SongSelectPlayer:
self.selected_diff_text_fadein = tex.get_animation(37, is_copy=True)
# Player-specific objects
self.chara = Chara2D(int(self.player_num) - 1, 100)
self.chara = Chara2D(int(self.player_num) - 1)
plate_info = global_data.config[f'nameplate_{self.player_num}p']
self.nameplate = Nameplate(plate_info['name'], plate_info['title'],
self.player_num, plate_info['dan'], plate_info['gold'], plate_info['rainbow'], plate_info['title_bg'])
@@ -436,10 +436,10 @@ class SongSelectPlayer:
def on_song_selected(self, selected_song):
"""Called when a song is selected"""
if 4 not in selected_song.tja.metadata.course_data:
if Difficulty.URA not in selected_song.tja.metadata.course_data:
self.is_ura = False
elif (4 in selected_song.tja.metadata.course_data and
3 not in selected_song.tja.metadata.course_data):
elif (Difficulty.URA in selected_song.tja.metadata.course_data and
Difficulty.ONI not in selected_song.tja.metadata.course_data):
self.is_ura = True
def handle_input_browsing(self, last_moved, selected_item):
@@ -644,46 +644,47 @@ class SongSelectPlayer:
def draw_selector(self, is_half: bool):
fade = 0.5 if (self.neiro_selector is not None or self.modifier_selector is not None) else self.text_fade_in.attribute
direction = 1 if self.diff_select_move_right else -1
offset = tex.skin_config["selector_offset"].x
if self.selected_difficulty <= -1 or self.prev_diff == -1:
if self.prev_diff == -1 and self.selected_difficulty >= 0:
if not self.diff_selector_move_2.is_finished:
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon'
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * 70) - 220 + (self.diff_selector_move_2.attribute * direction), fade=fade)
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * tex.skin_config["selector_balloon_offset_2"].x) + tex.skin_config["selector_balloon_offset_1"].x + (self.diff_selector_move_2.attribute * direction), fade=fade)
name = f'{self.player_num}p_outline_back_half' if is_half else f'{self.player_num}p_outline_back'
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * 70) + (self.diff_selector_move_2.attribute * direction))
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * tex.skin_config["selector_balloon_offset_2"].x) + (self.diff_selector_move_2.attribute * direction))
else:
difficulty = min(Difficulty.ONI, self.selected_difficulty)
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon'
tex.draw_texture('diff_select', name, x=(difficulty * 115), fade=fade)
tex.draw_texture('diff_select', name, x=(difficulty * offset), fade=fade)
name = f'{self.player_num}p_outline_half' if is_half else f'{self.player_num}p_outline'
tex.draw_texture('diff_select', name, x=(difficulty * 115))
tex.draw_texture('diff_select', name, x=(difficulty * offset))
elif not self.diff_selector_move_2.is_finished:
name = f'{self.player_num}p_outline_back_half' if is_half else f'{self.player_num}p_outline_back'
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * 70) + (self.diff_selector_move_2.attribute * direction))
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * tex.skin_config["selector_balloon_offset_2"].x) + (self.diff_selector_move_2.attribute * direction))
if self.selected_difficulty != -3:
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon'
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * 70) - 220 + (self.diff_selector_move_2.attribute * direction), fade=fade)
tex.draw_texture('diff_select', name, x=((self.prev_diff+3) * tex.skin_config["selector_balloon_offset_2"].x) + tex.skin_config["selector_balloon_offset_1"].x + (self.diff_selector_move_2.attribute * direction), fade=fade)
else:
name = f'{self.player_num}p_outline_back_half' if is_half else f'{self.player_num}p_outline_back'
tex.draw_texture('diff_select', name, x=((self.selected_difficulty+3) * 70))
tex.draw_texture('diff_select', name, x=((self.selected_difficulty+3) * tex.skin_config["selector_balloon_offset_2"].x))
if self.selected_difficulty != -3:
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon'
tex.draw_texture('diff_select', name, x=((self.selected_difficulty+3) * 70) - 220, fade=fade)
tex.draw_texture('diff_select', name, x=((self.selected_difficulty+3) * tex.skin_config["selector_balloon_offset_2"].x) + tex.skin_config["selector_balloon_offset_1"].x, fade=fade)
else:
if self.prev_diff == -1:
return
if not self.diff_selector_move_1.is_finished:
difficulty = min(Difficulty.ONI, self.prev_diff)
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon'
tex.draw_texture('diff_select', name, x=(difficulty * 115) + (self.diff_selector_move_1.attribute * direction), fade=fade)
tex.draw_texture('diff_select', name, x=(difficulty * offset) + (self.diff_selector_move_1.attribute * direction), fade=fade)
name = f'{self.player_num}p_outline_half' if is_half else f'{self.player_num}p_outline'
tex.draw_texture('diff_select', name, x=(difficulty * 115) + (self.diff_selector_move_1.attribute * direction))
tex.draw_texture('diff_select', name, x=(difficulty * offset) + (self.diff_selector_move_1.attribute * direction))
else:
difficulty = min(Difficulty.ONI, self.selected_difficulty)
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon'
tex.draw_texture('diff_select', name, x=(difficulty * 115), fade=fade)
tex.draw_texture('diff_select', name, x=(difficulty * offset), fade=fade)
name = f'{self.player_num}p_outline_half' if is_half else f'{self.player_num}p_outline'
tex.draw_texture('diff_select', name, x=(difficulty * 115))
tex.draw_texture('diff_select', name, x=(difficulty * offset))
def draw_background_diffs(self, state: int):
if (self.selected_song and state == State.SONG_SELECTED and self.selected_difficulty >= Difficulty.EASY):
@@ -710,21 +711,21 @@ class SongSelectPlayer:
if self.neiro_selector is not None:
offset = self.neiro_selector.move.attribute
if self.neiro_selector.is_confirmed:
offset += -370
offset += tex.skin_config["song_select_offset"].x
else:
offset *= -1
if self.modifier_selector is not None:
offset = self.modifier_selector.move.attribute
if self.modifier_selector.is_confirmed:
offset += -370
offset += tex.skin_config["song_select_offset"].x
else:
offset *= -1
if self.player_num == PlayerNum.P1:
self.nameplate.draw(30, 640)
self.chara.draw(x=-50, y=410 + (offset*0.6))
self.nameplate.draw(tex.skin_config["song_select_nameplate_1p"].x, tex.skin_config["song_select_nameplate_1p"].y)
self.chara.draw(x=tex.skin_config["song_select_chara_1p"].x, y=tex.skin_config["song_select_chara_1p"].y + (offset*0.6))
else:
self.nameplate.draw(950, 640)
self.chara.draw(mirror=True, x=950, y=410 + (offset*0.6))
self.nameplate.draw(tex.skin_config["song_select_nameplate_2p"].x, tex.skin_config["song_select_nameplate_2p"].y)
self.chara.draw(mirror=True, x=tex.skin_config["song_select_chara_2p"].x, y=tex.skin_config["song_select_chara_2p"].y + (offset*0.6))
if self.neiro_selector is not None:
self.neiro_selector.draw()

View File

@@ -8,7 +8,8 @@ from libs.audio import audio
from libs.utils import global_data
from libs.video import VideoPlayer
import pyray as ray
from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, Player, Background, SCREEN_WIDTH, ResultTransition
from libs.texture import tex
from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, Player, Background, ResultTransition
logger = logging.getLogger(__name__)
@@ -74,7 +75,7 @@ class TwoPlayerGameScreen(GameScreen):
def init_tja(self, song: Path):
"""Initialize the TJA file"""
self.tja = TJAParser(song, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X)
self.tja = TJAParser(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)

View File

@@ -1,5 +1,6 @@
import logging
from libs.global_data import PlayerNum
from libs.texture import tex
from libs.utils import get_current_ms
from scenes.result import Background, FadeIn, ResultPlayer, ResultScreen
@@ -8,7 +9,7 @@ logger = logging.getLogger(__name__)
class TwoPlayerResultScreen(ResultScreen):
def on_screen_start(self):
super().on_screen_start()
self.background = Background(PlayerNum.TWO_PLAYER, 1280)
self.background = Background(PlayerNum.TWO_PLAYER, tex.screen_width)
self.fade_in = FadeIn(PlayerNum.TWO_PLAYER)
self.player_1 = ResultPlayer(PlayerNum.P1, True, False)
self.player_2 = ResultPlayer(PlayerNum.P2, True, True)