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

@@ -19,10 +19,10 @@ from libs.screen import Screen
from libs.tja import TJAParser from libs.tja import TJAParser
from libs.utils import ( from libs.utils import (
force_dedicated_gpu, force_dedicated_gpu,
get_config,
global_data, global_data,
global_tex global_tex
) )
from libs.config import get_config
from scenes.devtest import DevScreen from scenes.devtest import DevScreen
from scenes.entry import EntryScreen from scenes.entry import EntryScreen
from scenes.game import GameScreen from scenes.game import GameScreen
@@ -119,8 +119,8 @@ def main():
logger.info("Starting PyTaiko") logger.info("Starting PyTaiko")
logger.debug(f"Loaded config: {global_data.config}") logger.debug(f"Loaded config: {global_data.config}")
screen_width = global_data.config["video"]["screen_width"] screen_width = global_tex.screen_width
screen_height = global_data.config["video"]["screen_height"] screen_height = global_tex.screen_height
if global_data.config["video"]["vsync"]: if global_data.config["video"]["vsync"]:
ray.set_config_flags(ray.ConfigFlags.FLAG_VSYNC_HINT) ray.set_config_flags(ray.ConfigFlags.FLAG_VSYNC_HINT)

View File

@@ -30,6 +30,7 @@ rainbow = false
[paths] [paths]
tja_path = ['Songs'] tja_path = ['Songs']
video_path = ['Videos'] video_path = ['Videos']
graphics_path = 'Graphics/GreenVer'
[keys] [keys]
exit_key = 'Q' exit_key = 'Q'

View File

@@ -4,8 +4,8 @@ import platform
import logging import logging
from pathlib import Path from pathlib import Path
from libs.global_data import VolumeConfig from libs.config import VolumeConfig
from libs.utils import get_config from libs.config import get_config
ffi = cffi.FFI() ffi = cffi.FFI()

View File

@@ -177,7 +177,7 @@ class Background:
self.bg_normal.draw(self.tex_wrapper) self.bg_normal.draw(self.tex_wrapper)
self.don_bg.draw(self.tex_wrapper) self.don_bg.draw(self.tex_wrapper)
if self.don_bg_2 is not None: if self.don_bg_2 is not None:
self.don_bg_2.draw(self.tex_wrapper, y=536) self.don_bg_2.draw(self.tex_wrapper, y=self.tex_wrapper.skin_config["game_2p_offset"].y)
if self.renda is not None: if self.renda is not None:
self.renda.draw() self.renda.draw()
if self.dancer is not None: if self.dancer is not None:

View File

@@ -17,6 +17,7 @@ class BGFever:
class BGFeverBase: class BGFeverBase:
def __init__(self, tex: TextureWrapper, index: int, path: str): def __init__(self, tex: TextureWrapper, index: int, path: str):
self.name = 'bg_fever_' + str(index) self.name = 'bg_fever_' + str(index)
self.tex = tex
tex.load_zip(path, f'bg_fever/{self.name}') tex.load_zip(path, f'bg_fever/{self.name}')
self.transitioned = False self.transitioned = False
def start(self): def start(self):
@@ -28,13 +29,13 @@ class BGFeverBase:
class BGFever1(BGFeverBase): class BGFever1(BGFeverBase):
class Tile: class Tile:
def __init__(self): def __init__(self, tex):
self.expansion = Animation.create_move(166, total_distance=360) self.expansion = Animation.create_move(166, total_distance=tex.screen_height//2)
self.expansion.start() self.expansion.start()
def update(self, current_time_ms): def update(self, current_time_ms):
self.expansion.update(current_time_ms) self.expansion.update(current_time_ms)
def draw(self, tex: TextureWrapper, name: str, x: int, frame: int): def draw(self, tex: TextureWrapper, name: str, x: int, frame: int):
tex.draw_texture(name, 'background', frame=frame, x=x, y2=-360+self.expansion.attribute, y=360+(180-self.expansion.attribute/2)) tex.draw_texture(name, 'background', frame=frame, x=x, y2=-tex.screen_height//2+self.expansion.attribute, y=tex.screen_height//2+(tex.screen_height//4-self.expansion.attribute/2))
def __init__(self, tex: TextureWrapper, index: int, path): def __init__(self, tex: TextureWrapper, index: int, path):
super().__init__(tex, index, path) super().__init__(tex, index, path)
self.wait = 0 self.wait = 0
@@ -89,7 +90,7 @@ class BGFever1(BGFeverBase):
def update(self, current_time_ms: float): def update(self, current_time_ms: float):
if len(self.bg_tiles) < 20 and current_time_ms >= self.wait + 66: if len(self.bg_tiles) < 20 and current_time_ms >= self.wait + 66:
self.bg_tiles.append(BGFever1.Tile()) self.bg_tiles.append(BGFever1.Tile(self.tex))
self.wait = current_time_ms self.wait = current_time_ms
for tile in self.bg_tiles: for tile in self.bg_tiles:
tile.update(current_time_ms) tile.update(current_time_ms)

View File

@@ -15,6 +15,7 @@ class BGNormal:
class BGNormalBase: class BGNormalBase:
def __init__(self, tex: TextureWrapper, index: int, path: str): def __init__(self, tex: TextureWrapper, index: int, path: str):
self.name = "bg_" + str(index) self.name = "bg_" + str(index)
self.tex = tex
tex.load_zip(path, f'bg_normal/{self.name}') tex.load_zip(path, f'bg_normal/{self.name}')
def update(self, current_time_ms: float): def update(self, current_time_ms: float):
pass pass
@@ -69,29 +70,29 @@ class BGNormal3(BGNormalBase):
class BGNormal4(BGNormalBase): class BGNormal4(BGNormalBase):
class Petal: class Petal:
def __init__(self): def __init__(self, tex: TextureWrapper):
self.spawn_point = self.random_excluding_range() self.spawn_point = self.random_excluding_range(tex.screen_width)
duration = random.randint(1400, 2000) duration = random.randint(1400, 2000)
self.move_x = Animation.create_move(duration, total_distance=random.randint(-300, 300)) self.move_x = Animation.create_move(duration, total_distance=random.randint(-300, 300))
self.move_y = Animation.create_move(duration, total_distance=360) self.move_y = Animation.create_move(duration, total_distance=tex.screen_height//2)
self.move_x.start() self.move_x.start()
self.move_y.start() self.move_y.start()
def random_excluding_range(self): def random_excluding_range(self, screen_width):
while True: while True:
num = random.randint(0, 1280) num = random.randint(0, screen_width)
if num < 260 or num > 540: if num < 260 or num > 540:
return num return num
def update(self, current_time_ms): def update(self, current_time_ms):
self.move_x.update(current_time_ms) self.move_x.update(current_time_ms)
self.move_y.update(current_time_ms) self.move_y.update(current_time_ms)
def draw(self, name: str, tex: TextureWrapper): def draw(self, name: str, tex: TextureWrapper):
tex.draw_texture(name, 'petal', x=self.spawn_point + self.move_x.attribute, y=360+self.move_y.attribute, fade=0.75) tex.draw_texture(name, 'petal', x=self.spawn_point + self.move_x.attribute, y=tex.screen_height//2+self.move_y.attribute, fade=0.75)
def __init__(self, tex: TextureWrapper, index: int, path: str): def __init__(self, tex: TextureWrapper, index: int, path: str):
super().__init__(tex, index, path) super().__init__(tex, index, path)
self.flicker = tex.get_animation(11) self.flicker = tex.get_animation(11)
self.turtle_move = tex.get_animation(12) self.turtle_move = tex.get_animation(12)
self.turtle_change = tex.get_animation(13) self.turtle_change = tex.get_animation(13)
self.petals = {self.Petal(), self.Petal(), self.Petal(), self.Petal(), self.Petal()} self.petals = {self.Petal(tex), self.Petal(tex), self.Petal(tex), self.Petal(tex), self.Petal(tex)}
def update(self, current_time_ms: float): def update(self, current_time_ms: float):
self.flicker.update(current_time_ms) self.flicker.update(current_time_ms)
self.turtle_move.update(current_time_ms) self.turtle_move.update(current_time_ms)
@@ -100,7 +101,7 @@ class BGNormal4(BGNormalBase):
petal.update(current_time_ms) petal.update(current_time_ms)
if petal.move_y.is_finished: if petal.move_y.is_finished:
self.petals.remove(petal) self.petals.remove(petal)
self.petals.add(self.Petal()) self.petals.add(self.Petal(self.tex))
def draw(self, tex: TextureWrapper): def draw(self, tex: TextureWrapper):
tex.draw_texture(self.name, 'background') tex.draw_texture(self.name, 'background')
tex.draw_texture(self.name, 'chara') tex.draw_texture(self.name, 'chara')

View File

@@ -20,9 +20,10 @@ class BaseChibi:
self.name = 'chibi_' + str(index) self.name = 'chibi_' + str(index)
self.bpm = bpm self.bpm = bpm
self.is_2p = is_2p self.is_2p = is_2p
self.hori_move = Animation.create_move(60000 / self.bpm * 5, total_distance=1280) self.tex = tex
self.hori_move = Animation.create_move(60000 / self.bpm * 5, total_distance=tex.screen_width)
self.hori_move.start() self.hori_move.start()
self.vert_move = Animation.create_move(60000 / self.bpm / 2, total_distance=50, reverse_delay=0) self.vert_move = Animation.create_move(60000 / self.bpm / 2, total_distance=50 * tex.screen_scale, reverse_delay=0)
self.vert_move.start() self.vert_move.start()
self.index = random.randint(0, len([item for item in tex.textures[self.name] if item[0].isdigit()])-1) self.index = random.randint(0, len([item for item in tex.textures[self.name] if item[0].isdigit()])-1)
tex_list = tex.textures[self.name][str(self.index)].texture tex_list = tex.textures[self.name][str(self.index)].texture
@@ -47,9 +48,9 @@ class BaseChibi:
textures = [((duration / len(self.keyframes))*i, (duration / len(self.keyframes))*(i+1), index) for i, index in enumerate(self.keyframes)] textures = [((duration / len(self.keyframes))*i, (duration / len(self.keyframes))*(i+1), index) for i, index in enumerate(self.keyframes)]
self.texture_change = Animation.create_texture_change(duration, textures=textures) self.texture_change = Animation.create_texture_change(duration, textures=textures)
self.texture_change.start() self.texture_change.start()
self.hori_move = Animation.create_move(60000 / self.bpm * 5, total_distance=1280) self.hori_move = Animation.create_move(60000 / self.bpm * 5, total_distance=self.tex.screen_width)
self.hori_move.start() self.hori_move.start()
self.vert_move = Animation.create_move(60000 / self.bpm / 2, total_distance=50, reverse_delay=0) self.vert_move = Animation.create_move(60000 / self.bpm / 2, total_distance=50 * self.tex.screen_scale, reverse_delay=0)
self.vert_move.start() self.vert_move.start()
def draw(self, tex: TextureWrapper): def draw(self, tex: TextureWrapper):
@@ -62,9 +63,9 @@ class ChibiBad(BaseChibi):
self.index = random.randint(0, 2) self.index = random.randint(0, 2)
self.keyframes = [3, 4] self.keyframes = [3, 4]
duration = (60000 / self.bpm) / 2 duration = (60000 / self.bpm) / 2
self.hori_move = Animation.create_move(duration * 10, total_distance=1280) self.hori_move = Animation.create_move(duration * 10, total_distance=1280 * self.tex.screen_width)
self.hori_move.start() self.hori_move.start()
self.vert_move = Animation.create_move(duration, total_distance=50, reverse_delay=0) self.vert_move = Animation.create_move(duration, total_distance=50 * self.tex.screen_scale, reverse_delay=0)
self.vert_move.start() self.vert_move.start()
self.fade_in = Animation.create_fade(duration, initial_opacity=0.0, final_opacity=1.0) self.fade_in = Animation.create_fade(duration, initial_opacity=0.0, final_opacity=1.0)
self.fade_in.start() self.fade_in.start()
@@ -95,7 +96,7 @@ class Chibi0(BaseChibi):
class Chibi2(BaseChibi): class Chibi2(BaseChibi):
def __init__(self, index: int, bpm: float, tex: TextureWrapper, is_2p: bool): def __init__(self, index: int, bpm: float, tex: TextureWrapper, is_2p: bool):
super().__init__(index, bpm, tex, is_2p) super().__init__(index, bpm, tex, is_2p)
self.rotate = Animation.create_move(60000 / self.bpm, total_distance=360) self.rotate = Animation.create_move(60000 / self.bpm, total_distance=self.tex.screen_height//2)
self.rotate.start() self.rotate.start()
def update(self, current_time_ms: float, bpm: float): def update(self, current_time_ms: float, bpm: float):

View File

@@ -165,7 +165,7 @@ class BaseDancerGroup():
dancer.update(current_time_ms, bpm) dancer.update(current_time_ms, bpm)
def draw(self, tex: TextureWrapper): def draw(self, tex: TextureWrapper):
total_width = 1280 total_width = tex.screen_width
num_dancers = len(self.active_dancers) num_dancers = len(self.active_dancers)
first_dancer = next((dancer for dancer in self.active_dancers if dancer is not None), None) first_dancer = next((dancer for dancer in self.active_dancers if dancer is not None), None)

View File

@@ -15,7 +15,7 @@ class Renda:
class BaseRenda: class BaseRenda:
def __init__(self, tex: TextureWrapper, index: int): def __init__(self, tex: TextureWrapper, index: int):
self.name = 'renda_' + str(index) self.name = 'renda_' + str(index)
self.hori_move = Animation.create_move(1500, total_distance=1280) self.hori_move = Animation.create_move(1500, total_distance=tex.screen_width)
self.hori_move.start() self.hori_move.start()
def update(self, current_time_ms: float): def update(self, current_time_ms: float):
@@ -24,13 +24,13 @@ class BaseRenda:
class Renda0(BaseRenda): class Renda0(BaseRenda):
def __init__(self, tex: TextureWrapper, index: int): def __init__(self, tex: TextureWrapper, index: int):
super().__init__(tex, index) super().__init__(tex, index)
self.vert_move = Animation.create_move(1500, total_distance=800) self.vert_move = Animation.create_move(1500, total_distance=tex.screen_height + (80 * tex.screen_scale))
self.vert_move.start() self.vert_move.start()
tex_list = tex.textures['renda'][self.name].texture tex_list = tex.textures['renda'][self.name].texture
num_of_rendas = len(tex_list) if isinstance(tex_list, list) else 0 num_of_rendas = len(tex_list) if isinstance(tex_list, list) else 0
self.frame = random.randint(0, num_of_rendas - 1) self.frame = random.randint(0, num_of_rendas - 1)
self.x = random.randint(0, 500) self.x = random.randint(0, int(500 * tex.screen_scale))
self.y = random.randint(0, 20) self.y = random.randint(0, int(20 * tex.screen_scale))
def update(self, current_time_ms: float): def update(self, current_time_ms: float):
super().update(current_time_ms) super().update(current_time_ms)
@@ -43,8 +43,8 @@ class Renda1(BaseRenda):
def __init__(self, tex: TextureWrapper, index: int): def __init__(self, tex: TextureWrapper, index: int):
super().__init__(tex, index) super().__init__(tex, index)
self.frame = random.randint(0, 5) self.frame = random.randint(0, 5)
self.y = random.randint(0, 200) self.y = random.randint(0, int(200 * tex.screen_scale))
self.rotate = Animation.create_move(800, total_distance=360) self.rotate = Animation.create_move(800, total_distance=tex.screen_height//2)
self.rotate.start() self.rotate.start()
self.origin = ray.Vector2(64, 64) self.origin = ray.Vector2(64, 64)
@@ -60,10 +60,10 @@ class Renda1(BaseRenda):
class Renda2(BaseRenda): class Renda2(BaseRenda):
def __init__(self, tex: TextureWrapper, index: int): def __init__(self, tex: TextureWrapper, index: int):
super().__init__(tex, index) super().__init__(tex, index)
self.vert_move = Animation.create_move(1500, total_distance=800) self.vert_move = Animation.create_move(1500, total_distance=tex.screen_height + (80 * tex.screen_scale))
self.vert_move.start() self.vert_move.start()
self.x = random.randint(0, 500) self.x = random.randint(0, int(500 * tex.screen_scale))
self.y = random.randint(0, 20) self.y = random.randint(0, int(20 * tex.screen_scale))
def update(self, current_time_ms: float): def update(self, current_time_ms: float):
super().update(current_time_ms) super().update(current_time_ms)

151
libs/config.py Normal file
View File

@@ -0,0 +1,151 @@
from pathlib import Path
import tomlkit
import json
from typing import TypedDict
import pyray as ray
class GeneralConfig(TypedDict):
fps_counter: bool
audio_offset: int
visual_offset: int
language: str
hard_judge: int
touch_enabled: bool
timer_frozen: bool
judge_counter: bool
nijiiro_notes: bool
log_level: int
fake_online: bool
class NameplateConfig(TypedDict):
name: str
title: str
title_bg: int
dan: int
gold: bool
rainbow: bool
class PathsConfig(TypedDict):
tja_path: list[Path]
video_path: list[Path]
graphics_path: Path
class KeysConfig(TypedDict):
exit_key: int
fullscreen_key: int
borderless_key: int
pause_key: int
back_key: int
restart_key: int
class Keys1PConfig(TypedDict):
left_kat: list[int]
left_don: list[int]
right_don: list[int]
right_kat: list[int]
class Keys2PConfig(TypedDict):
left_kat: list[int]
left_don: list[int]
right_don: list[int]
right_kat: list[int]
class GamepadConfig(TypedDict):
left_kat: list[int]
left_don: list[int]
right_don: list[int]
right_kat: list[int]
class AudioConfig(TypedDict):
device_type: int
sample_rate: int
buffer_size: int
class VolumeConfig(TypedDict):
sound: float
music: float
voice: float
hitsound: float
attract_mode: float
class VideoConfig(TypedDict):
fullscreen: bool
borderless: bool
target_fps: int
vsync: bool
class Config(TypedDict):
general: GeneralConfig
nameplate_1p: NameplateConfig
nameplate_2p: NameplateConfig
paths: PathsConfig
keys: KeysConfig
keys_1p: Keys1PConfig
keys_2p: Keys2PConfig
gamepad: GamepadConfig
audio: AudioConfig
volume: VolumeConfig
video: VideoConfig
def get_key_string(key_code: int) -> str:
"""Convert a key code back to its string representation"""
if 65 <= key_code <= 90:
return chr(key_code)
if 48 <= key_code <= 57:
return chr(key_code)
for attr_name in dir(ray):
if attr_name.startswith('KEY_'):
if getattr(ray, attr_name) == key_code:
return attr_name[4:].lower()
raise ValueError(f"Unknown key code: {key_code}")
def get_key_code(key: str) -> int:
if len(key) == 1 and key.isalnum():
return ord(key.upper())
else:
key_code = getattr(ray, f"KEY_{key.upper()}", None)
if key_code is None:
raise ValueError(f"Invalid key: {key}")
return key_code
def get_config() -> Config:
"""Get the configuration from the TOML file"""
config_path = Path('dev-config.toml') if Path('dev-config.toml').exists() else Path('config.toml')
with open(config_path, "r", encoding="utf-8") as f:
config_file = tomlkit.load(f)
config: Config = json.loads(json.dumps(config_file))
for key in config['keys']:
config['keys'][key] = get_key_code(config['keys'][key])
for key in config['keys_1p']:
bindings = config['keys_1p'][key]
for i, bind in enumerate(bindings):
config['keys_1p'][key][i] = get_key_code(bind)
for key in config['keys_2p']:
bindings = config['keys_2p'][key]
for i, bind in enumerate(bindings):
config['keys_2p'][key][i] = get_key_code(bind)
return config
def save_config(config: Config) -> None:
"""Save the configuration to the TOML file"""
config_to_save = json.loads(json.dumps(config))
for key in config_to_save['keys']:
config_to_save['keys'][key] = get_key_string(config_to_save['keys'][key])
for key in config_to_save['keys_1p']:
bindings = config_to_save['keys_1p'][key]
for i, bind in enumerate(bindings):
config_to_save['keys_1p'][key][i] = get_key_string(bind)
for key in config_to_save['keys_2p']:
bindings = config_to_save['keys_2p'][key]
for i, bind in enumerate(bindings):
config_to_save['keys_2p'][key][i] = get_key_string(bind)
config_path = Path('dev-config.toml') if Path('dev-config.toml').exists() else Path('config.toml')
with open(config_path, "w", encoding="utf-8") as f:
tomlkit.dump(config_to_save, f)

View File

@@ -8,13 +8,13 @@ from libs.audio import audio
from libs.animation import Animation, MoveAnimation from libs.animation import Animation, MoveAnimation
from libs.global_data import Crown, Difficulty from libs.global_data import Crown, Difficulty
from libs.tja import TJAParser, test_encodings from libs.tja import TJAParser, test_encodings
from libs.texture import SCREEN_SCALE, SCREEN_WIDTH, tex from libs.texture import tex
from libs.utils import OutlinedText, get_current_ms, global_data from libs.utils import OutlinedText, get_current_ms, global_data
from datetime import datetime, timedelta from datetime import datetime, timedelta
import sqlite3 import sqlite3
import pyray as ray import pyray as ray
BOX_CENTER = 594 * SCREEN_SCALE BOX_CENTER = 594 * tex.screen_scale
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -37,6 +37,7 @@ class BaseBox():
} }
BACK_INDEX = 17 BACK_INDEX = 17
DEFAULT_INDEX = 9 DEFAULT_INDEX = 9
DIFFICULTY_SORT_INDEX = 14
"""Base class for all box types in the song select screen.""" """Base class for all box types in the song select screen."""
def __init__(self, name: str, texture_index: int): def __init__(self, name: str, texture_index: int):
self.text_name = name self.text_name = name
@@ -44,7 +45,7 @@ class BaseBox():
self.position = float('inf') self.position = float('inf')
self.start_position: float = -1 self.start_position: float = -1
self.target_position: float = -1 self.target_position: float = -1
self.open_anim = Animation.create_move(133, total_distance=150*SCREEN_SCALE, delay=83.33) self.open_anim = Animation.create_move(133, total_distance=150*tex.screen_scale, delay=83.33)
self.open_fade = Animation.create_fade(200, initial_opacity=0, final_opacity=1.0) self.open_fade = Animation.create_fade(200, initial_opacity=0, final_opacity=1.0)
self.move = None self.move = None
self.is_open = False self.is_open = False
@@ -52,7 +53,7 @@ class BaseBox():
self.wait = 0 self.wait = 0
def load_text(self): def load_text(self):
self.name = OutlinedText(self.text_name, 40, ray.WHITE, outline_thickness=5, vertical=True) self.name = OutlinedText(self.text_name, tex.skin_config["song_box_name"].font_size, ray.WHITE, outline_thickness=5, vertical=True)
def move_box(self, current_time: float): def move_box(self, current_time: float):
if self.position != self.target_position and self.move is None: if self.position != self.target_position and self.move is None:
@@ -60,12 +61,12 @@ class BaseBox():
direction = 1 direction = 1
else: else:
direction = -1 direction = -1
if abs(self.target_position - self.position) > 250: if abs(self.target_position - self.position) > 250 * tex.screen_scale:
direction *= -1 direction *= -1
self.move = Animation.create_move(83.3, total_distance=100 * direction * SCREEN_SCALE, ease_out='cubic') self.move = Animation.create_move(83.3, total_distance=100 * direction * tex.screen_scale, ease_out='cubic')
self.move.start() self.move.start()
if self.is_open or self.target_position == BOX_CENTER: if self.is_open or self.target_position == BOX_CENTER:
self.move.total_distance = 250 * direction self.move.total_distance = int(250 * direction * tex.screen_scale)
self.start_position = self.position self.start_position = self.position
if self.move is not None: if self.move is not None:
self.move.update(current_time) self.move.update(current_time)
@@ -81,12 +82,12 @@ class BaseBox():
def _draw_closed(self, x: float, y: float): def _draw_closed(self, x: float, y: float):
tex.draw_texture('box', 'folder_texture_left', frame=self.texture_index, x=x) tex.draw_texture('box', 'folder_texture_left', frame=self.texture_index, x=x)
offset = 1 if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0 offset = 1 * tex.screen_scale if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0
tex.draw_texture('box', 'folder_texture', frame=self.texture_index, x=x, x2=32, y=offset) tex.draw_texture('box', 'folder_texture', frame=self.texture_index, x=x, x2=tex.skin_config["song_box_bg"].width, y=offset)
tex.draw_texture('box', 'folder_texture_right', frame=self.texture_index, x=x) tex.draw_texture('box', 'folder_texture_right', frame=self.texture_index, x=x)
if self.texture_index == SongBox.DEFAULT_INDEX: if self.texture_index == BaseBox.DEFAULT_INDEX:
tex.draw_texture('box', 'genre_overlay', x=x, y=y) tex.draw_texture('box', 'genre_overlay', x=x, y=y)
elif self.texture_index == 14: elif self.texture_index == BaseBox.DIFFICULTY_SORT_INDEX:
tex.draw_texture('box', 'diff_overlay', x=x, y=y) tex.draw_texture('box', 'diff_overlay', x=x, y=y)
def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool): def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool):
@@ -200,7 +201,7 @@ class SongBox(BaseBox):
def _draw_closed(self, x: float, y: float): def _draw_closed(self, x: float, y: float):
super()._draw_closed(x, y) super()._draw_closed(x, y)
self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.name_texture_index, ray.Color(101, 0, 82, 255)), x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height) self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.name_texture_index, ray.Color(101, 0, 82, 255)), x=x + tex.skin_config["song_box_name"].x - int(self.name.texture.width / 2), y=y+tex.skin_config["song_box_name"].y, y2=min(self.name.texture.height, tex.skin_config["song_box_name"].height)-self.name.texture.height)
if self.tja.ex_data.new: if self.tja.ex_data.new:
tex.draw_texture('yellow_box', 'ex_data_new_song_balloon', x=x, y=y) tex.draw_texture('yellow_box', 'ex_data_new_song_balloon', x=x, y=y)
@@ -230,18 +231,14 @@ class FolderBox(BaseBox):
super().__init__(name, texture_index) super().__init__(name, texture_index)
self.box_texture_path = Path(box_texture) if box_texture else None self.box_texture_path = Path(box_texture) if box_texture else None
self.is_back = self.texture_index == SongBox.BACK_INDEX self.is_back = self.texture_index == SongBox.BACK_INDEX
if self.is_back:
for i in range(1, SongBox.BACK_INDEX-1):
if audio.is_sound_playing(f'genre_voice_{i}'):
audio.stop_sound(f'genre_voice_{i}')
self.tja_count = tja_count self.tja_count = tja_count
self.crown = dict() self.crown = dict()
def load_text(self): def load_text(self):
super().load_text() super().load_text()
self.hori_name = OutlinedText(self.text_name, 40, ray.WHITE, outline_thickness=5) self.hori_name = OutlinedText(self.text_name, tex.skin_config['song_hori_name'].font_size, ray.WHITE, outline_thickness=5)
self.box_texture = ray.load_texture(str(self.box_texture_path)) if self.box_texture_path and self.box_texture_path.exists() else None self.box_texture = ray.load_texture(str(self.box_texture_path)) if self.box_texture_path and self.box_texture_path.exists() else None
self.tja_count_text = OutlinedText(str(self.tja_count), 35, ray.WHITE, outline_thickness=5) self.tja_count_text = OutlinedText(str(self.tja_count), tex.skin_config['song_tja_count'].font_size, ray.WHITE, outline_thickness=5)
self.text_loaded = True self.text_loaded = True
def update(self, current_time: float, is_diff_select: bool): def update(self, current_time: float, is_diff_select: bool):
@@ -261,10 +258,10 @@ class FolderBox(BaseBox):
def _draw_closed(self, x: float, y: float): def _draw_closed(self, x: float, y: float):
super()._draw_closed(x, y) super()._draw_closed(x, y)
offset = 1 if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0 offset = 1 * tex.screen_scale if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0
tex.draw_texture('box', 'folder_clip', frame=self.texture_index, x=x - (1 - offset), y=y) tex.draw_texture('box', 'folder_clip', frame=self.texture_index, x=x - ((1 * tex.screen_scale) - offset), y=y)
self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.texture_index, ray.Color(101, 0, 82, 255)), x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height) self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.texture_index, ray.Color(101, 0, 82, 255)), x=x + tex.skin_config["song_box_name"].x - int(self.name.texture.width / 2), y=y+tex.skin_config["song_box_name"].y, y2=min(self.name.texture.height, tex.skin_config["song_box_name"].height)-self.name.texture.height)
if self.crown: #Folder lamp if self.crown: #Folder lamp
highest_crown = max(self.crown) highest_crown = max(self.crown)
@@ -279,37 +276,37 @@ class FolderBox(BaseBox):
color = ray.WHITE color = ray.WHITE
if fade_override is not None: if fade_override is not None:
color = ray.fade(ray.WHITE, fade_override) color = ray.fade(ray.WHITE, fade_override)
if not self.is_back and self.open_anim.attribute >= 100: if not self.is_back and self.open_anim.attribute >= (100 * tex.screen_scale):
tex.draw_texture('box', 'folder_top_edge', x=x, y=y - self.open_anim.attribute, color=color, mirror='horizontal', frame=self.texture_index) tex.draw_texture('box', 'folder_top_edge', x=x, y=y - self.open_anim.attribute, color=color, mirror='horizontal', frame=self.texture_index)
tex.draw_texture('box', 'folder_top', x=x, y=y - self.open_anim.attribute, color=color, frame=self.texture_index) tex.draw_texture('box', 'folder_top', x=x, y=y - self.open_anim.attribute, color=color, frame=self.texture_index)
tex.draw_texture('box', 'folder_top_edge', x=x+268, y=y - self.open_anim.attribute, color=color, frame=self.texture_index) tex.draw_texture('box', 'folder_top_edge', x=x+tex.skin_config["song_folder_top"].x, y=y - self.open_anim.attribute, color=color, frame=self.texture_index)
dest_width = min(300, self.hori_name.texture.width) dest_width = min(tex.skin_config["song_hori_name"].width, self.hori_name.texture.width)
self.hori_name.draw(outline_color=ray.BLACK, x=(x + 48) - (dest_width//2), y=y + 107 - self.open_anim.attribute, x2=dest_width-self.hori_name.texture.width, color=color) self.hori_name.draw(outline_color=ray.BLACK, x=(x + tex.skin_config["song_hori_name"].x) - (dest_width//2), y=y + tex.skin_config["song_hori_name"].y - self.open_anim.attribute, x2=dest_width-self.hori_name.texture.width, color=color)
tex.draw_texture('box', 'folder_texture_left', frame=self.texture_index, x=x - self.open_anim.attribute) tex.draw_texture('box', 'folder_texture_left', frame=self.texture_index, x=x - self.open_anim.attribute)
offset = 1 if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0 offset = 1 * tex.screen_scale if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0
tex.draw_texture('box', 'folder_texture', frame=self.texture_index, x=x - self.open_anim.attribute, y=offset, x2=(self.open_anim.attribute*2)+32) tex.draw_texture('box', 'folder_texture', frame=self.texture_index, x=x - self.open_anim.attribute, y=offset, x2=(self.open_anim.attribute*2)+tex.skin_config["song_box_bg"].width)
tex.draw_texture('box', 'folder_texture_right', frame=self.texture_index, x=x + self.open_anim.attribute) tex.draw_texture('box', 'folder_texture_right', frame=self.texture_index, x=x + self.open_anim.attribute)
if self.texture_index == SongBox.DEFAULT_INDEX: if self.texture_index == BaseBox.DEFAULT_INDEX:
tex.draw_texture('box', 'genre_overlay_large', x=x, y=y, color=color) tex.draw_texture('box', 'genre_overlay_large', x=x, y=y, color=color)
elif self.texture_index == 14: elif self.texture_index == BaseBox.DIFFICULTY_SORT_INDEX:
tex.draw_texture('box', 'diff_overlay_large', x=x, y=y, color=color) tex.draw_texture('box', 'diff_overlay_large', x=x, y=y, color=color)
color = ray.WHITE color = ray.WHITE
if fade_override is not None: if fade_override is not None:
color = ray.fade(ray.WHITE, fade_override) color = ray.fade(ray.WHITE, fade_override)
if self.texture_index != 14: if self.texture_index != BaseBox.DIFFICULTY_SORT_INDEX:
tex.draw_texture('yellow_box', 'song_count_back', color=color, fade=0.5) tex.draw_texture('yellow_box', 'song_count_back', color=color, fade=0.5)
tex.draw_texture('yellow_box', 'song_count_num', color=color) tex.draw_texture('yellow_box', 'song_count_num', color=color)
tex.draw_texture('yellow_box', 'song_count_songs', color=color) tex.draw_texture('yellow_box', 'song_count_songs', color=color)
dest_width = min(124, self.tja_count_text.texture.width) dest_width = min(tex.skin_config["song_tja_count"].width, self.tja_count_text.texture.width)
self.tja_count_text.draw(outline_color=ray.BLACK, x=560 - (dest_width//2), y=126, x2=dest_width-self.tja_count_text.texture.width, color=color) self.tja_count_text.draw(outline_color=ray.BLACK, x=tex.skin_config["song_tja_count"].x - (dest_width//2), y=tex.skin_config["song_tja_count"].y, x2=dest_width-self.tja_count_text.texture.width, color=color)
if self.texture_index != SongBox.DEFAULT_INDEX: if self.texture_index != SongBox.DEFAULT_INDEX:
tex.draw_texture('box', 'folder_graphic', color=color, frame=self.texture_index) tex.draw_texture('box', 'folder_graphic', color=color, frame=self.texture_index)
tex.draw_texture('box', 'folder_text', color=color, frame=self.texture_index) tex.draw_texture('box', 'folder_text', color=color, frame=self.texture_index)
elif self.box_texture is not None: elif self.box_texture is not None:
ray.draw_texture(self.box_texture, int((x+48) - (self.box_texture.width//2)), int((y+240) - (self.box_texture.height//2)), color) ray.draw_texture(self.box_texture, int((x+tex.skin_config["box_texture"].x) - (self.box_texture.width//2)), int((y+tex.skin_config["box_texture"].y) - (self.box_texture.height//2)), color)
class YellowBox: class YellowBox:
"""A song box when it is opened.""" """A song box when it is opened."""
@@ -319,7 +316,7 @@ class YellowBox:
self.tja = tja self.tja = tja
if self.tja is not None: if self.tja is not None:
subtitle_text = self.tja.metadata.subtitle.get(global_data.config['general']['language'], '') subtitle_text = self.tja.metadata.subtitle.get(global_data.config['general']['language'], '')
font_size = 30 if len(subtitle_text) < 30 else 20 font_size = tex.skin_config["yb_subtitle"].font_size if len(subtitle_text) < 30 else tex.skin_config["yb_subtitle"].font_size - int(10 * tex.screen_scale)
self.subtitle = OutlinedText(subtitle_text, font_size, ray.WHITE, outline_thickness=5, vertical=True) self.subtitle = OutlinedText(subtitle_text, font_size, ray.WHITE, outline_thickness=5, vertical=True)
self.is_dan = is_dan self.is_dan = is_dan
self.subtitle = None self.subtitle = None
@@ -401,16 +398,17 @@ class YellowBox:
def _draw_tja_data(self, song_box: SongBox, color: ray.Color, fade: float): def _draw_tja_data(self, song_box: SongBox, color: ray.Color, fade: float):
if not self.tja: if not self.tja:
return return
offset = tex.skin_config['yb_diff_offset'].x
for diff in self.tja.metadata.course_data: for diff in self.tja.metadata.course_data:
if diff >= Difficulty.URA: if diff >= Difficulty.URA:
continue continue
elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] == Crown.DFC: if diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] == Crown.DFC:
tex.draw_texture('yellow_box', 's_crown_dfc', x=(diff*60), color=color) tex.draw_texture('yellow_box', 's_crown_dfc', x=(diff*offset), color=color)
elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] == Crown.FC: elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] == Crown.FC:
tex.draw_texture('yellow_box', 's_crown_fc', x=(diff*60), color=color) tex.draw_texture('yellow_box', 's_crown_fc', x=(diff*offset), color=color)
elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] >= Crown.CLEAR: elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] >= Crown.CLEAR:
tex.draw_texture('yellow_box', 's_crown_clear', x=(diff*60), color=color) tex.draw_texture('yellow_box', 's_crown_clear', x=(diff*offset), color=color)
tex.draw_texture('yellow_box', 's_crown_outline', x=(diff*60), fade=min(fade, 0.25)) tex.draw_texture('yellow_box', 's_crown_outline', x=(diff*offset), fade=min(fade, 0.25))
if self.tja.ex_data.new_audio: if self.tja.ex_data.new_audio:
tex.draw_texture('yellow_box', 'ex_data_new_audio', color=color) tex.draw_texture('yellow_box', 'ex_data_new_audio', color=color)
@@ -424,17 +422,17 @@ class YellowBox:
tex.draw_texture('yellow_box', f'favorite_{global_data.player_num}p', color=color) tex.draw_texture('yellow_box', f'favorite_{global_data.player_num}p', color=color)
for i in range(4): for i in range(4):
tex.draw_texture('yellow_box', 'difficulty_bar', frame=i, x=(i*60), color=color) tex.draw_texture('yellow_box', 'difficulty_bar', frame=i, x=(i*offset), color=color)
if i not in self.tja.metadata.course_data: if i not in self.tja.metadata.course_data:
tex.draw_texture('yellow_box', 'difficulty_bar_shadow', frame=i, x=(i*60), fade=min(fade, 0.25)) tex.draw_texture('yellow_box', 'difficulty_bar_shadow', frame=i, x=(i*offset), fade=min(fade, 0.25))
for diff in self.tja.metadata.course_data: for diff in self.tja.metadata.course_data:
if diff >= Difficulty.URA: if diff >= Difficulty.URA:
continue continue
for j in range(self.tja.metadata.course_data[diff].level): for j in range(self.tja.metadata.course_data[diff].level):
tex.draw_texture('yellow_box', 'star', x=(diff*60), y=(j*-17), color=color) tex.draw_texture('yellow_box', 'star', x=(diff*offset), y=(j*tex.skin_config['yb_diff_offset'].y), color=color)
if self.tja.metadata.course_data[diff].is_branching and (get_current_ms() // 1000) % 2 == 0: if self.tja.metadata.course_data[diff].is_branching and (get_current_ms() // 1000) % 2 == 0:
tex.draw_texture('yellow_box', 'branch_indicator', x=(diff*60), color=color) tex.draw_texture('yellow_box', 'branch_indicator', x=(diff*offset), color=color)
def _draw_tja_data_diff(self, is_ura: bool, song_box: SongBox): def _draw_tja_data_diff(self, is_ura: bool, song_box: SongBox):
if not self.tja: if not self.tja:
@@ -443,37 +441,39 @@ class YellowBox:
tex.draw_texture('diff_select', 'option', fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'option', fade=self.fade_in.attribute)
tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute)
offset_x = tex.skin_config['yb_diff_offset_diff_select'].x
offset_y = tex.skin_config['yb_diff_offset_diff_select'].y
for diff in self.tja.metadata.course_data: for diff in self.tja.metadata.course_data:
if diff >= Difficulty.URA: if diff >= Difficulty.URA:
continue continue
elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] is not None and song_box.scores[diff][4] == 2 and song_box.scores[diff][2] == 0) or (song_box.scores[diff][2] == 0 and song_box.scores[diff][3] == 0)): elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] is not None and song_box.scores[diff][4] == 2 and song_box.scores[diff][2] == 0) or (song_box.scores[diff][2] == 0 and song_box.scores[diff][3] == 0)):
tex.draw_texture('yellow_box', 's_crown_dfc', x=(diff*115)+8, y=-120, fade=self.fade_in.attribute) tex.draw_texture('yellow_box', 's_crown_dfc', x=(diff*offset_x)+tex.skin_config['yb_diff_offset_crown'].x, y=offset_y, fade=self.fade_in.attribute)
elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] is not None and song_box.scores[diff][4] == 2) or (song_box.scores[diff][3] == 0)): elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] is not None and song_box.scores[diff][4] == 2) or (song_box.scores[diff][3] == 0)):
tex.draw_texture('yellow_box', 's_crown_fc', x=(diff*115)+8, y=-120, fade=self.fade_in.attribute) tex.draw_texture('yellow_box', 's_crown_fc', x=(diff*offset_x)+tex.skin_config['yb_diff_offset_crown'].x, y=offset_y, fade=self.fade_in.attribute)
elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] >= 1: elif diff in song_box.scores and song_box.scores[diff] is not None and song_box.scores[diff][4] is not None and song_box.scores[diff][4] >= 1:
tex.draw_texture('yellow_box', 's_crown_clear', x=(diff*115)+8, y=-120, fade=self.fade_in.attribute) tex.draw_texture('yellow_box', 's_crown_clear', x=(diff*offset_x)+tex.skin_config['yb_diff_offset_crown'].x, y=offset_y, fade=self.fade_in.attribute)
tex.draw_texture('yellow_box', 's_crown_outline', x=(diff*115)+8, y=-120, fade=min(self.fade_in.attribute, 0.25)) tex.draw_texture('yellow_box', 's_crown_outline', x=(diff*offset_x)+tex.skin_config['yb_diff_offset_crown'].x, y=offset_y, fade=min(self.fade_in.attribute, 0.25))
for i in range(4): for i in range(4):
if i == Difficulty.ONI and is_ura: if i == Difficulty.ONI and is_ura:
tex.draw_texture('diff_select', 'diff_tower', frame=4, x=(i*115), fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'diff_tower', frame=4, x=(i*offset_x), fade=self.fade_in.attribute)
tex.draw_texture('diff_select', 'ura_oni_plate', fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'ura_oni_plate', fade=self.fade_in.attribute)
else: else:
tex.draw_texture('diff_select', 'diff_tower', frame=i, x=(i*115), fade=self.fade_in.attribute) tex.draw_texture('diff_select', 'diff_tower', frame=i, x=(i*offset_x), fade=self.fade_in.attribute)
if i not in self.tja.metadata.course_data: if i not in self.tja.metadata.course_data:
tex.draw_texture('diff_select', 'diff_tower_shadow', frame=i, x=(i*115), fade=min(self.fade_in.attribute, 0.25)) tex.draw_texture('diff_select', 'diff_tower_shadow', frame=i, x=(i*offset_x), fade=min(self.fade_in.attribute, 0.25))
for course in self.tja.metadata.course_data: for course in self.tja.metadata.course_data:
if (course == Difficulty.URA and not is_ura) or (course == Difficulty.ONI and is_ura): if (course == Difficulty.URA and not is_ura) or (course == Difficulty.ONI and is_ura):
continue continue
for j in range(self.tja.metadata.course_data[course].level): for j in range(self.tja.metadata.course_data[course].level):
tex.draw_texture('yellow_box', 'star_ura', x=min(course, Difficulty.ONI)*115, y=(j*-20), fade=self.fade_in.attribute) tex.draw_texture('yellow_box', 'star_ura', x=min(course, Difficulty.ONI)*offset_x, y=(j*tex.skin_config["yb_diff_offset_crown"].y), fade=self.fade_in.attribute)
if self.tja.metadata.course_data[course].is_branching and (get_current_ms() // 1000) % 2 == 0: if self.tja.metadata.course_data[course].is_branching and (get_current_ms() // 1000) % 2 == 0:
if course == Difficulty.URA: if course == Difficulty.URA:
name = 'branch_indicator_ura' name = 'branch_indicator_ura'
else: else:
name = 'branch_indicator_diff' name = 'branch_indicator_diff'
tex.draw_texture('yellow_box', name, x=min(course, Difficulty.ONI)*115, fade=self.fade_in.attribute) tex.draw_texture('yellow_box', name, x=min(course, Difficulty.ONI)*offset_x, fade=self.fade_in.attribute)
def _draw_text(self, song_box, name: OutlinedText): def _draw_text(self, song_box, name: OutlinedText):
if not isinstance(self.right_out, MoveAnimation): if not isinstance(self.right_out, MoveAnimation):
@@ -487,11 +487,11 @@ class YellowBox:
tex.draw_texture('box', 'back_text_highlight', x=x) tex.draw_texture('box', 'back_text_highlight', x=x)
else: else:
texture = name.texture texture = name.texture
name.draw(outline_color=ray.BLACK, x=x + 30, y=35 + self.top_y_out.attribute, y2=min(texture.height, 417)-texture.height, color=ray.WHITE) name.draw(outline_color=ray.BLACK, x=x + tex.skin_config["yb_name"].x, y=tex.skin_config["yb_name"].y + self.top_y_out.attribute, y2=min(texture.height, tex.skin_config["yb_name"].height)-texture.height, color=ray.WHITE)
if self.subtitle is not None: if self.subtitle is not None:
texture = self.subtitle.texture texture = self.subtitle.texture
y = self.bottom_y - min(texture.height, 410) + 10 + self.top_y_out.attribute - self.top_y_out.start_position y = self.bottom_y - min(texture.height, tex.skin_config["yb_subtitle"].height) + tex.skin_config["yb_subtitle"].y + self.top_y_out.attribute - self.top_y_out.start_position
self.subtitle.draw(outline_color=ray.BLACK, x=x-15, y=y, y2=min(texture.height, 410)-texture.height) self.subtitle.draw(outline_color=ray.BLACK, x=x+tex.skin_config["yb_subtitle"].x, y=y, y2=min(texture.height, tex.skin_config["yb_subtitle"].height)-texture.height)
def _draw_yellow_box(self): def _draw_yellow_box(self):
tex.draw_texture('yellow_box', 'yellow_box_bottom_right', x=self.right_x) tex.draw_texture('yellow_box', 'yellow_box_bottom_right', x=self.right_x)
@@ -541,12 +541,12 @@ class DanBox(BaseBox):
def load_text(self): def load_text(self):
super().load_text() super().load_text()
self.hori_name = OutlinedText(self.text_name, 40, ray.WHITE) self.hori_name = OutlinedText(self.text_name, tex.skin_config["dan_title"].font_size, ray.WHITE)
for song, genre, difficulty, level in self.songs: for song, genre, difficulty, level in self.songs:
title = song.metadata.title.get(global_data.config["general"]["language"], song.metadata.title["en"]) title = song.metadata.title.get(global_data.config["general"]["language"], song.metadata.title["en"])
subtitle = song.metadata.subtitle.get(global_data.config["general"]["language"], "") subtitle = song.metadata.subtitle.get(global_data.config["general"]["language"], "")
title_text = OutlinedText(title, 40, ray.WHITE, vertical=True) title_text = OutlinedText(title, tex.skin_config["dan_title"].font_size, ray.WHITE, vertical=True)
font_size = 30 if len(subtitle) < 30 else 20 font_size = tex.skin_config["dan_subtitle"].font_size if len(subtitle) < 30 else tex.skin_config["dan_subtitle"].font_size - int(10 * tex.screen_scale)
subtitle_text = OutlinedText(subtitle, font_size, ray.WHITE, vertical=True) subtitle_text = OutlinedText(subtitle, font_size, ray.WHITE, vertical=True)
self.song_text.append((title_text, subtitle_text)) self.song_text.append((title_text, subtitle_text))
self.text_loaded = True self.text_loaded = True
@@ -575,28 +575,29 @@ class DanBox(BaseBox):
tex.draw_texture('yellow_box', 'exam_box_center') tex.draw_texture('yellow_box', 'exam_box_center')
tex.draw_texture('yellow_box', 'exam_header') tex.draw_texture('yellow_box', 'exam_header')
offset = tex.skin_config["exam_box_offset"].y
for i, exam in enumerate(self.exams): for i, exam in enumerate(self.exams):
tex.draw_texture('yellow_box', 'judge_box', y=(i*83)) tex.draw_texture('yellow_box', 'judge_box', y=(i*offset))
tex.draw_texture('yellow_box', 'exam_' + self.exams[i].type, y=(i*83)) tex.draw_texture('yellow_box', 'exam_' + exam.type, y=(i*offset))
counter = str(self.exams[i].red) counter = str(exam.red)
margin = 20 margin = tex.skin_config["exam_counter_margin"].x
if self.exams[i].type == 'gauge': if exam.type == 'gauge':
tex.draw_texture('yellow_box', 'exam_percent', y=(i*83)) tex.draw_texture('yellow_box', 'exam_percent', y=(i*offset))
offset = -8 x_offset = tex.skin_config["exam_gauge_offset"].x
else: else:
offset = 0 x_offset = 0
for j in range(len(counter)): for j in range(len(counter)):
tex.draw_texture('yellow_box', 'judge_num', frame=int(counter[j]), x=offset-(len(counter) - j) * margin, y=(i*83)) tex.draw_texture('yellow_box', 'judge_num', frame=int(counter[j]), x=x_offset-(len(counter) - j) * margin, y=(i*offset))
if self.exams[i].range == 'more': if exam.range == 'more':
tex.draw_texture('yellow_box', 'exam_more', x=(offset*-1.7), y=(i*83)) tex.draw_texture('yellow_box', 'exam_more', x=(x_offset*-1.7), y=(i*offset))
elif self.exams[i].range == 'less': elif exam.range == 'less':
tex.draw_texture('yellow_box', 'exam_less', x=(offset*-1.7), y=(i*83)) tex.draw_texture('yellow_box', 'exam_less', x=(x_offset*-1.7), y=(i*offset))
def _draw_closed(self, x: float, y: float): def _draw_closed(self, x: float, y: float):
tex.draw_texture('box', 'folder', frame=self.texture_index, x=x) tex.draw_texture('box', 'folder', frame=self.texture_index, x=x)
if self.name is not None: if self.name is not None:
self.name.draw(outline_color=ray.BLACK, x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height) self.name.draw(outline_color=ray.BLACK, x=x + tex.skin_config["song_box_name"].x - int(self.name.texture.width / 2), y=y+tex.skin_config["song_box_name"].height, y2=min(self.name.texture.height, tex.skin_config["song_box_name"].height)-self.name.texture.height)
def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool): def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool):
if fade_override is not None: if fade_override is not None:
@@ -607,29 +608,32 @@ class DanBox(BaseBox):
self.yellow_box.draw(None, None, False, self.name) self.yellow_box.draw(None, None, False, self.name)
for i, song in enumerate(self.song_text): for i, song in enumerate(self.song_text):
title, subtitle = song title, subtitle = song
x = i * 140 x = i * tex.skin_config["dan_yellow_box_offset"].x
tex.draw_texture('yellow_box', 'genre_banner', x=x, frame=self.songs[i][1], fade=fade) tex.draw_texture('yellow_box', 'genre_banner', x=x, frame=self.songs[i][1], fade=fade)
tex.draw_texture('yellow_box', 'difficulty', x=x, frame=self.songs[i][2], fade=fade) tex.draw_texture('yellow_box', 'difficulty', x=x, frame=self.songs[i][2], fade=fade)
tex.draw_texture('yellow_box', 'difficulty_x', x=x, fade=fade) tex.draw_texture('yellow_box', 'difficulty_x', x=x, fade=fade)
tex.draw_texture('yellow_box', 'difficulty_star', x=x, fade=fade) tex.draw_texture('yellow_box', 'difficulty_star', x=x, fade=fade)
level = self.songs[i][0].metadata.course_data[self.songs[i][2]].level level = self.songs[i][0].metadata.course_data[self.songs[i][2]].level
counter = str(level) counter = str(level)
total_width = len(counter) * 10 margin = tex.skin_config["dan_level_counter_margin"].x
total_width = len(counter) * margin
for i in range(len(counter)): for i in range(len(counter)):
tex.draw_texture('yellow_box', 'difficulty_num', frame=int(counter[i]), x=x-(total_width // 2) + (i * 10), fade=fade) tex.draw_texture('yellow_box', 'difficulty_num', frame=int(counter[i]), x=x-(total_width // 2) + (i * margin), fade=fade)
title.draw(outline_color=ray.BLACK, x=665+x, y=127, y2=min(title.texture.height, 400)-title.texture.height, fade=fade) title_data = tex.skin_config["dan_title"]
subtitle.draw(outline_color=ray.BLACK, x=620+x, y=525-min(subtitle.texture.height, 400), y2=min(subtitle.texture.height, 400)-subtitle.texture.height, fade=fade) subtitle_data = tex.skin_config["dan_subtitle"]
title.draw(outline_color=ray.BLACK, x=title_data.x+x, y=title_data.y, y2=min(title.texture.height, title_data.height)-title.texture.height, fade=fade)
subtitle.draw(outline_color=ray.BLACK, x=subtitle_data.x+x, y=subtitle_data.y-min(subtitle.texture.height, subtitle_data.height), y2=min(subtitle.texture.height, subtitle_data.height)-subtitle.texture.height, fade=fade)
tex.draw_texture('yellow_box', 'total_notes_bg', fade=fade) tex.draw_texture('yellow_box', 'total_notes_bg', fade=fade)
tex.draw_texture('yellow_box', 'total_notes', fade=fade) tex.draw_texture('yellow_box', 'total_notes', fade=fade)
counter = str(self.total_notes) counter = str(self.total_notes)
for i in range(len(counter)): for i in range(len(counter)):
tex.draw_texture('yellow_box', 'total_notes_counter', frame=int(counter[i]), x=(i * 25), fade=fade) tex.draw_texture('yellow_box', 'total_notes_counter', frame=int(counter[i]), x=(i * tex.skin_config["total_notes_counter_margin"].x), fade=fade)
tex.draw_texture('yellow_box', 'frame', frame=self.texture_index, fade=fade) tex.draw_texture('yellow_box', 'frame', frame=self.texture_index, fade=fade)
if self.hori_name is not None: if self.hori_name is not None:
self.hori_name.draw(outline_color=ray.BLACK, x=434 - (self.hori_name.texture.width//2), y=84, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width, fade=fade) self.hori_name.draw(outline_color=ray.BLACK, x=tex.skin_config["dan_hori_name"].x - (self.hori_name.texture.width//2), y=tex.skin_config["dan_hori_name"].y, x2=min(self.hori_name.texture.width, tex.skin_config["dan_hori_name"].width)-self.hori_name.texture.width, fade=fade)
self._draw_exam_box() self._draw_exam_box()
@@ -649,42 +653,42 @@ class GenreBG:
self.end_position = self.end_box.position self.end_position = self.end_box.position
self.fade_in.update(current_ms) self.fade_in.update(current_ms)
def draw(self, y): def draw(self, y):
offset = -150 if self.start_box.is_open else 0 offset = (tex.skin_config["genre_bg_offset"].x * -1) if self.start_box.is_open else 0
tex.draw_texture('box', 'folder_background_edge', frame=self.end_box.texture_index, x=self.start_position+offset, y=y, mirror="horizontal", fade=self.fade_in.attribute) tex.draw_texture('box', 'folder_background_edge', frame=self.end_box.texture_index, x=self.start_position+offset, y=y, mirror="horizontal", fade=self.fade_in.attribute)
extra_distance = 155 if self.end_box.is_open or (self.start_box.is_open and 844 <= self.end_position <= 1144) else 0 extra_distance = tex.skin_config["genre_bg_extra_distance"].x if self.end_box.is_open or (self.start_box.is_open and (844 * tex.screen_scale) <= self.end_position <= (1144 * tex.screen_scale)) else 0
if self.start_position >= -56 and self.end_position < self.start_position: if self.start_position >= tex.skin_config["genre_bg_left_max"].x and self.end_position < self.start_position:
x2 = self.start_position + 1400 x2 = self.start_position + tex.skin_config["genre_bg_offset_2"].x
x = self.start_position+offset x = self.start_position+offset
elif (self.start_position <= -56) and (self.end_position < self.start_position): elif (self.start_position <= tex.skin_config["genre_bg_left_max"].x) and (self.end_position < self.start_position):
x = 0 x = 0
x2 = 1280 x2 = tex.screen_width
else: else:
x2 = abs(self.end_position) - self.start_position + extra_distance + 57 x2 = abs(self.end_position) - self.start_position + extra_distance + (-1 * tex.skin_config["genre_bg_left_max"].x + (1 * tex.screen_scale))
x = self.start_position+offset x = self.start_position+offset
tex.draw_texture('box', 'folder_background', x=x, y=y, x2=x2, frame=self.end_box.texture_index) tex.draw_texture('box', 'folder_background', x=x, y=y, x2=x2, frame=self.end_box.texture_index)
if self.end_position < self.start_position and self.end_position >= -56: if self.end_position < self.start_position and self.end_position >= tex.skin_config["genre_bg_left_max"].x:
x2 = min(self.end_position+75, 1280) + extra_distance x2 = min(self.end_position+tex.skin_config["genre_bg_folder_background"].width, tex.screen_width) + extra_distance
tex.draw_texture('box', 'folder_background', x=-18, y=y, x2=x2, frame=self.end_box.texture_index) tex.draw_texture('box', 'folder_background', x=tex.skin_config["genre_bg_folder_background"].x, y=y, x2=x2, frame=self.end_box.texture_index)
offset = 150 if self.end_box.is_open else 0 offset = tex.skin_config["genre_bg_offset"].x if self.end_box.is_open else 0
tex.draw_texture('box', 'folder_background_edge', x=self.end_position+80+offset, y=y, fade=self.fade_in.attribute, frame=self.end_box.texture_index) tex.draw_texture('box', 'folder_background_edge', x=self.end_position+tex.skin_config["genre_bg_folder_edge"].x+offset, y=y, fade=self.fade_in.attribute, frame=self.end_box.texture_index)
if ((self.start_position <= 594 and self.end_position >= 594) or if ((self.start_position <= BOX_CENTER and self.end_position >= BOX_CENTER) or
((self.start_position <= 594 or self.end_position >= 594) and (self.start_position > self.end_position))): ((self.start_position <= BOX_CENTER or self.end_position >= BOX_CENTER) and (self.start_position > self.end_position))):
offset = 100 if self.diff_num is not None else 0 offset = tex.skin_config["genre_bg_offset_3"].x if self.diff_num is not None else 0
dest_width = min(300, self.title.texture.width) dest_width = min(tex.skin_config["genre_bg_title"].width, self.title.texture.width)
tex.draw_texture('box', 'folder_background_folder', x=-((offset+dest_width)//2), y=y-2, x2=dest_width+offset - 10, fade=self.fade_in.attribute, frame=self.end_box.texture_index) tex.draw_texture('box', 'folder_background_folder', x=-((offset+dest_width)//2), y=y+tex.skin_config["genre_bg_folder_background_folder"].y, x2=dest_width+offset++tex.skin_config["genre_bg_folder_background_folder"].width, fade=self.fade_in.attribute, frame=self.end_box.texture_index)
tex.draw_texture('box', 'folder_background_folder_edge', x=-((offset+dest_width)//2), y=y-2, fade=self.fade_in.attribute, frame=self.end_box.texture_index, mirror="horizontal") tex.draw_texture('box', 'folder_background_folder_edge', x=-((offset+dest_width)//2), y=y+tex.skin_config["genre_bg_folder_background_folder"].y, fade=self.fade_in.attribute, frame=self.end_box.texture_index, mirror="horizontal")
tex.draw_texture('box', 'folder_background_folder_edge', x=((offset+dest_width)//2)+20, y=y-2, fade=self.fade_in.attribute, frame=self.end_box.texture_index) tex.draw_texture('box', 'folder_background_folder_edge', x=((offset+dest_width)//2)+tex.skin_config["genre_bg_folder_background_folder"].x, y=y+tex.skin_config["genre_bg_folder_background_folder"].y, fade=self.fade_in.attribute, frame=self.end_box.texture_index)
if self.diff_num is not None: if self.diff_num is not None:
tex.draw_texture('diff_sort', 'star_num', frame=self.diff_num, x=-150 + (dest_width//2), y=-143) tex.draw_texture('diff_sort', 'star_num', frame=self.diff_num, x=(tex.skin_config["genre_bg_offset"].x * -1) + (dest_width//2), y=tex.skin_config["diff_sort_star_num"].y)
self.title.draw(outline_color=ray.BLACK, x=(SCREEN_WIDTH//2) - (dest_width//2)-(offset//2), y=y-60, x2=dest_width - self.title.texture.width, color=ray.fade(ray.WHITE, self.fade_in.attribute)) self.title.draw(outline_color=ray.BLACK, x=(tex.screen_width//2) - (dest_width//2)-(offset//2), y=y+tex.skin_config["genre_bg_title"].y, x2=dest_width - self.title.texture.width, color=ray.fade(ray.WHITE, self.fade_in.attribute))
class ScoreHistory: class ScoreHistory:
"""The score information that appears while hovering over a song""" """The score information that appears while hovering over a song"""
@@ -726,7 +730,7 @@ class ScoreHistory:
tex.draw_texture('leaderboard', 'difficulty', frame=self.curr_difficulty, index=self.long) tex.draw_texture('leaderboard', 'difficulty', frame=self.curr_difficulty, index=self.long)
for i in range(4): for i in range(4):
tex.draw_texture('leaderboard', 'normal', index=self.long, y=50+(i*50)) tex.draw_texture('leaderboard', 'normal', index=self.long, y=tex.skin_config["score_info_bg_offset"].y+(i*tex.skin_config["score_info_bg_offset"].y))
tex.draw_texture('leaderboard', 'judge_good') tex.draw_texture('leaderboard', 'judge_good')
tex.draw_texture('leaderboard', 'judge_ok') tex.draw_texture('leaderboard', 'judge_ok')
@@ -739,12 +743,12 @@ class ScoreHistory:
if counter is None: if counter is None:
continue continue
counter = str(counter) counter = str(counter)
margin = 24 margin = tex.skin_config["score_info_counter_margin"].x
for i in range(len(counter)): for i in range(len(counter)):
if j == 0: if j == 0:
tex.draw_texture('leaderboard', 'counter', frame=int(counter[i]), x=-((len(counter) * 14) // 2) + (i * 14), color=ray.WHITE, index=self.long) tex.draw_texture('leaderboard', 'counter', frame=int(counter[i]), x=-((len(counter) * tex.skin_config["score_info_counter_margin"].width) // 2) + (i * tex.skin_config["score_info_counter_margin"].width), color=ray.WHITE, index=self.long)
else: else:
tex.draw_texture('leaderboard', 'judge_num', frame=int(counter[i]), x=-(len(counter) - i) * margin, y=j*50) tex.draw_texture('leaderboard', 'judge_num', frame=int(counter[i]), x=-(len(counter) - i) * margin, y=j*tex.skin_config["score_info_bg_offset"].y)
def draw(self): def draw(self):
if self.long: if self.long:
@@ -766,19 +770,19 @@ class ScoreHistory:
tex.draw_texture('leaderboard','ura') tex.draw_texture('leaderboard','ura')
tex.draw_texture('leaderboard', 'pts', color=color) tex.draw_texture('leaderboard', 'pts', color=color)
tex.draw_texture('leaderboard', 'pts', y=50) tex.draw_texture('leaderboard', 'pts', y=tex.skin_config["score_info_bg_offset"].y)
tex.draw_texture('leaderboard', 'difficulty', frame=self.curr_difficulty) tex.draw_texture('leaderboard', 'difficulty', frame=self.curr_difficulty)
counter = str(self.curr_score) counter = str(self.curr_score)
total_width = len(counter) * 14 total_width = len(counter) * tex.skin_config["score_info_counter_margin"].width
for i in range(len(counter)): for i in range(len(counter)):
tex.draw_texture('leaderboard', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * 14), color=color) tex.draw_texture('leaderboard', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * tex.skin_config["score_info_counter_margin"].width), color=color)
counter = str(self.curr_score_su) counter = str(self.curr_score_su)
total_width = len(counter) * 14 total_width = len(counter) * tex.skin_config["score_info_counter_margin"].width
for i in range(len(counter)): for i in range(len(counter)):
tex.draw_texture('leaderboard', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * 14), y=50, color=ray.WHITE) tex.draw_texture('leaderboard', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * tex.skin_config["score_info_counter_margin"].width), y=tex.skin_config["score_info_bg_offset"].y, color=ray.WHITE)
def parse_box_def(path: Path): def parse_box_def(path: Path):
"""Parse box.def file for directory metadata""" """Parse box.def file for directory metadata"""
@@ -1469,26 +1473,23 @@ class FileNavigator:
offset += len(self.items) offset += len(self.items)
# Adjust spacing based on dan select mode # Adjust spacing based on dan select mode
base_spacing = 100 base_spacing = 100 * tex.screen_scale
center_offset = 150 center_offset = 150 * tex.screen_scale
side_offset_l = 0 side_offset_l = 0 * tex.screen_scale
side_offset_r = 300 side_offset_r = 300 * tex.screen_scale
if self.in_dan_select: if self.in_dan_select:
base_spacing = 150 base_spacing = 150 * tex.screen_scale
side_offset_l = 200 side_offset_l = 200 * tex.screen_scale
side_offset_r = 500 side_offset_r = 500 * tex.screen_scale
position = (BOX_CENTER - 150) + (base_spacing * offset) position = (BOX_CENTER - center_offset) + (base_spacing * offset)
if position == BOX_CENTER - 150: if position == BOX_CENTER - center_offset:
#item.box.is_open = True
position += center_offset position += center_offset
elif position > BOX_CENTER - 150: elif position > BOX_CENTER - center_offset:
#item.box.is_open = False
position += side_offset_r position += side_offset_r
else: else:
position -= side_offset_l position -= side_offset_l
#item.box.is_open = False
if item.box.position == float('inf'): if item.box.position == float('inf'):
item.box.position = position item.box.position = position

View File

@@ -1,7 +1,9 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import IntEnum from enum import IntEnum
from pathlib import Path from pathlib import Path
from typing import Any, TypedDict from typing import Any
from libs.config import Config
class PlayerNum(IntEnum): class PlayerNum(IntEnum):
ALL = 0 ALL = 0
@@ -26,90 +28,6 @@ class Crown(IntEnum):
FC = 2 FC = 2
DFC = 3 DFC = 3
class GeneralConfig(TypedDict):
fps_counter: bool
audio_offset: int
visual_offset: int
language: str
hard_judge: int
touch_enabled: bool
timer_frozen: bool
judge_counter: bool
nijiiro_notes: bool
log_level: int
fake_online: bool
class NameplateConfig(TypedDict):
name: str
title: str
title_bg: int
dan: int
gold: bool
rainbow: bool
class PathsConfig(TypedDict):
tja_path: list[Path]
video_path: list[Path]
class KeysConfig(TypedDict):
exit_key: int
fullscreen_key: int
borderless_key: int
pause_key: int
back_key: int
restart_key: int
class Keys1PConfig(TypedDict):
left_kat: list[int]
left_don: list[int]
right_don: list[int]
right_kat: list[int]
class Keys2PConfig(TypedDict):
left_kat: list[int]
left_don: list[int]
right_don: list[int]
right_kat: list[int]
class GamepadConfig(TypedDict):
left_kat: list[int]
left_don: list[int]
right_don: list[int]
right_kat: list[int]
class AudioConfig(TypedDict):
device_type: int
sample_rate: int
buffer_size: int
class VolumeConfig(TypedDict):
sound: float
music: float
voice: float
hitsound: float
attract_mode: float
class VideoConfig(TypedDict):
screen_width: int
screen_height: int
fullscreen: bool
borderless: bool
target_fps: int
vsync: bool
class Config(TypedDict):
general: GeneralConfig
nameplate_1p: NameplateConfig
nameplate_2p: NameplateConfig
paths: PathsConfig
keys: KeysConfig
keys_1p: Keys1PConfig
keys_2p: Keys2PConfig
gamepad: GamepadConfig
audio: AudioConfig
volume: VolumeConfig
video: VideoConfig
@dataclass @dataclass
class Modifiers: class Modifiers:
""" """

View File

@@ -3,7 +3,8 @@ from typing import Callable
import pyray as ray import pyray as ray
from libs.global_data import PlayerNum from libs.global_data import PlayerNum
from libs.utils import OutlinedText, get_config, global_tex from libs.utils import OutlinedText, global_tex
from libs.config import get_config
from libs.audio import audio from libs.audio import audio

View File

@@ -7,7 +7,8 @@ from pathlib import Path
from libs.global_data import Crown from libs.global_data import Crown
from libs.tja import NoteList, TJAParser, test_encodings from libs.tja import NoteList, TJAParser, test_encodings
from libs.utils import get_config, global_data from libs.utils import global_data
from libs.config import get_config
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@@ -12,9 +12,7 @@ from pyray import Vector2, Rectangle, Color
from libs.animation import BaseAnimation, parse_animations from libs.animation import BaseAnimation, parse_animations
SCREEN_WIDTH = 1280 from libs.config import get_config
SCREEN_HEIGHT = 720
SCREEN_SCALE = SCREEN_WIDTH / 1280
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -52,12 +50,15 @@ class TextureWrapper:
self.textures: dict[str, dict[str, Texture]] = dict() self.textures: dict[str, dict[str, Texture]] = dict()
self.animations: dict[int, BaseAnimation] = dict() self.animations: dict[int, BaseAnimation] = dict()
self.skin_config: dict[str, SkinInfo] = dict() self.skin_config: dict[str, SkinInfo] = dict()
self.graphics_path = Path("Graphics") self.graphics_path = Path(get_config()['paths']['graphics_path'])
if (self.graphics_path / "skin_config.json").exists(): if (self.graphics_path / "skin_config.json").exists():
data = json.loads((self.graphics_path / "skin_config.json").read_text()) data = json.loads((self.graphics_path / "skin_config.json").read_text())
self.skin_config: dict[str, SkinInfo] = { self.skin_config: dict[str, SkinInfo] = {
k: SkinInfo(v.get('x', 0), v.get('y', 0), v.get('font_size', 0), v.get('width', 0), v.get('height', 0)) for k, v in data.items() k: SkinInfo(v.get('x', 0), v.get('y', 0), v.get('font_size', 0), v.get('width', 0), v.get('height', 0)) for k, v in data.items()
} }
self.screen_width = int(self.skin_config["screen"].width)
self.screen_height = int(self.skin_config["screen"].height)
self.screen_scale = self.screen_width / 1280
def unload_textures(self): def unload_textures(self):
"""Unload all textures and animations.""" """Unload all textures and animations."""

View File

@@ -11,7 +11,7 @@ from pathlib import Path
from typing import Optional from typing import Optional
from libs.global_data import Modifiers from libs.global_data import Modifiers
from libs.utils import get_pixels_per_frame, strip_comments from libs.utils import get_pixels_per_frame, strip_comments, global_tex
@lru_cache(maxsize=64) @lru_cache(maxsize=64)
@@ -321,7 +321,7 @@ class TJAParser:
data (list): The data extracted from the TJA file. data (list): The data extracted from the TJA file.
""" """
DIFFS = {0: "easy", 1: "normal", 2: "hard", 3: "oni", 4: "edit", 5: "tower", 6: "dan"} DIFFS = {0: "easy", 1: "normal", 2: "hard", 3: "oni", 4: "edit", 5: "tower", 6: "dan"}
def __init__(self, path: Path, start_delay: int = 0, distance: int = 866): def __init__(self, path: Path, start_delay: int = 0, distance: float = 866):
""" """
Initialize a TJA object. Initialize a TJA object.
@@ -1012,10 +1012,10 @@ def modifier_speed(notes: NoteList, value: float):
modded_bars = notes.bars.copy() modded_bars = notes.bars.copy()
for note in modded_notes: for note in modded_notes:
note.pixels_per_frame_x *= value note.pixels_per_frame_x *= value
note.load_ms = note.hit_ms - (866 / get_pixels_per_ms(note.pixels_per_frame_x)) note.load_ms = note.hit_ms - (866 * global_tex.screen_scale / get_pixels_per_ms(note.pixels_per_frame_x))
for bar in modded_bars: for bar in modded_bars:
bar.pixels_per_frame_x *= value bar.pixels_per_frame_x *= value
bar.load_ms = bar.hit_ms - (866 / get_pixels_per_ms(bar.pixels_per_frame_x)) bar.load_ms = bar.hit_ms - (866 * global_tex.screen_scale / get_pixels_per_ms(bar.pixels_per_frame_x))
return modded_notes, modded_bars return modded_notes, modded_bars
def modifier_display(notes: NoteList): def modifier_display(notes: NoteList):

View File

@@ -20,8 +20,8 @@ class Transition:
self.title = '' self.title = ''
self.subtitle = '' self.subtitle = ''
else: else:
self.title = OutlinedText(title, 40, ray.WHITE) self.title = OutlinedText(title, global_tex.skin_config['transition_title'].font_size, ray.WHITE)
self.subtitle = OutlinedText(subtitle, 30, ray.WHITE) self.subtitle = OutlinedText(subtitle, global_tex.skin_config['transition_subtitle'].font_size, ray.WHITE)
self.is_second = is_second self.is_second = is_second
def start(self): def start(self):
@@ -48,26 +48,26 @@ class Transition:
if self.is_second: if self.is_second:
color_1 = ray.fade(ray.WHITE, self.song_info_fade_out.attribute) color_1 = ray.fade(ray.WHITE, self.song_info_fade_out.attribute)
color_2 = ray.fade(ray.WHITE, min(0.70, self.song_info_fade_out.attribute)) color_2 = ray.fade(ray.WHITE, min(0.70, self.song_info_fade_out.attribute))
offset = 816 - self.rainbow_up.attribute offset = global_tex.skin_config['transition_offset'].y - self.rainbow_up.attribute
global_tex.draw_texture('rainbow_transition', 'text_bg', y=-self.rainbow_up.attribute - offset, color=color_2) global_tex.draw_texture('rainbow_transition', 'text_bg', y=-self.rainbow_up.attribute - offset, color=color_2)
if isinstance(self.title, OutlinedText): if isinstance(self.title, OutlinedText):
texture = self.title.texture texture = self.title.texture
x = 1280//2 - texture.width//2 x = global_tex.screen_width//2 - texture.width//2
y = 1176 - texture.height//2 - int(self.rainbow_up.attribute) - offset - 20 y = global_tex.skin_config['transition_title'].y - texture.height//2 - int(self.rainbow_up.attribute) - offset
self.title.draw(outline_color=ray.BLACK, x=x, y=y, color=color_1) self.title.draw(outline_color=ray.BLACK, x=x, y=y, color=color_1)
if isinstance(self.subtitle, OutlinedText): if isinstance(self.subtitle, OutlinedText):
texture = self.subtitle.texture texture = self.subtitle.texture
x = 1280//2 - texture.width//2 x = global_tex.screen_width//2 - texture.width//2
y = 1176 - texture.height//2 - int(self.rainbow_up.attribute) - offset - 20 y = global_tex.skin_config['transition_subtitle'].y - texture.height//2 - int(self.rainbow_up.attribute) - offset
self.subtitle.draw(outline_color=ray.BLACK, x=x, y=y + 50, color=color_1) self.subtitle.draw(outline_color=ray.BLACK, x=x, y=y, color=color_1)
def draw(self): def draw(self):
"""Draw the transition effect.""" """Draw the transition effect."""
total_offset = 0 total_offset = 0
if self.is_second: if self.is_second:
total_offset = 816 total_offset = global_tex.skin_config['transition_offset'].y
global_tex.draw_texture('rainbow_transition', 'rainbow_bg_bottom', y=-self.rainbow_up.attribute - total_offset) global_tex.draw_texture('rainbow_transition', 'rainbow_bg_bottom', y=-self.rainbow_up.attribute - total_offset)
global_tex.draw_texture('rainbow_transition', 'rainbow_bg_top', y=-self.rainbow_up.attribute - total_offset) global_tex.draw_texture('rainbow_transition', 'rainbow_bg_top', y=-self.rainbow_up.attribute - total_offset)
global_tex.draw_texture('rainbow_transition', 'rainbow_bg', y=-self.rainbow_up.attribute - total_offset) global_tex.draw_texture('rainbow_transition', 'rainbow_bg', y=-self.rainbow_up.attribute - total_offset)
@@ -75,7 +75,7 @@ class Transition:
chara_offset = 0 chara_offset = 0
if self.is_second: if self.is_second:
offset = self.chara_down.attribute - self.mini_up.attribute//3 offset = self.chara_down.attribute - self.mini_up.attribute//3
chara_offset = 408 chara_offset = global_tex.skin_config['transition_chara_offset'].y
if self.title == '' and self.subtitle == '': if self.title == '' and self.subtitle == '':
return return
global_tex.draw_texture('rainbow_transition', 'chara_left', x=-self.mini_up.attribute//2 - chara_offset, y=-self.mini_up.attribute + offset - total_offset) global_tex.draw_texture('rainbow_transition', 'chara_left', x=-self.mini_up.attribute//2 - chara_offset, y=-self.mini_up.attribute + offset - total_offset)

View File

@@ -3,22 +3,20 @@ import hashlib
import sys import sys
import logging import logging
import time import time
import json from libs.global_data import PlayerNum, global_data
from libs.global_data import Config, PlayerNum, global_data
from functools import lru_cache from functools import lru_cache
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
import pyray as ray import pyray as ray
import raylib as rl import raylib as rl
import tomlkit
from raylib import ( from raylib import (
SHADER_UNIFORM_FLOAT, SHADER_UNIFORM_FLOAT,
SHADER_UNIFORM_VEC2, SHADER_UNIFORM_VEC2,
SHADER_UNIFORM_VEC4, SHADER_UNIFORM_VEC4,
) )
from libs.texture import SCREEN_WIDTH, TextureWrapper from libs.texture import TextureWrapper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -75,68 +73,6 @@ def get_pixels_per_frame(bpm: float, time_signature: float, distance: float) ->
total_frames = 60 * total_time total_frames = 60 * total_time
return (distance / total_frames) return (distance / total_frames)
def get_config() -> Config:
"""Get the configuration from the TOML file"""
config_path = Path('dev-config.toml') if Path('dev-config.toml').exists() else Path('config.toml')
with open(config_path, "r", encoding="utf-8") as f:
config_file = tomlkit.load(f)
config: Config = json.loads(json.dumps(config_file))
for key in config['keys']:
config['keys'][key] = get_key_code(config['keys'][key])
for key in config['keys_1p']:
bindings = config['keys_1p'][key]
for i, bind in enumerate(bindings):
config['keys_1p'][key][i] = get_key_code(bind)
for key in config['keys_2p']:
bindings = config['keys_2p'][key]
for i, bind in enumerate(bindings):
config['keys_2p'][key][i] = get_key_code(bind)
return config
def save_config(config: Config) -> None:
"""Save the configuration to the TOML file"""
config_to_save = json.loads(json.dumps(config))
for key in config_to_save['keys']:
config_to_save['keys'][key] = get_key_string(config_to_save['keys'][key])
for key in config_to_save['keys_1p']:
bindings = config_to_save['keys_1p'][key]
for i, bind in enumerate(bindings):
config_to_save['keys_1p'][key][i] = get_key_string(bind)
for key in config_to_save['keys_2p']:
bindings = config_to_save['keys_2p'][key]
for i, bind in enumerate(bindings):
config_to_save['keys_2p'][key][i] = get_key_string(bind)
config_path = Path('dev-config.toml') if Path('dev-config.toml').exists() else Path('config.toml')
with open(config_path, "w", encoding="utf-8") as f:
tomlkit.dump(config_to_save, f)
def get_key_string(key_code: int) -> str:
"""Convert a key code back to its string representation"""
if 65 <= key_code <= 90:
return chr(key_code)
if 48 <= key_code <= 57:
return chr(key_code)
for attr_name in dir(ray):
if attr_name.startswith('KEY_'):
if getattr(ray, attr_name) == key_code:
return attr_name[4:].lower()
raise ValueError(f"Unknown key code: {key_code}")
def get_key_code(key: str) -> int:
if len(key) == 1 and key.isalnum():
return ord(key.upper())
else:
key_code = getattr(ray, f"KEY_{key.upper()}", None)
if key_code is None:
raise ValueError(f"Invalid key: {key}")
return key_code
def is_input_key_pressed(keys: list[int], gamepad_buttons: list[int]): def is_input_key_pressed(keys: list[int], gamepad_buttons: list[int]):
if global_data.input_locked: if global_data.input_locked:
return False return False
@@ -230,7 +166,7 @@ class OutlinedText:
""" """
self.text = text self.text = text
self.hash = self._hash_text(text, font_size, color, vertical) self.hash = self._hash_text(text, font_size, color, vertical)
self.outline_thickness = outline_thickness * (SCREEN_WIDTH/1280) self.outline_thickness = outline_thickness * global_tex.screen_scale
if self.hash in text_cache: if self.hash in text_cache:
self.texture = ray.load_texture(f'cache/image/{self.hash}.png') self.texture = ray.load_texture(f'cache/image/{self.hash}.png')
else: else:
@@ -496,7 +432,7 @@ class OutlinedText:
final_color = ray.fade(color, fade) final_color = ray.fade(color, fade)
else: else:
final_color = color final_color = color
dest_rect = ray.Rectangle(x, y, self.texture.width+x2, self.texture.height+y2) dest_rect = ray.Rectangle(x, y+((10 * global_tex.screen_scale)-10), self.texture.width+x2, self.texture.height+y2)
if self.outline_thickness > 0: if self.outline_thickness > 0:
ray.begin_shader_mode(self.shader) ray.begin_shader_mode(self.shader)
ray.draw_texture_pro(self.texture, self.default_src, dest_rect, origin, rotation, final_color) ray.draw_texture_pro(self.texture, self.default_src, dest_rect, origin, rotation, final_color)

View File

@@ -6,7 +6,7 @@ from moviepy import VideoFileClip
from libs.audio import audio from libs.audio import audio
from libs.utils import get_current_ms from libs.utils import get_current_ms
from libs.texture import SCREEN_WIDTH, SCREEN_HEIGHT from libs.texture import tex
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -120,7 +120,7 @@ class VideoPlayer:
def draw(self): def draw(self):
"""Draw video frames to the raylib canvas""" """Draw video frames to the raylib canvas"""
if self.texture is not None: if self.texture is not None:
ray.DrawTexturePro(self.texture, (0, 0, self.texture.width, self.texture.height), (0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), (0, 0), 0, ray.WHITE) ray.DrawTexturePro(self.texture, (0, 0, self.texture.width, self.texture.height), (0, 0, tex.screen_width, tex.screen_height), (0, 0), 0, ray.WHITE)
def stop(self): def stop(self):
"""Stops the video, audio, and clears its buffer""" """Stops the video, audio, and clears its buffer"""

View File

@@ -28,13 +28,13 @@ class DanResultScreen(Screen):
self.coin_overlay = CoinOverlay() self.coin_overlay = CoinOverlay()
self.allnet_indicator = AllNetIcon() self.allnet_indicator = AllNetIcon()
self.start_ms = get_current_ms() 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.player = DanResultPlayer(global_data.player_num)
self.is_result_2 = False self.is_result_2 = False
self.result_2_fade_in = tex.get_animation(1) 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.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.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, 40, ray.WHITE) 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_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 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) 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") return self.on_screen_end("DAN_SELECT")
def draw_overlay(self): 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.coin_overlay.draw()
self.allnet_indicator.draw() self.allnet_indicator.draw()
def draw_song_info_1(self): def draw_song_info_1(self):
result_data = global_data.session_data[global_data.player_num].dan_result_data 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)): for i in range(len(result_data.songs)):
song = result_data.songs[i] song = result_data.songs[i]
tex.draw_texture('background', 'genre_banner', y=i*height, frame=song.genre_index) 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', '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', 'difficulty', frame=song.selected_difficulty, y=i*height)
tex.draw_texture('result_info', 'diff_star', y=i*height) tex.draw_texture('result_info', 'diff_star', y=i*height)
tex.draw_texture('result_info', 'diff_x', y=i*height) tex.draw_texture('result_info', 'diff_x', y=i*height)
counter = str(song.diff_level)[::-1] counter = str(song.diff_level)[::-1]
margin = 12 margin = tex.skin_config["dan_result_diff_num_margin"].x
for j, digit in enumerate(counter): 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', 'diff_num', frame=int(digit), x=-(j*margin), y=i*height)
tex.draw_texture('result_info', 'good', 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] counter = str(song.good)[::-1]
for j, digit in enumerate(counter): for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'counter', index=0, frame=int(digit), x=-(j*margin), y=i*height) 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_divider', fade=fade, x=i*240)
tex.draw_texture('background', 'result_2_pullout', fade=fade) tex.draw_texture('background', 'result_2_pullout', fade=fade)
tex.draw_texture('result_info', 'dan_emblem', fade=fade, frame=result_data.dan_color) 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), self.hori_name.draw(outline_color=ray.BLACK, x=tex.skin_config["dan_result_hori_name"].x - (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)) 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) 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] counter = str(sum(song.good for song in result_data.songs))[::-1]
for j, digit in enumerate(counter): for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'counter', index=4, frame=int(digit), x=-(j*margin), fade=fade) 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', 'exam_header', fade=fade)
tex.draw_texture('result_info', 'score_box', 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] counter = str(result_data.score)[::-1]
for j, digit in enumerate(counter): for j, digit in enumerate(counter):
tex.draw_texture('result_info', 'score_counter', frame=int(digit), x=-(j*margin), fade=fade) 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 # Draw exam info
for i, exam in enumerate(self.exam_info): for i, exam in enumerate(self.exam_info):
exam_data = self.exam_data[i] 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_bg', y=y_offset, fade=fade, scale=scale)
tex.draw_texture('exam_info', 'exam_overlay_1', 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 # 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 # Draw exam type and red value counter
red_counter = str(exam.red) 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) 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 # Draw range indicator
if exam.range == 'less': if exam.range == 'less':
@@ -181,7 +181,7 @@ class DanResultScreen(Screen):
# Draw current value counter # Draw current value counter
tex.draw_texture('exam_info', 'exam_overlay_2', y=y_offset, fade=fade, scale=scale) tex.draw_texture('exam_info', 'exam_overlay_2', y=y_offset, fade=fade, scale=scale)
value_counter = str(exam_data.counter_value) 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': if exam.type == 'gauge':
tex.draw_texture('exam_info', 'exam_percent', y=y_offset, index=1, fade=fade, scale=scale) tex.draw_texture('exam_info', 'exam_percent', y=y_offset, index=1, fade=fade, scale=scale)
if exam_data.failed: if exam_data.failed:
@@ -207,15 +207,15 @@ class DanResultPlayer:
def __init__(self, player_num: PlayerNum): def __init__(self, player_num: PlayerNum):
plate_info = global_data.config[f'nameplate_{player_num}p'] 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.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): def update(self, current_time_ms: float):
self.nameplate.update(current_time_ms) self.nameplate.update(current_time_ms)
self.chara.update(current_time_ms, 100, False, False) self.chara.update(current_time_ms, 100, False, False)
def draw(self): def draw(self):
self.nameplate.draw(10, 585) self.nameplate.draw(tex.skin_config['dan_result_nameplate'].x, tex.skin_config['dan_result_nameplate'].y)
self.chara.draw(0, 405) self.chara.draw(tex.skin_config['dan_result_chara'].x, tex.skin_config['dan_result_chara'].y)
class DanGauge(Gauge): class DanGauge(Gauge):
"""The player's gauge""" """The player's gauge"""

View File

@@ -4,7 +4,7 @@ import pyray as ray
from libs.audio import audio from libs.audio import audio
from libs.global_data import PlayerNum, global_data 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.chara_2d import Chara2D
from libs.global_objects import AllNetIcon, CoinOverlay, Indicator, Nameplate, Timer from libs.global_objects import AllNetIcon, CoinOverlay, Indicator, Nameplate, Timer
from libs.screen import Screen from libs.screen import Screen
@@ -103,15 +103,15 @@ class DanSelectScreen(Screen):
tex.draw_texture('global', 'footer') tex.draw_texture('global', 'footer')
for item in self.navigator.items: for item in self.navigator.items:
box = item.box box = item.box
if -156 <= box.position <= SCREEN_WIDTH + 144: if (-156 * tex.screen_scale) <= box.position <= tex.screen_width + (144 * tex.screen_scale):
if box.position <= 500: if box.position <= (500 * tex.screen_scale):
box.draw(box.position, 95, False) box.draw(box.position, tex.skin_config["boxes"].y, False)
else: else:
box.draw(box.position, 95, False) box.draw(box.position, tex.skin_config["boxes"].y, False)
if self.state == State.SONG_SELECTED: 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.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.timer.draw()
self.coin_overlay.draw() self.coin_overlay.draw()
tex.draw_texture('global', 'dan_select') tex.draw_texture('global', 'dan_select')
@@ -133,7 +133,7 @@ class DanSelectPlayer:
self.confirmation_window = ConfirmationWindow() self.confirmation_window = ConfirmationWindow()
# Player-specific objects # 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'] plate_info = global_data.config[f'nameplate_{self.player_num}p']
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], 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']) 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): def draw(self):
if self.player_num == PlayerNum.P1: if self.player_num == PlayerNum.P1:
self.nameplate.draw(30, 640) self.nameplate.draw(tex.skin_config["dan_select_nameplate_1p"].x, tex.skin_config["dan_select_nameplate_1p"].y)
self.chara.draw(x=-50, y=410) self.chara.draw(x=tex.skin_config["dan_select_chara_1p"].x, y=tex.skin_config["dan_select_chara_1p"].y)
else: else:
self.nameplate.draw(950, 640) 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=950, y=410) 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() self.confirmation_window.draw()

View File

@@ -1,5 +1,5 @@
import copy import copy
from typing import override from typing import Optional, override
import pyray as ray import pyray as ray
import logging import logging
from libs.animation import Animation from libs.animation import Animation
@@ -11,7 +11,7 @@ from libs.global_objects import AllNetIcon
from libs.tja import TJAParser from libs.tja import TJAParser
from libs.transition import Transition from libs.transition import Transition
from libs.utils import OutlinedText, get_current_ms 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 from scenes.game import ClearAnimation, FCAnimation, FailAnimation, GameScreen, Gauge, ResultTransition, SongInfo
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -87,7 +87,7 @@ class DanGameScreen(GameScreen):
song, genre_index, difficulty, level = songs[self.song_index] song, genre_index, difficulty, level = songs[self.song_index]
session_data.selected_difficulty = difficulty session_data.selected_difficulty = difficulty
self.player_1.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: if self.song_music is not None:
audio.unload_music_stream(self.song_music) audio.unload_music_stream(self.song_music)
self.song_music = None self.song_music = None
@@ -281,22 +281,22 @@ class DanGameScreen(GameScreen):
# Draw total notes counter # Draw total notes counter
tex.draw_texture('dan_info', 'total_notes') tex.draw_texture('dan_info', 'total_notes')
counter = str(cache['remaining_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 # Draw exam info
for i, exam_info in enumerate(cache['exam_data']): 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'] exam = exam_info['exam']
tex.draw_texture('dan_info', 'exam_bg', y=y_offset) tex.draw_texture('dan_info', 'exam_bg', y=y_offset)
tex.draw_texture('dan_info', 'exam_overlay_1', y=y_offset) tex.draw_texture('dan_info', 'exam_overlay_1', y=y_offset)
# Draw progress bar # 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 # Draw exam type and red value counter
red_counter = str(exam_info['red_value']) 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) tex.draw_texture('dan_info', f'exam_{exam.type}', y=y_offset, x=-len(red_counter)*20)
# Draw range indicator # Draw range indicator
@@ -308,7 +308,7 @@ class DanGameScreen(GameScreen):
# Draw current value counter # Draw current value counter
tex.draw_texture('dan_info', 'exam_overlay_2', y=y_offset) tex.draw_texture('dan_info', 'exam_overlay_2', y=y_offset)
value_counter = str(exam_info['counter_value']) 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': if exam.type == 'gauge':
tex.draw_texture('dan_info', 'exam_percent', y=y_offset, index=1) tex.draw_texture('dan_info', 'exam_percent', y=y_offset, index=1)
@@ -320,10 +320,10 @@ class DanGameScreen(GameScreen):
# Draw frame and title # Draw frame and title
tex.draw_texture('dan_info', 'frame', frame=self.color) tex.draw_texture('dan_info', 'frame', frame=self.color)
if self.hori_name is not None: if self.hori_name is not None:
self.hori_name.draw(outline_color=ray.BLACK, x=154 - (self.hori_name.texture.width//2), self.hori_name.draw(outline_color=ray.BLACK, x=tex.skin_config["dan_game_hori_name"].x - (self.hori_name.texture.width//2),
y=392, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width) 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""" """Helper to draw digit counters"""
for j in range(len(counter)): for j in range(len(counter)):
kwargs = {'frame': int(counter[j]), 'x': -(len(counter) - j) * margin, 'y': y} 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.chara_2d import Chara2D
from libs.global_data import PlayerNum from libs.global_data import PlayerNum
from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, EntryOverlay, Timer 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.screen import Screen
from libs.utils import ( from libs.utils import (
OutlinedText, OutlinedText,
@@ -212,7 +212,7 @@ class EntryScreen(Screen):
tex.draw_texture('global', 'player_entry') tex.draw_texture('global', 'player_entry')
if self.box_manager.is_finished(): 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.timer.draw()
self.entry_overlay.draw(y=tex.skin_config['entry_overlay_entry'].y) 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 spacing = tex.skin_config["entry_box_spacing"].x
box_width = self.boxes[0].texture.width box_width = self.boxes[0].texture.width
total_width = self.num_boxes * box_width + (self.num_boxes - 1) * spacing 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): for i, box in enumerate(self.boxes):
box.set_positions(start_x + i * (box_width + spacing)) box.set_positions(start_x + i * (box_width + spacing))
if i > 0: 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_data import Crown, Difficulty, Modifiers, PlayerNum
from libs.global_objects import AllNetIcon, Nameplate from libs.global_objects import AllNetIcon, Nameplate
from libs.screen import Screen from libs.screen import Screen
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex from libs.texture import tex
from libs.tja import ( from libs.tja import (
Balloon, Balloon,
Drumroll, Drumroll,
@@ -57,7 +57,7 @@ class Judgments(IntEnum):
BAD = 2 BAD = 2
class GameScreen(Screen): class GameScreen(Screen):
JUDGE_X = 414 JUDGE_X = 414 * tex.screen_scale
def on_screen_start(self): def on_screen_start(self):
super().on_screen_start() super().on_screen_start()
self.mask_shader = ray.load_shader("shader/outline.vs", "shader/mask.fs") 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): def init_tja(self, song: Path):
"""Initialize the TJA file""" """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(): if self.tja.metadata.bgmovie != Path() and self.tja.metadata.bgmovie.exists():
self.movie = VideoPlayer(self.tja.metadata.bgmovie) self.movie = VideoPlayer(self.tja.metadata.bgmovie)
self.movie.set_volume(0.0) 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: 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""" """Calculates the x-coordinate of a note based on its load time and current time"""
time_diff = load_ms - current_ms 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: 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""" """Calculates the y-coordinate of a note based on its load time and current time"""
time_diff = load_ms - current_ms 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): def get_judge_position(self, current_ms: float):
"""Get the current judgment circle position based on bar data""" """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 # Find the most recent bar with judge position data
for bar in self.current_bars: for bar in self.current_bars:
if hasattr(bar, 'judge_pos_x') and bar.hit_ms <= current_ms: if hasattr(bar, 'judge_pos_x') and bar.hit_ms <= current_ms:
judge_x = bar.judge_pos_x judge_x = bar.judge_pos_x * tex.screen_scale
judge_y = bar.judge_pos_y judge_y = bar.judge_pos_y * tex.screen_scale
elif bar.hit_ms > current_ms: elif bar.hit_ms > current_ms:
break break
@@ -495,10 +495,10 @@ class Player:
return return
# More efficient removal with early exit # More efficient removal with early exit
removal_threshold = GameScreen.JUDGE_X + 650 removal_threshold = GameScreen.JUDGE_X + (650 * tex.screen_scale)
bars_to_keep = [] bars_to_keep = []
for bar in self.current_bars: 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: if position >= removal_threshold:
bars_to_keep.append(bar) bars_to_keep.append(bar)
self.current_bars = bars_to_keep self.current_bars = bars_to_keep
@@ -630,8 +630,8 @@ class Player:
note = self.current_notes_draw[0] 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: 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] note = self.current_notes_draw[1]
position = self.get_position_x(SCREEN_WIDTH, current_ms, note.hit_ms, note.pixels_per_frame_x) position = self.get_position_x(tex.screen_width, current_ms, note.hit_ms, note.pixels_per_frame_x)
if position < GameScreen.JUDGE_X + 650: if position < GameScreen.JUDGE_X + (650 * tex.screen_scale):
self.current_notes_draw.pop(0) self.current_notes_draw.pop(0)
def note_manager(self, current_ms: float, background: Optional[Background]): 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): def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int):
"""Draws a drumroll in the player's lane""" """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 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]) 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) 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 end_position += self.judge_x
length = end_position - start_position length = end_position - start_position
color = ray.Color(255, head.color, head.color, 255) color = ray.Color(255, head.color, head.color, 255)
y = tex.skin_config["notes"].y
moji_y = tex.skin_config["moji"].y
moji_x = tex.skin_config["moji"].x
if head.display: if head.display:
if length > 0: 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: 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: 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', "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=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=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_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 - (168//2)) + 64, y=323+(self.is_2p*176)+self.judge_y) 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 - (168//2)) + 32, y=323+(self.is_2p*176)+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): def draw_balloon(self, current_ms: float, head: Balloon, current_eighth: int):
"""Draws a balloon in the player's lane""" """Draws a balloon in the player's lane"""
offset = 12 offset = tex.skin_config["balloon_offset"].x
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 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]) 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 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: if current_ms >= tail.hit_ms:
position = end_position position = end_position
elif current_ms >= head.hit_ms: elif current_ms >= head.hit_ms:
@@ -1037,8 +1040,8 @@ class Player:
else: else:
position = start_position position = start_position
if head.display: 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', 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+128, y=192+(self.is_2p*176)+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): def draw_bars(self, current_ms: float):
"""Draw bars in the player's lane""" """Draw bars in the player's lane"""
@@ -1048,7 +1051,7 @@ class Player:
for bar in reversed(self.current_bars): for bar in reversed(self.current_bars):
if not bar.display: if not bar.display:
continue 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) 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 x_position += self.judge_x
y_position += self.judge_y 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)) angle = math.degrees(math.atan2(bar.pixels_per_frame_y, bar.pixels_per_frame_x))
else: else:
angle = 0 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): def draw_notes(self, current_ms: float, start_ms: float):
@@ -1090,10 +1093,10 @@ class Player:
else: else:
effective_ms = current_ms 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) y_position = self.get_position_y(effective_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
else: 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) 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 x_position += self.judge_x
y_position += self.judge_y y_position += self.judge_y
@@ -1101,13 +1104,13 @@ class Player:
self.draw_drumroll(current_ms, note, current_eighth) self.draw_drumroll(current_ms, note, current_eighth)
elif isinstance(note, Balloon) and not note.is_kusudama: elif isinstance(note, Balloon) and not note.is_kusudama:
self.draw_balloon(current_ms, note, current_eighth) self.draw_balloon(current_ms, note, current_eighth)
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position+(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: else:
if note.display: 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', 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 - (168//2) + 64, y=323 + y_position+(self.is_2p*176)) 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): def draw_modifiers(self):
@@ -1171,13 +1174,13 @@ class Player:
# Group 7: Player-specific elements # Group 7: Player-specific elements
if not self.modifiers.auto: if not self.modifiers.auto:
if self.is_2p: 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: else:
self.nameplate.draw(-62, 285) self.nameplate.draw(tex.skin_config["game_nameplate_2p"].x, tex.skin_config["game_nameplate_2p"].y)
else: else:
tex.draw_texture('lane', 'auto_icon', index=self.is_2p) tex.draw_texture('lane', 'auto_icon', index=self.is_2p)
self.draw_modifiers() 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 # Group 8: Special animations and counters
if self.drumroll_counter is not None: if self.drumroll_counter is not None:
@@ -1334,13 +1337,15 @@ class GaugeHitEffect:
self.color = ray.fade(ray.YELLOW, self.circle_fadein.attribute) self.color = ray.fade(ray.YELLOW, self.circle_fadein.attribute)
self.is_finished = False self.is_finished = False
self.width = tex.textures["gauge"]["hit_effect"].width
self.texture_color = ray.WHITE self.texture_color = ray.WHITE
self.dest_width = 152 self.dest_width = self.width * tex.screen_scale
self.dest_height = 152 self.dest_height = self.width * tex.screen_scale
self.origin = ray.Vector2(76, 76) # 152/2 self.origin = ray.Vector2(self.width//2, self.width//2)
self.rotation_angle = 0 self.rotation_angle = 0
self.x2_pos = -152 self.x2_pos = -self.width
self.y2_pos = -152 self.y2_pos = -self.width
# Cache for texture selection # Cache for texture selection
self.circle_texture = 'hit_effect_circle_big' if self.is_big else 'hit_effect_circle' 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: if abs(resize_val - getattr(self, '_last_resize_calc', -1)) > 0.005:
self._last_resize_calc = resize_val self._last_resize_calc = resize_val
self.texture_color = self._get_texture_color_for_resize(resize_val) self.texture_color = self._get_texture_color_for_resize(resize_val)
self.dest_width = 152 * resize_val self.dest_width = self.width * resize_val
self.dest_height = 152 * resize_val self.dest_height = self.width * resize_val
self.origin = ray.Vector2(self.dest_width / 2, self.dest_height / 2) self.origin = ray.Vector2(self.dest_width / 2, self.dest_height / 2)
self.x2_pos = -152 + (152 * resize_val) self.x2_pos = -self.width + (self.width * resize_val)
self.y2_pos = -152 + (152 * resize_val) self.y2_pos = -self.width + (self.width * resize_val)
self.rotation_angle = self.rotation.attribute * 100 self.rotation_angle = self.rotation.attribute * 100
@@ -1412,8 +1417,9 @@ class GaugeHitEffect:
center=True) center=True)
# Note type texture # Note type texture
pos_data = tex.skin_config["gauge_hit_effect_note"]
tex.draw_texture('notes', str(self.note_type), 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) fade=fade_value)
# Circle effect texture (use cached texture name) # Circle effect texture (use cached texture name)
@@ -1434,12 +1440,12 @@ class NoteArc:
self.explosion_point_index = 0 self.explosion_point_index = 0
self.points_per_explosion = 5 self.points_per_explosion = 5
curve_height = 425 curve_height = 425 * tex.screen_scale
self.start_x, self.start_y = start_x + 350, start_y + 192 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, 101 self.end_x, self.end_y = 1158 * tex.screen_scale, 101 * tex.screen_scale
if self.player_num == PlayerNum.P2: if self.player_num == PlayerNum.P2:
self.start_y += 176 self.start_y += (176 * tex.screen_scale)
self.end_y += 372 self.end_y += (372 * tex.screen_scale)
self.explosion_x = self.start_x self.explosion_x = self.start_x
self.explosion_y = self.start_y self.explosion_y = self.start_y
@@ -1511,12 +1517,12 @@ class NoteArc:
if crop_width > 0: if crop_width > 0:
src = ray.Rectangle(crop_start_x, 0, crop_width, rainbow_height) src = ray.Rectangle(crop_start_x, 0, crop_width, rainbow_height)
mirror = 'vertical' if self.player_num == PlayerNum.P2 else '' 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) 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) 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() 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: elif self.is_big:
tex.draw_texture('hit_effect', 'explosion', x=self.explosion_x, y=self.explosion_y-30, frame=self.explosion_anim.attribute) 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) color = ray.fade(ray.WHITE, self.fade_animation.attribute)
tex.draw_texture('drumroll_counter', 'bubble', color=color, index=self.is_2p) tex.draw_texture('drumroll_counter', 'bubble', color=color, index=self.is_2p)
counter = str(self.drumroll_count) 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): 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: class BalloonAnimation:
"""Draws a Balloon""" """Draws a Balloon"""
@@ -1594,16 +1600,16 @@ class BalloonAnimation:
def draw(self): def draw(self):
if self.is_popped: 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: elif self.balloon_count >= 1:
balloon_index = min(6, (self.balloon_count - 1) * 6 // self.balloon_total) 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: 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)) 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): 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: class KusudamaAnimation:
"""Draws a Kusudama""" """Draws a Kusudama"""
@@ -1667,9 +1673,9 @@ class KusudamaAnimation:
counter = str(max(0, self.balloon_total - self.balloon_count)) counter = str(max(0, self.balloon_total - self.balloon_count))
if counter == '0': if counter == '0':
return return
total_width = len(counter) * 150 total_width = len(counter) * tex.skin_config["kusudama_counter_margin"].x
for i, digit in enumerate(counter): 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: class Combo:
"""Displays the current combo""" """Displays the current combo"""
@@ -1725,21 +1731,21 @@ class Combo:
counter = self._cached_combo_str counter = self._cached_combo_str
if self.combo < 100: if self.combo < 100:
margin = 30 margin = tex.skin_config["combo_margin"].x
total_width = len(counter) * margin total_width = len(counter) * margin
tex.draw_texture('combo', 'combo', index=self.is_2p) tex.draw_texture('combo', 'combo', index=self.is_2p)
for i, digit in enumerate(counter): 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) 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: else:
margin = 35 margin = tex.skin_config["combo_margin"].y
total_width = len(counter) * margin total_width = len(counter) * margin
tex.draw_texture('combo', 'combo_100', index=self.is_2p) tex.draw_texture('combo', 'combo_100', index=self.is_2p)
for i, digit in enumerate(counter): 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) 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 j, (x, y) in enumerate(glimmer_positions):
for i in range(3): 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: class ScoreCounter:
"""Displays the total score""" """Displays the total score"""
@@ -1765,8 +1771,8 @@ class ScoreCounter:
self._cached_score_str = str(self.score) self._cached_score_str = str(self.score)
counter = self._cached_score_str counter = self._cached_score_str
x, y = 150, 185 + (self.is_2p*310) x, y = 150 * tex.screen_scale, (185 * tex.screen_scale) + (self.is_2p*310*tex.screen_scale)
margin = 20 margin = tex.skin_config["score_counter_margin"].x
total_width = len(counter) * margin total_width = len(counter) * margin
start_x = x - total_width start_x = x - total_width
for i, digit in enumerate(counter): for i, digit in enumerate(counter):
@@ -1800,7 +1806,7 @@ class ScoreCounterAnimation:
# Cache string and layout calculations # Cache string and layout calculations
self.counter_str = str(counter) 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.total_width = len(self.counter_str) * self.margin
self.y_pos_list = [] self.y_pos_list = []
@@ -1834,14 +1840,14 @@ class ScoreCounterAnimation:
elif self.move_animation_2.is_finished: elif self.move_animation_2.is_finished:
y = self.move_animation_3.attribute y = self.move_animation_3.attribute
else: else:
y = 148 y = 148 * tex.screen_scale
y_offset = y * self.direction y_offset = y * self.direction
tex.draw_texture('lane', 'score_number', tex.draw_texture('lane', 'score_number',
frame=int(digit), frame=int(digit),
x=start_x + (i * self.margin), 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) color=self.color)
class SongInfo: class SongInfo:
@@ -1849,7 +1855,7 @@ class SongInfo:
def __init__(self, song_name: str, genre: int): def __init__(self, song_name: str, genre: int):
self.song_name = song_name self.song_name = song_name
self.genre = genre 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) self.fade = tex.get_animation(3)
def update(self, current_ms: float): def update(self, current_ms: float):
@@ -1858,8 +1864,8 @@ class SongInfo:
def draw(self): def draw(self):
tex.draw_texture('song_info', 'song_num', fade=self.fade.attribute, frame=global_data.songs_played % 4) 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_x = tex.skin_config["song_info"].x - self.song_title.texture.width
text_y = 50 - self.song_title.texture.height//2 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)) 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: if self.genre < 9:
@@ -1884,19 +1890,19 @@ class ResultTransition:
def draw(self): def draw(self):
x = 0 x = 0
screen_width = 1280 while x < tex.screen_width:
while x < screen_width: tex_height = global_tex.textures['result_transition']['1p_shutter_footer'].height
if self.player_num == PlayerNum.TWO_PLAYER: 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', '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=720 - 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=-432 + 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=1008 - self.move.attribute) global_tex.draw_texture('result_transition', '2p_shutter_footer', x=x, y=tex.screen_height + tex_height - self.move.attribute)
else: 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=-tex.screen_height + 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', 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=-432 + 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=1008 - 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 += 256 x += tex.screen_width // 5
class GogoTime: class GogoTime:
"""Displays the Gogo Time fire and fireworks""" """Displays the Gogo Time fire and fireworks"""
@@ -1957,14 +1963,14 @@ class ComboAnnounce:
thousands_offset = -110 thousands_offset = -110
hundreds_offset = 20 hundreds_offset = 20
if self.combo % 1000 == 0: 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_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, 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: else:
if thousands <= 5: 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: if remaining_hundreds > 0:
tex.draw_texture('combo', 'announce_number', frame=remaining_hundreds-1, x=hundreds_offset, fade=fade, index=self.is_2p) 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: else:
text_offset = 0 text_offset = 0
tex.draw_texture('combo', 'announce_number', frame=self.combo // 100 - 1, x=0, fade=fade, index=self.is_2p) 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: 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', '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.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: class FailAnimation:
"""Animates the fail effect""" """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', '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_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_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=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*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*tex.skin_config["2p_offset"].y))
class ClearAnimation: class ClearAnimation:
"""Animates the clear effect""" """Animates the clear effect"""
@@ -2112,7 +2118,7 @@ class ClearAnimation:
tex.draw_texture('ending_anim', 'clear', index=self.is_2p) tex.draw_texture('ending_anim', 'clear', index=self.is_2p)
else: else:
for i in range(4, -1, -1): 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', '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_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) 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) tex.draw_texture('ending_anim', 'fan_r', frame=self.fan_texture_change.attribute, fade=self.fan_fade_in.attribute, index=self.is_2p)
else: else:
for i in range(4, -1, -1): 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', '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_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) 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.ok = ok
self.bad = bad self.bad = bad
self.drumrolls = drumrolls 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_str = str(rounded(counter))
counter_len = len(counter_str) counter_len = len(counter_str)
for i, digit in enumerate(counter_str): for i, digit in enumerate(counter_str):
@@ -2224,14 +2230,15 @@ class JudgeCounter:
total_notes = self.good + self.ok + self.bad total_notes = self.good + self.ok + self.bad
if total_notes == 0: if total_notes == 0:
total_notes = 1 total_notes = 1
self.draw_counter(self.good / total_notes * 100, 260, 440, 23, self.orange) margin = tex.skin_config["judge_counter_margin"].x
self.draw_counter(self.ok / total_notes * 100, 260, 477, 23, self.orange) 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.bad / total_notes * 100, 260, 515, 23, 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.good + self.ok) / total_notes * 100, 270, 388, 23, 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, 180, 440, 23, self.white) 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.ok, 180, 477, 23, self.white) 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.bad, 180, 515, 23, 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.drumrolls, 180, 577, 23, 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: class Gauge:
"""The player's 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) 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) gauge_length = int(self.gauge_length)
clear_point = self.clear_start[self.difficulty] 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: 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: 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_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) * 8, x2=(gauge_length-clear_point)*8, index=self.is_2p) 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 # Rainbow effect for full gauge
if gauge_length == self.gauge_max and self.rainbow_fade_in is not None: 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) 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 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]: 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]: 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: 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) tex.draw_texture('gauge', 'overlay' + self.string_diff, fade=0.15, index=self.is_2p, mirror=mirror)
# Draw clear status indicators # Draw clear status indicators

View File

@@ -7,7 +7,7 @@ from libs.animation import Animation
from libs.global_objects import AllNetIcon from libs.global_objects import AllNetIcon
from libs.screen import Screen from libs.screen import Screen
from libs.song_hash import build_song_hashes 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.utils import get_current_ms, global_data
from libs.file_navigator import navigator from libs.file_navigator import navigator
@@ -17,8 +17,8 @@ logger = logging.getLogger(__name__)
class LoadScreen(Screen): class LoadScreen(Screen):
def __init__(self, name: str): def __init__(self, name: str):
super().__init__(name) super().__init__(name)
self.width = SCREEN_WIDTH self.width = tex.screen_width
self.height = SCREEN_HEIGHT self.height = tex.screen_height
self.songs_loaded = False self.songs_loaded = False
self.navigator_started = False self.navigator_started = False
self.loading_complete = 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.tja import Balloon, Drumroll, Note, NoteType, TJAParser, apply_modifiers
from libs.utils import get_current_ms from libs.utils import get_current_ms
from libs.texture import tex 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__) logger = logging.getLogger(__name__)
@@ -23,8 +23,8 @@ class PracticeGameScreen(GameScreen):
def init_tja(self, song: Path): def init_tja(self, song: Path):
"""Initialize the TJA file""" """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)
self.scrobbling_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=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']) 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: 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.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 time_diff = load_ms - self.scrobble_time - self.scrobble_move.attribute
else: else:
time_diff = load_ms - current_ms 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: 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""" """Calculates the y-coordinate of a note based on its load time and current time"""
time_diff = load_ms - current_ms 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): def draw_drumroll(self, current_ms: float, head: Drumroll, current_eighth: int, index: int):
"""Draws a drumroll in the player's lane""" """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]) 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) 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 length = end_position - start_position
color = ray.Color(255, head.color, head.color, 255) 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 head.display:
if length > 0: 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: 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: else:
tex.draw_texture('notes', "drumroll_tail", x=end_position+64, 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=192, 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_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 - (168//2)) + 64, y=323) 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 - (168//2)) + 32, y=323) 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): def draw_balloon(self, current_ms: float, head: Balloon, current_eighth: int, index: int):
"""Draws a balloon in the player's lane""" """Draws a balloon in the player's lane"""
offset = 12 offset = tex.skin_config["balloon_offset"].x
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]) 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) end_position = self.get_position_x(tex.screen_width, current_ms, tail.load_ms, tail.pixels_per_frame_x)
pause_position = 349 pause_position = tex.skin_config["balloon_pause_position"].x
if current_ms >= tail.hit_ms: if current_ms >= tail.hit_ms:
position = end_position position = end_position
elif current_ms >= head.hit_ms: elif current_ms >= head.hit_ms:
@@ -197,23 +200,23 @@ class PracticeGameScreen(GameScreen):
else: else:
position = start_position position = start_position
if head.display: if head.display:
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=position-offset, 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+128, y=192) 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): def draw_scrobble_list(self):
bar_draws = [] bar_draws = []
for bar in reversed(self.bars): for bar in reversed(self.bars):
if not bar.display: if not bar.display:
continue 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) 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 continue
if hasattr(bar, 'is_branch_start'): if hasattr(bar, 'is_branch_start'):
frame = 1 frame = 1
else: else:
frame = 0 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: for bar_type, frame, x, y in bar_draws:
tex.draw_texture('notes', bar_type, frame=frame, x=x, y=y) tex.draw_texture('notes', bar_type, frame=frame, x=x, y=y)
@@ -225,27 +228,27 @@ class PracticeGameScreen(GameScreen):
if isinstance(note, Drumroll): if isinstance(note, Drumroll):
self.draw_drumroll(self.current_ms, note, 0, note.index) self.draw_drumroll(self.current_ms, note, 0, note.index)
elif isinstance(note, Balloon) and not note.is_kusudama: 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) 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 continue
self.draw_balloon(self.current_ms, note, 0, note.index) 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: 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) 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 continue
if note.display: 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 color = ray.WHITE
if note.index in self.player_1.input_log: if note.index in self.player_1.input_log:
if self.player_1.input_log[note.index] == 'GOOD': if self.player_1.input_log[note.index] == 'GOOD':
color = ray.Color(255, 233, 0, 255) color = ray.Color(255, 233, 0, 255)
elif self.player_1.input_log[note.index] == 'BAD': elif self.player_1.input_log[note.index] == 'BAD':
color = ray.Color(34, 189, 243, 255) 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): def draw(self):
self.background.draw() 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) progress = min((self.scrobble_time + self.scrobble_move.attribute - self.bars[0].hit_ms) / self.player_1.end_time, 1)
else: else:
progress = min(self.current_ms / self.player_1.end_time, 1) 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: 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() self.draw_overlay()
@@ -276,9 +279,9 @@ class PracticePlayer(Player):
self.gauge = None self.gauge = None
self.paused = False self.paused = False
def spawn_hit_effects(self, note_type: DrumType, side: Side): def spawn_hit_effects(self, drum_type: DrumType, side: Side):
self.lane_hit_effect = LaneHitEffect(note_type, self.is_2p) self.lane_hit_effect = LaneHitEffect(drum_type, self.is_2p)
self.draw_drum_hit_list.append(PracticeDrumHitEffect(note_type, side, self.is_2p, player_num=self.player_num)) 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): def draw_overlays(self, mask_shader: ray.Shader):
# Group 4: Lane covers and UI elements (batch similar textures) # Group 4: Lane covers and UI elements (batch similar textures)
@@ -306,13 +309,13 @@ class PracticePlayer(Player):
# Group 7: Player-specific elements # Group 7: Player-specific elements
if not self.modifiers.auto: if not self.modifiers.auto:
if self.is_2p: 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: else:
self.nameplate.draw(-62, 285) self.nameplate.draw(tex.skin_config["game_nameplate_2p"].x, tex.skin_config["game_nameplate_2p"].y)
else: else:
tex.draw_texture('lane', 'auto_icon', index=self.is_2p) tex.draw_texture('lane', 'auto_icon', index=self.is_2p)
self.draw_modifiers() 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 # Group 8: Special animations and counters
if self.drumroll_counter is not None: if self.drumroll_counter is not None:
@@ -321,7 +324,6 @@ class PracticePlayer(Player):
self.balloon_anim.draw() self.balloon_anim.draw()
if self.kusudama_anim is not None: if self.kusudama_anim is not None:
self.kusudama_anim.draw() 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): def draw(self, ms_from_start: float, start_ms: float, mask_shader: ray.Shader, dan_transition = None):
# Group 1: Background and lane elements # Group 1: Background and lane elements

View File

@@ -26,7 +26,7 @@ class State:
class ResultScreen(Screen): class ResultScreen(Screen):
def on_screen_start(self): def on_screen_start(self):
super().on_screen_start() 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') audio.play_sound('bgm', 'music')
self.fade_in = FadeIn(global_data.player_num) self.fade_in = FadeIn(global_data.player_num)
self.fade_out = tex.get_animation(0) self.fade_out = tex.get_animation(0)
@@ -34,7 +34,7 @@ class ResultScreen(Screen):
self.allnet_indicator = AllNetIcon() self.allnet_indicator = AllNetIcon()
self.start_ms = get_current_ms() self.start_ms = get_current_ms()
self.is_skipped = False 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) self.player_1 = ResultPlayer(global_data.player_num, False, False)
def on_screen_end(self, next_screen: str): def on_screen_end(self, next_screen: str):
@@ -66,13 +66,13 @@ class ResultScreen(Screen):
def draw_overlay(self): def draw_overlay(self):
self.fade_in.draw() 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.coin_overlay.draw()
self.allnet_indicator.draw() self.allnet_indicator.draw()
def draw_song_info(self): def draw_song_info(self):
tex.draw_texture('song_info', 'song_num', frame=global_data.songs_played%4) 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): def draw(self):
self.background.draw() self.background.draw()
@@ -82,25 +82,26 @@ class ResultScreen(Screen):
class Background: class Background:
def __init__(self, player_num: PlayerNum, width: int): def __init__(self, player_num: PlayerNum, width: float):
self.player_num = player_num self.player_num = player_num
self.width = width self.width = width
def draw(self): def draw(self):
x = 0 x = 0
footer_height = tex.textures["background"]["footer_1p"].height
if self.player_num == PlayerNum.TWO_PLAYER: if self.player_num == PlayerNum.TWO_PLAYER:
while x < self.width: while x < self.width:
tex.draw_texture('background', 'background_1p', x=x, y=-360) tex.draw_texture('background', 'background_1p', x=x, y=-(tex.screen_height//2))
tex.draw_texture('background', 'background_2p', x=x, y=360) tex.draw_texture('background', 'background_2p', x=x, y=tex.screen_height//2)
tex.draw_texture('background', 'footer_1p', x=x, y=-72) tex.draw_texture('background', 'footer_1p', x=x, y=-footer_height)
tex.draw_texture('background', 'footer_2p', x=x, y=648) tex.draw_texture('background', 'footer_2p', x=x, y=tex.screen_height-footer_height)
x += 256 x += tex.screen_width // 5
else: else:
while x < self.width: 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=-(tex.screen_height//2))
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=(tex.screen_height//2))
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=-footer_height)
tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=648) tex.draw_texture('background', f'footer_{self.player_num}p', x=x, y=tex.screen_height-footer_height)
x += 256 x += tex.screen_width // 5
tex.draw_texture('background', 'result_text') tex.draw_texture('background', 'result_text')
class ResultPlayer: class ResultPlayer:
@@ -116,7 +117,7 @@ class ResultPlayer:
self.crown = None self.crown = None
self.state = None self.state = None
self.high_score_indicator = 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] session_data = global_data.session_data[self.player_num]
self.score_animator = ScoreAnimator(session_data.result_data.score) self.score_animator = ScoreAnimator(session_data.result_data.score)
plate_info = global_data.config[f'nameplate_{self.player_num}p'] plate_info = global_data.config[f'nameplate_{self.player_num}p']
@@ -206,7 +207,7 @@ class ResultPlayer:
continue continue
score_str = str(score)[::-1] score_str = str(score)[::-1]
for i, digit in enumerate(score_str): 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): def draw_total_score(self):
""" """
@@ -217,7 +218,7 @@ class ResultPlayer:
tex.draw_texture('score', 'score_shinuchi', index=self.is_2p) tex.draw_texture('score', 'score_shinuchi', index=self.is_2p)
if self.score != '': if self.score != '':
for i in range(len(str(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): def draw_modifiers(self):
"""Draw the modifiers if enabled.""" """Draw the modifiers if enabled."""
@@ -243,7 +244,7 @@ class ResultPlayer:
elif self.state == State.CLEAR: elif self.state == State.CLEAR:
tex.draw_texture('background', 'gradient_clear', fade=min(0.4, self.fade_in_bottom.attribute)) tex.draw_texture('background', 'gradient_clear', fade=min(0.4, self.fade_in_bottom.attribute))
else: 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: if self.state == State.FAIL:
tex.draw_texture('background', 'gradient_fail', fade=min(0.4, self.fade_in_bottom.attribute), y=y) tex.draw_texture('background', 'gradient_fail', fade=min(0.4, self.fade_in_bottom.attribute), y=y)
elif self.state == State.CLEAR: elif self.state == State.CLEAR:
@@ -270,10 +271,10 @@ class ResultPlayer:
if self.high_score_indicator is not None: if self.high_score_indicator is not None:
self.high_score_indicator.draw() 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: if self.gauge is not None:
self.gauge.draw() 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: class Crown:
"""Represents a crown animation""" """Represents a crown animation"""
@@ -375,7 +376,7 @@ class BottomCharacters:
def draw_flowers(self): 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)
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): def draw(self):
self.draw_flowers() self.draw_flowers()
@@ -402,20 +403,21 @@ class FadeIn:
def draw(self): def draw(self):
x = 0 x = 0
footer_height = tex.textures["background"]["footer_1p"].height
if self.player_num == PlayerNum.TWO_PLAYER: if self.player_num == PlayerNum.TWO_PLAYER:
while x < 1280: while x < tex.screen_width:
tex.draw_texture('background', 'background_1p', x=x, y=-360, fade=self.fadein.attribute) 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=360, 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=-72, 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=648, fade=self.fadein.attribute) tex.draw_texture('background', 'footer_2p', x=x, y=tex.screen_height - footer_height, fade=self.fadein.attribute)
x += 256 x += tex.screen_width // 5
else: else:
while x < 1280: while x < tex.screen_width:
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=-tex.screen_height//2, 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'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=-72, 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=648, 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 += 256 x += tex.screen_width // 5
class ScoreAnimator: class ScoreAnimator:
"""Animates a number from left to right""" """Animates a number from left to right"""
@@ -461,7 +463,7 @@ class HighScoreIndicator:
def draw(self): def draw(self):
tex.draw_texture('score', 'high_score', y=self.move.attribute, fade=self.fade.attribute, index=self.is_2p) 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))): 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: class Gauge:
@@ -504,16 +506,17 @@ class Gauge:
scale = 10/11 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) 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) 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 gauge_length == self.gauge_max:
if 0 < self.rainbow_animation.attribute < 8: 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-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) 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: 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: 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_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]*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_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]*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]*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', '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) 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_l_kat_pressed,
is_r_don_pressed, is_r_don_pressed,
is_r_kat_pressed, is_r_kat_pressed,
save_config,
) )
from libs.config import save_config
logger = logging.getLogger(__name__) 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_data import Difficulty, Modifiers, PlayerNum
from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, Timer from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate, Indicator, Timer
from libs.screen import Screen from libs.screen import Screen
from libs.texture import SCREEN_WIDTH, tex from libs.texture import tex
from libs.transition import Transition from libs.transition import Transition
from libs.utils import ( from libs.utils import (
OutlinedText, OutlinedText,
@@ -329,15 +329,15 @@ class SongSelectScreen(Screen):
self.draw_background_diffs() self.draw_background_diffs()
if self.navigator.genre_bg is not None and self.state == State.BROWSING: 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): for i, item in enumerate(self.navigator.items):
box = item.box box = item.box
if -156 <= box.position <= SCREEN_WIDTH + 144: if (-156 * tex.screen_scale) <= box.position <= (tex.screen_width + 144) * tex.screen_scale:
if box.position <= 500: if box.position <= (500 * tex.screen_scale):
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)
else: 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: 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) 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): if isinstance(curr_item, SongFile):
curr_item.box.draw_score_history() 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_bg', fade=0.75)
tex.draw_texture('global', 'song_num', frame=global_data.songs_played % 4) 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) self.selected_diff_text_fadein = tex.get_animation(37, is_copy=True)
# Player-specific objects # 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'] plate_info = global_data.config[f'nameplate_{self.player_num}p']
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], 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']) 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): def on_song_selected(self, selected_song):
"""Called when a song is selected""" """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 self.is_ura = False
elif (4 in selected_song.tja.metadata.course_data and elif (Difficulty.URA in selected_song.tja.metadata.course_data and
3 not in selected_song.tja.metadata.course_data): Difficulty.ONI not in selected_song.tja.metadata.course_data):
self.is_ura = True self.is_ura = True
def handle_input_browsing(self, last_moved, selected_item): def handle_input_browsing(self, last_moved, selected_item):
@@ -644,46 +644,47 @@ class SongSelectPlayer:
def draw_selector(self, is_half: bool): 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 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 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.selected_difficulty <= -1 or self.prev_diff == -1:
if self.prev_diff == -1 and self.selected_difficulty >= 0: if self.prev_diff == -1 and self.selected_difficulty >= 0:
if not self.diff_selector_move_2.is_finished: 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' 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' 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: else:
difficulty = min(Difficulty.ONI, self.selected_difficulty) 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' 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' 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: 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' 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: if self.selected_difficulty != -3:
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon' 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: else:
name = f'{self.player_num}p_outline_back_half' if is_half else f'{self.player_num}p_outline_back' 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: if self.selected_difficulty != -3:
name = f'{self.player_num}p_balloon_half' if is_half else f'{self.player_num}p_balloon' 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: else:
if self.prev_diff == -1: if self.prev_diff == -1:
return return
if not self.diff_selector_move_1.is_finished: if not self.diff_selector_move_1.is_finished:
difficulty = min(Difficulty.ONI, self.prev_diff) 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' 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' 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: else:
difficulty = min(Difficulty.ONI, self.selected_difficulty) 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' 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' 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): def draw_background_diffs(self, state: int):
if (self.selected_song and state == State.SONG_SELECTED and self.selected_difficulty >= Difficulty.EASY): 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: if self.neiro_selector is not None:
offset = self.neiro_selector.move.attribute offset = self.neiro_selector.move.attribute
if self.neiro_selector.is_confirmed: if self.neiro_selector.is_confirmed:
offset += -370 offset += tex.skin_config["song_select_offset"].x
else: else:
offset *= -1 offset *= -1
if self.modifier_selector is not None: if self.modifier_selector is not None:
offset = self.modifier_selector.move.attribute offset = self.modifier_selector.move.attribute
if self.modifier_selector.is_confirmed: if self.modifier_selector.is_confirmed:
offset += -370 offset += tex.skin_config["song_select_offset"].x
else: else:
offset *= -1 offset *= -1
if self.player_num == PlayerNum.P1: if self.player_num == PlayerNum.P1:
self.nameplate.draw(30, 640) self.nameplate.draw(tex.skin_config["song_select_nameplate_1p"].x, tex.skin_config["song_select_nameplate_1p"].y)
self.chara.draw(x=-50, y=410 + (offset*0.6)) 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: else:
self.nameplate.draw(950, 640) 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=950, y=410 + (offset*0.6)) 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: if self.neiro_selector is not None:
self.neiro_selector.draw() self.neiro_selector.draw()

View File

@@ -8,7 +8,8 @@ from libs.audio import audio
from libs.utils import global_data from libs.utils import global_data
from libs.video import VideoPlayer from libs.video import VideoPlayer
import pyray as ray 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__) logger = logging.getLogger(__name__)
@@ -74,7 +75,7 @@ class TwoPlayerGameScreen(GameScreen):
def init_tja(self, song: Path): def init_tja(self, song: Path):
"""Initialize the TJA file""" """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(): if self.tja.metadata.bgmovie != Path() and self.tja.metadata.bgmovie.exists():
self.movie = VideoPlayer(self.tja.metadata.bgmovie) self.movie = VideoPlayer(self.tja.metadata.bgmovie)
self.movie.set_volume(0.0) self.movie.set_volume(0.0)

View File

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