this update doubles the fps

This commit is contained in:
Anthony Samms
2025-11-17 20:10:36 -05:00
parent ca72a23310
commit 7066dc385b
9 changed files with 154 additions and 125 deletions

View File

@@ -20,7 +20,6 @@ from libs.tja import TJAParser
from libs.utils import (
force_dedicated_gpu,
get_config,
get_key_code,
global_data,
global_tex
)
@@ -208,16 +207,17 @@ def main():
ray.gen_texture_mipmaps(target.texture)
ray.set_texture_filter(target.texture, ray.TextureFilter.TEXTURE_FILTER_TRILINEAR)
ray.rl_set_blend_factors_separate(RL_SRC_ALPHA, RL_ONE_MINUS_SRC_ALPHA, RL_ONE, RL_ONE_MINUS_SRC_ALPHA, RL_FUNC_ADD, RL_FUNC_ADD)
ray.set_exit_key(get_key_code(global_data.config["keys"]["exit_key"]))
ray.set_exit_key(global_data.config["keys"]["exit_key"])
ray.hide_cursor()
logger.info("Cursor hidden")
last_fps = 1
while not ray.window_should_close():
if ray.is_key_pressed(get_key_code(global_data.config["keys"]["fullscreen_key"])):
if ray.is_key_pressed(global_data.config["keys"]["fullscreen_key"]):
ray.toggle_fullscreen()
logger.info("Toggled fullscreen")
elif ray.is_key_pressed(get_key_code(global_data.config["keys"]["borderless_key"])):
elif ray.is_key_pressed(global_data.config["keys"]["borderless_key"]):
ray.toggle_borderless_windowed()
logger.info("Toggled borderless windowed mode")
@@ -248,7 +248,15 @@ def main():
global_data.input_locked = 0
if global_data.config["general"]["fps_counter"]:
ray.draw_fps(20, 20)
curr_fps = ray.get_fps()
if curr_fps != 0 and curr_fps != last_fps:
last_fps = curr_fps
if last_fps < 30:
ray.draw_text(f'{last_fps} FPS', 20, 20, 20, ray.RED)
elif last_fps < 60:
ray.draw_text(f'{last_fps} FPS', 20, 20, 20, ray.YELLOW)
else:
ray.draw_text(f'{last_fps} FPS', 20, 20, 20, ray.LIME)
ray.end_blend_mode()
ray.end_texture_mode()
ray.begin_drawing()

View File

@@ -1346,8 +1346,7 @@ class FileNavigator:
"""Get crowns for a directory, calculating only if needed"""
if dir_key in self.crown_cache_dirty or dir_key not in self.directory_crowns:
# Calculate crowns on-demand
dir_path = Path(dir_key)
tja_files = self._get_tja_files_for_directory(dir_path)
tja_files = self.directory_contents[dir_key]
self._calculate_directory_crowns(dir_key, tja_files)
self.crown_cache_dirty.discard(dir_key)

View File

@@ -5,9 +5,10 @@ import logging
import tempfile
import zipfile
from pathlib import Path
from typing import Optional, Union
from typing import Any, Optional
import pyray as ray
import raylib as ray
from pyray import Vector2, Rectangle, Color
from libs.animation import BaseAnimation, parse_animations
@@ -23,7 +24,7 @@ class Coordinates:
class Texture:
"""Texture class for managing textures and animations."""
def __init__(self, name: str, texture: Union[ray.Texture, list[ray.Texture]], init_vals: dict[str, int]):
def __init__(self, name: str, texture: Any, init_vals: dict[str, int]):
self.name = name
self.texture = texture
self.init_vals = init_vals
@@ -66,13 +67,13 @@ class TextureWrapper:
logger.warning(f"Duplicate texture ID {texture.id}: {ids[texture.id]} and {zip}/{file}[{i}]")
else:
ids[texture.id] = f"{zip}/{file}[{i}]"
ray.unload_texture(texture)
ray.UnloadTexture(texture)
else:
if tex_object.texture.id in ids:
logger.warning(f"Duplicate texture ID {tex_object.texture.id}: {ids[tex_object.texture.id]} and {zip}/{file}")
else:
ids[tex_object.texture.id] = f"{zip}/{file}"
ray.unload_texture(tex_object.texture)
ray.UnloadTexture(tex_object.texture)
self.textures.clear()
self.animations.clear()
@@ -147,10 +148,10 @@ class TextureWrapper:
extracted_path = Path(temp_dir) / tex_name
if extracted_path.is_dir():
frames = [ray.load_texture(str(frame)) for frame in sorted(extracted_path.iterdir(),
frames = [ray.LoadTexture(str(frame).encode('utf-8')) for frame in sorted(extracted_path.iterdir(),
key=lambda x: int(x.stem)) if frame.is_file()]
else:
frames = [ray.load_texture(str(extracted_path))]
frames = [ray.LoadTexture(str(extracted_path).encode('utf-8'))]
self.textures[zip.stem][tex_name] = Texture(tex_name, frames, tex_mapping)
self._read_tex_obj_data(tex_mapping, self.textures[zip.stem][tex_name])
elif f"{tex_name}.png" in zip_ref.namelist():
@@ -162,7 +163,7 @@ class TextureWrapper:
temp_path = temp_file.name
try:
tex = ray.load_texture(temp_path)
tex = ray.LoadTexture(temp_path.encode('utf-8'))
self.textures[zip.stem][tex_name] = Texture(tex_name, tex, tex_mapping)
self._read_tex_obj_data(tex_mapping, self.textures[zip.stem][tex_name])
finally:
@@ -192,25 +193,58 @@ class TextureWrapper:
def control(self, tex_object: Texture, index: int = 0):
'''debug function'''
distance = 1
if ray.is_key_down(ray.KeyboardKey.KEY_LEFT_SHIFT):
if ray.IsKeyDown(ray.KEY_LEFT_SHIFT):
distance = 10
if ray.is_key_pressed(ray.KeyboardKey.KEY_LEFT):
if ray.IsKeyPressed(ray.KEY_LEFT):
tex_object.x[index] -= distance
logger.info(f"{tex_object.name}: {tex_object.x[index]}, {tex_object.y[index]}")
if ray.is_key_pressed(ray.KeyboardKey.KEY_RIGHT):
if ray.IsKeyPressed(ray.KEY_RIGHT):
tex_object.x[index] += distance
logger.info(f"{tex_object.name}: {tex_object.x[index]}, {tex_object.y[index]}")
if ray.is_key_pressed(ray.KeyboardKey.KEY_UP):
if ray.IsKeyPressed(ray.KEY_UP):
tex_object.y[index] -= distance
logger.info(f"{tex_object.name}: {tex_object.x[index]}, {tex_object.y[index]}")
if ray.is_key_pressed(ray.KeyboardKey.KEY_DOWN):
if ray.IsKeyPressed(ray.KEY_DOWN):
tex_object.y[index] += distance
logger.info(f"{tex_object.name}: {tex_object.x[index]}, {tex_object.y[index]}")
def draw_texture(self, subset: str, texture: str, color: ray.Color=ray.WHITE, frame: int = 0, scale: float = 1.0, center: bool = False,
def _draw_texture_untyped(self, subset: str, texture: str, color: tuple[int, int, int, int], frame: int, scale: float, center: bool,
mirror: str, x: float, y: float, x2: float, y2: float,
origin: tuple[float, float], rotation: float, fade: float,
index: int, src: Optional[tuple[float, float, float, float]], controllable: bool) -> None:
mirror_x = -1 if mirror == 'horizontal' else 1
mirror_y = -1 if mirror == 'vertical' else 1
if fade != 1.1:
final_color = ray.Fade(color, fade)
else:
final_color = color
tex_object = self.textures[subset][texture]
if src is not None:
source_rect = src
else:
source_rect = (0, 0, tex_object.width * mirror_x, tex_object.height * mirror_y)
if center:
dest_rect = (tex_object.x[index] + (tex_object.width//2) - ((tex_object.width * scale)//2) + x, tex_object.y[index] + (tex_object.height//2) - ((tex_object.height * scale)//2) + y, tex_object.x2[index]*scale + x2, tex_object.y2[index]*scale + y2)
else:
dest_rect = (tex_object.x[index] + x, tex_object.y[index] + y, tex_object.x2[index]*scale + x2, tex_object.y2[index]*scale + y2)
if tex_object.is_frames:
if not isinstance(tex_object.texture, list):
raise Exception("Texture was marked as multiframe but is only 1 texture")
if frame >= len(tex_object.texture):
raise Exception(f"Frame {frame} not available in iterable texture {tex_object.name}")
ray.DrawTexturePro(tex_object.texture[frame], source_rect, dest_rect, origin, rotation, final_color)
else:
if isinstance(tex_object.texture, list):
raise Exception("Texture is multiframe but was called as 1 texture")
ray.DrawTexturePro(tex_object.texture, source_rect, dest_rect, origin, rotation, final_color)
if tex_object.controllable[index] or controllable:
self.control(tex_object)
def draw_texture(self, subset: str, texture: str, color: Color = Color(255, 255, 255, 255), frame: int = 0, scale: float = 1.0, center: bool = False,
mirror: str = '', x: float = 0, y: float = 0, x2: float = 0, y2: float = 0,
origin: ray.Vector2 = ray.Vector2(0,0), rotation: float = 0, fade: float = 1.1,
index: int = 0, src: Optional[ray.Rectangle] = None, controllable: bool = False) -> None:
origin: Vector2 = Vector2(0,0), rotation: float = 0, fade: float = 1.1,
index: int = 0, src: Optional[Rectangle] = None, controllable: bool = False) -> None:
"""
Wrapper function for raylib's draw_texture_pro().
Parameters:
@@ -232,33 +266,14 @@ class TextureWrapper:
src (Optional[ray.Rectangle]): The source rectangle of the texture.
controllable (bool): Whether the texture is controllable.
"""
mirror_x = -1 if mirror == 'horizontal' else 1
mirror_y = -1 if mirror == 'vertical' else 1
if fade != 1.1:
final_color = ray.fade(color, fade)
else:
final_color = color
tex_object = self.textures[subset][texture]
if src is not None:
source_rect = src
src_data = (src.x, src.y, src.width, src.height)
else:
source_rect = ray.Rectangle(0, 0, tex_object.width * mirror_x, tex_object.height * mirror_y)
if center:
dest_rect = ray.Rectangle(tex_object.x[index] + (tex_object.width//2) - ((tex_object.width * scale)//2) + x, tex_object.y[index] + (tex_object.height//2) - ((tex_object.height * scale)//2) + y, tex_object.x2[index]*scale + x2, tex_object.y2[index]*scale + y2)
src_data = None
if isinstance(color, tuple):
color_data = (color[0], color[1], color[2], color[3])
else:
dest_rect = ray.Rectangle(tex_object.x[index] + x, tex_object.y[index] + y, tex_object.x2[index]*scale + x2, tex_object.y2[index]*scale + y2)
if tex_object.is_frames:
if not isinstance(tex_object.texture, list):
raise Exception("Texture was marked as multiframe but is only 1 texture")
if frame >= len(tex_object.texture):
raise Exception(f"Frame {frame} not available in iterable texture {tex_object.name}")
ray.draw_texture_pro(tex_object.texture[frame], source_rect, dest_rect, origin, rotation, final_color)
else:
if isinstance(tex_object.texture, list):
raise Exception("Texture is multiframe but was called as 1 texture")
ray.draw_texture_pro(tex_object.texture, source_rect, dest_rect, origin, rotation, final_color)
if tex_object.controllable[index] or controllable:
self.control(tex_object)
color_data = (color.r, color.g, color.b, color.a)
self._draw_texture_untyped(subset, texture, color_data, frame, scale, center, mirror, x, y, x2, y2, (origin.x, origin.y), rotation, fade, index, src_data, controllable)
tex = TextureWrapper()

View File

@@ -10,6 +10,7 @@ from pathlib import Path
from typing import Optional
import pyray as ray
import raylib as rl
import tomlkit
from raylib import (
SHADER_UNIFORM_FLOAT,
@@ -83,7 +84,7 @@ def get_config() -> Config:
config: Config = json.loads(json.dumps(config_file))
for key in config['keys']:
config[key] = get_key_code(config['keys'][key])
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):
@@ -116,12 +117,12 @@ def is_input_key_pressed(keys: list[int], gamepad_buttons: list[int]):
if global_data.input_locked:
return False
for key in keys:
if ray.is_key_pressed(key):
if rl.IsKeyPressed(key):
return True
if ray.is_gamepad_available(0):
if rl.IsGamepadAvailable(0):
for button in gamepad_buttons:
if ray.is_gamepad_button_pressed(0, button):
if rl.IsGamepadButtonPressed(0, button):
return True
return False

View File

@@ -1,7 +1,7 @@
from pathlib import Path
import logging
import pyray as ray
import raylib as ray
from moviepy import VideoFileClip
from libs.audio import audio
@@ -52,13 +52,24 @@ class VideoPlayer:
frame_data = self.video.get_frame(time_sec)
if self.texture is None:
image = ray.Image(frame_data, self.video.w, self.video.h, 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
self.texture = ray.load_texture_from_image(image)
if frame_data is None:
return False
frame_bytes = frame_data.tobytes()
pixels_ptr = ray.ffi.cast('void *', ray.ffi.from_buffer('unsigned char[]', frame_bytes))
image = ray.ffi.new('Image *', {
'data': pixels_ptr,
'width': self.video.w,
'height': self.video.h,
'mipmaps': 1,
'format': ray.PIXELFORMAT_UNCOMPRESSED_R8G8B8
})
self.texture = ray.LoadTextureFromImage(image[0])
else:
if frame_data is not None:
frame_bytes = frame_data.tobytes()
pixels_ptr = ray.ffi.cast('void *', ray.ffi.from_buffer('unsigned char[]', frame_bytes))
ray.update_texture(self.texture, pixels_ptr)
ray.UpdateTexture(self.texture, pixels_ptr)
self.current_frame_data = frame_data
return True
@@ -108,14 +119,14 @@ class VideoPlayer:
def draw(self):
"""Draw video frames to the raylib canvas"""
if self.texture is not None:
ray.draw_texture(self.texture, 0, 0, ray.WHITE)
ray.DrawTexture(self.texture, 0, 0, ray.WHITE)
def stop(self):
"""Stops the video, audio, and clears its buffer"""
self.video.close()
if self.texture is not None:
ray.unload_texture(self.texture)
ray.UnloadTexture(self.texture)
self.texture = None
if self.audio is not None:

View File

@@ -31,7 +31,6 @@ from libs.transition import Transition
from libs.utils import (
OutlinedText,
get_current_ms,
get_key_code,
global_data,
global_tex,
is_l_don_pressed,
@@ -1224,13 +1223,13 @@ class Judgment:
self.big = big
self.is_finished = False
self.fade_animation_1 = Animation.create_fade(132, initial_opacity=0.5, delay=100)
self.fade_animation_1.start()
self.fade_animation_2 = Animation.create_fade(316 - 233.3, delay=233.3)
self.fade_animation_2.start()
self.move_animation = Animation.create_move(83, total_distance=15, start_position=144)
self.fade_animation_1 = tex.get_animation(27, is_copy=True)
self.fade_animation_2 = tex.get_animation(28, is_copy=True)
self.move_animation = tex.get_animation(29, is_copy=True)
self.texture_animation = tex.get_animation(30, is_copy=True)
self.move_animation.start()
self.texture_animation = Animation.create_texture_change(100, textures=[(33, 50, 0), (50, 83, 1), (83, 100, 2), (100, float('inf'), 3)])
self.fade_animation_2.start()
self.fade_animation_1.start()
self.texture_animation.start()
def update(self, current_ms):
@@ -1323,14 +1322,14 @@ class GaugeHitEffect:
self.note_type = note_type
self.is_big = big
self.texture_change = tex.get_animation(2, is_copy=True)
self.circle_fadein = tex.get_animation(31, is_copy=True)
self.resize = tex.get_animation(32, is_copy=True)
self.fade_out = tex.get_animation(33, is_copy=True)
self.rotation = tex.get_animation(34, is_copy=True)
self.texture_change.start()
self.circle_fadein = Animation.create_fade(133, initial_opacity=0.0, final_opacity=1.0, delay=16.67)
self.circle_fadein.start()
self.resize = Animation.create_texture_resize(233, delay=self.texture_change.duration, initial_size=0.75, final_size=1.15)
self.resize.start()
self.fade_out = Animation.create_fade(66, delay=233)
self.fade_out.start()
self.rotation = Animation.create_fade(300, delay=116.67, initial_opacity=0.0, final_opacity=1.0)
self.rotation.start()
self.color = ray.fade(ray.YELLOW, self.circle_fadein.attribute)
self.is_finished = False
@@ -1779,17 +1778,17 @@ class ScoreCounterAnimation:
self.is_2p = is_2p
self.counter = counter
self.direction = -1 if self.is_2p else 1
self.fade_animation_1 = Animation.create_fade(50, initial_opacity=0.0, final_opacity=1.0)
self.fade_animation_1 = tex.get_animation(35, is_copy=True)
self.move_animation_1 = tex.get_animation(36, is_copy=True)
self.fade_animation_2 = tex.get_animation(37, is_copy=True)
self.move_animation_2 = tex.get_animation(38, is_copy=True)
self.move_animation_3 = tex.get_animation(39, is_copy=True)
self.move_animation_4 = tex.get_animation(40, is_copy=True)
self.fade_animation_1.start()
self.move_animation_1 = Animation.create_move(80, total_distance=-20, start_position=175)
self.move_animation_1.start()
self.fade_animation_2 = Animation.create_fade(80, delay=366.74)
self.fade_animation_2.start()
self.move_animation_2 = Animation.create_move(66, total_distance=5, start_position=145, delay=80)
self.move_animation_2.start()
self.move_animation_3 = Animation.create_move(66, delay=279.36, total_distance=-2, start_position=146)
self.move_animation_3.start()
self.move_animation_4 = Animation.create_move(80, delay=366.74, total_distance=10, start_position=148)
self.move_animation_4.start()
if player_num == PlayerNum.P2:
@@ -1928,7 +1927,7 @@ class ComboAnnounce:
self.is_2p = is_2p
self.combo = combo
self.wait = current_time_ms
self.fade = Animation.create_fade(100)
self.fade = tex.get_animation(65)
self.fade.start()
self.is_finished = False
self.audio_played = False
@@ -1977,11 +1976,11 @@ class BranchIndicator:
self.is_2p = is_2p
self.difficulty = 'normal'
self.diff_2 = self.difficulty
self.diff_down = Animation.create_move(100, total_distance=20, ease_out='quadratic')
self.diff_up = Animation.create_move(133, total_distance=70, delay=self.diff_down.duration, ease_out='quadratic')
self.diff_fade = Animation.create_fade(133, delay=self.diff_down.duration)
self.level_fade = Animation.create_fade(116, initial_opacity=0.0, final_opacity=1.0, reverse_delay=116*10)
self.level_scale = Animation.create_texture_resize(116, initial_size=1.0, final_size=1.2, reverse_delay=0)
self.diff_down = tex.get_animation(41)
self.diff_up = tex.get_animation(42)
self.diff_fade = tex.get_animation(43)
self.level_fade = tex.get_animation(44)
self.level_scale = tex.get_animation(45)
self.direction = 1
def update(self, current_time_ms):
self.diff_down.update(current_time_ms)
@@ -2023,24 +2022,24 @@ class FailAnimation:
"""Animates the fail effect"""
def __init__(self, is_2p: bool):
self.is_2p = is_2p
self.bachio_fade_in = Animation.create_fade(150, initial_opacity=0.0, final_opacity=1.0)
self.bachio_fade_in = tex.get_animation(46)
self.bachio_texture_change = tex.get_animation(47)
self.bachio_fall = tex.get_animation(48)
self.bachio_move_out = tex.get_animation(49)
self.bachio_boom_fade_in = tex.get_animation(50)
self.bachio_boom_scale = tex.get_animation(51)
self.bachio_up = tex.get_animation(52)
self.bachio_down = tex.get_animation(53)
self.text_fade_in = tex.get_animation(54)
self.text_fade_in.start()
self.bachio_fade_in.start()
self.bachio_texture_change = Animation.create_texture_change(266.67, textures=[(0, 150, 0), (150, 266.67, 1)], delay=self.bachio_fade_in.duration)
self.bachio_fall = Animation.create_texture_change(500, textures=[[0, 495, 0], [495, 500, 1]], delay=self.bachio_texture_change.duration)
self.bachio_texture_change.start()
self.bachio_fall.start()
self.bachio_move_out = Animation.create_move(116.67, total_distance=150, delay=self.bachio_fade_in.duration, ease_out='quadratic')
self.bachio_move_out.start()
self.bachio_boom_fade_in = Animation.create_fade(66.67, initial_opacity=0.0, final_opacity=1.0, reverse_delay=0, delay=self.bachio_fade_in.duration + self.bachio_move_out.duration)
self.bachio_boom_scale = Animation.create_texture_resize(133.34, initial_size=0.5, final_size=1.0, delay=self.bachio_fade_in.duration + self.bachio_move_out.duration)
self.bachio_boom_fade_in.start()
self.bachio_boom_scale.start()
self.bachio_up = Animation.create_move(416.67, total_distance=60, delay=self.bachio_fade_in.duration + self.bachio_move_out.duration, ease_out='quadratic')
self.bachio_down = Animation.create_move(100, total_distance=60, delay=self.bachio_fade_in.duration + self.bachio_move_out.duration + self.bachio_up.duration, ease_out='quadratic')
self.bachio_up.start()
self.bachio_down.start()
self.text_fade_in = Animation.create_fade(283.33, initial_opacity=0.0, final_opacity=1.0, delay=self.bachio_fade_in.duration + self.bachio_move_out.duration + self.bachio_up.duration/2)
self.text_fade_in.start()
self.name = 'in'
self.frame = self.bachio_texture_change.attribute
audio.play_sound('fail', 'sound')
@@ -2070,13 +2069,13 @@ class ClearAnimation:
"""Animates the clear effect"""
def __init__(self, is_2p: bool):
self.is_2p = is_2p
self.bachio_fade_in = Animation.create_fade(150, initial_opacity=0.0, final_opacity=1.0)
self.bachio_fade_in = tex.get_animation(46)
self.bachio_fade_in.start()
self.bachio_texture_change = Animation.create_texture_change(266.67, textures=[(0, 150, 0), (150, 266.67, 1)], delay=self.bachio_fade_in.duration)
self.bachio_texture_change = tex.get_animation(47)
self.bachio_texture_change.start()
self.bachio_out = Animation.create_texture_change(200, textures=[[0, 50, 0], [50, 100, 1], [100, 150, 2], [150, 200, 3]], delay=self.bachio_texture_change.duration+100)
self.bachio_out = tex.get_animation(55)
self.bachio_out.start()
self.bachio_move_out = Animation.create_move(116.67, total_distance=200, delay=self.bachio_fade_in.duration, ease_out='quadratic')
self.bachio_move_out = tex.get_animation(66)
self.bachio_move_out.start()
self.clear_separate_fade_in = [Animation.create_fade(100, initial_opacity=0.0, final_opacity=1.0, delay=i*50) for i in range(5)]
for fade in self.clear_separate_fade_in:
@@ -2084,7 +2083,7 @@ class ClearAnimation:
self.clear_separate_stretch = [Animation.create_text_stretch(200, delay=i*50) for i in range(5)]
for stretch in self.clear_separate_stretch:
stretch.start()
self.clear_highlight_fade_in = Animation.create_fade(183, initial_opacity=0.0, final_opacity=1.0, reverse_delay=0, delay=450)
self.clear_highlight_fade_in = tex.get_animation(56)
self.clear_highlight_fade_in.start()
self.draw_clear_full = False
self.name = 'in'
@@ -2122,13 +2121,13 @@ class FCAnimation:
"""Animates the full combo effect"""
def __init__(self, is_2p: bool):
self.is_2p = is_2p
self.bachio_fade_in = Animation.create_fade(150, initial_opacity=0.0, final_opacity=1.0)
self.bachio_fade_in = tex.get_animation(46)
self.bachio_fade_in.start()
self.bachio_texture_change = Animation.create_texture_change(266.67, textures=[(0, 150, 0), (150, 266.67, 1)], delay=self.bachio_fade_in.duration)
self.bachio_texture_change = tex.get_animation(47)
self.bachio_texture_change.start()
self.bachio_out = Animation.create_texture_change(200, textures=[[0, 50, 0], [50, 100, 1], [100, 150, 2], [150, 200, 3]], delay=self.bachio_texture_change.duration+100)
self.bachio_out = tex.get_animation(55)
self.bachio_out.start()
self.bachio_move_out = Animation.create_move(116.67, total_distance=200, delay=self.bachio_fade_in.duration, ease_out='quadratic')
self.bachio_move_out = tex.get_animation(49)
self.bachio_move_out.start()
self.clear_separate_fade_in = [Animation.create_fade(100, initial_opacity=0.0, final_opacity=1.0, delay=i*50) for i in range(5)]
for fade in self.clear_separate_fade_in:
@@ -2136,15 +2135,15 @@ class FCAnimation:
self.clear_separate_stretch = [Animation.create_text_stretch(200, delay=i*50) for i in range(5)]
for stretch in self.clear_separate_stretch:
stretch.start()
self.clear_highlight_fade_in = Animation.create_fade(183, initial_opacity=0.0, final_opacity=1.0, reverse_delay=0, delay=450)
self.clear_highlight_fade_in = tex.get_animation(56)
self.clear_highlight_fade_in.start()
self.fc_highlight_up = Animation.create_move(133, total_distance=20, reverse_delay=216.67, delay=450 + self.clear_highlight_fade_in.duration, ease_out='quadratic')
self.fc_highlight_up = tex.get_animation(57)
self.fc_highlight_up.start()
self.fc_highlight_fade_out = Animation.create_fade(133)
self.bachio_move_out_2 = Animation.create_move(700, total_distance=150, ease_in='quadratic', ease_out='quadratic')
self.bachio_move_up = Animation.create_move(350, total_distance=150, reverse_delay=0, ease_in='quadratic')
self.fan_fade_in = Animation.create_fade(183, initial_opacity=0.0, final_opacity=1.0)
self.fan_texture_change = Animation.create_texture_change(100, textures=[[0, 16.67, 0], [16.67, 33.33, 1], [33.33, 50, 2], [50, 66.67, 3], [66.67, 83.33, 4], [83.33, 100, 5]], delay=self.fan_fade_in.duration)
self.fc_highlight_fade_out = tex.get_animation(58)
self.bachio_move_out_2 = tex.get_animation(59)
self.bachio_move_up = tex.get_animation(60)
self.fan_fade_in = tex.get_animation(61)
self.fan_texture_change = tex.get_animation(62)
self.draw_clear_full = False
self.name = 'in'
self.frame = 0
@@ -2298,7 +2297,7 @@ class Gauge:
]
self.gauge_update_anim = tex.get_animation(10)
self.rainbow_fade_in = None
self.rainbow_animation = None
self.rainbow_animation = tex.get_animation(64)
def add_good(self):
"""Adds a good note to the gauge"""
@@ -2327,7 +2326,7 @@ class Gauge:
self.is_clear = self.gauge_length > self.clear_start[min(self.difficulty, Difficulty.HARD)]-1
self.is_rainbow = self.gauge_length == self.gauge_max
if self.gauge_length == self.gauge_max and self.rainbow_fade_in is None:
self.rainbow_fade_in = Animation.create_fade(450, initial_opacity=0.0, final_opacity=1.0)
self.rainbow_fade_in = tex.get_animation(63)
self.rainbow_fade_in.start()
self.gauge_update_anim.update(current_ms)
self.tamashii_fire_change.update(current_ms)
@@ -2335,13 +2334,7 @@ class Gauge:
if self.rainbow_fade_in is not None:
self.rainbow_fade_in.update(current_ms)
if self.rainbow_animation is None:
self.rainbow_animation = Animation.create_texture_change((16.67*8) * 3, textures=[((16.67 * 3) * i, (16.67 * 3) * (i + 1), i) for i in range(8)])
self.rainbow_animation.start()
else:
self.rainbow_animation.update(current_ms)
if self.rainbow_animation.is_finished or self.gauge_length < 87:
self.rainbow_animation = None
self.rainbow_animation.update(current_ms)
def draw(self):
mirror = 'vertical' if self.is_2p else ''
@@ -2357,7 +2350,7 @@ class Gauge:
tex.draw_texture('gauge', 'bar_clear_bottom', x=(clear_point) * 8, x2=(gauge_length-clear_point)*8, index=self.is_2p)
# Rainbow effect for full gauge
if gauge_length == self.gauge_max and self.rainbow_fade_in is not None and self.rainbow_animation is not None:
if gauge_length == self.gauge_max and self.rainbow_fade_in is not None:
if 0 < self.rainbow_animation.attribute < 8:
tex.draw_texture('gauge', 'rainbow' + self.string_diff, frame=self.rainbow_animation.attribute-1, 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)

View File

@@ -10,9 +10,9 @@ from libs.audio import audio
from libs.background import Background
from libs.global_data import Modifiers, PlayerNum, global_data
from libs.tja import Balloon, Drumroll, Note, NoteType, TJAParser, apply_modifiers
from libs.utils import get_current_ms, get_key_code
from libs.utils import get_current_ms
from libs.texture import tex
from scenes.game import DrumHitEffect, GameScreen, JudgeCounter, LaneHitEffect, Player, SCREEN_WIDTH
from scenes.game import DrumHitEffect, DrumType, GameScreen, JudgeCounter, LaneHitEffect, Player, SCREEN_WIDTH, Side
logger = logging.getLogger(__name__)
@@ -93,14 +93,14 @@ class PracticeGameScreen(GameScreen):
self.start_ms = get_current_ms() - self.pause_time
def global_keys(self):
if ray.is_key_pressed(get_key_code(global_data.config["keys"]["restart_key"])):
if ray.is_key_pressed(global_data.config["keys"]["restart_key"]):
if self.song_music is not None:
audio.stop_music_stream(self.song_music)
self.init_tja(global_data.session_data[global_data.player_num].selected_song)
audio.play_sound('restart', 'sound')
self.song_started = False
if ray.is_key_pressed(get_key_code(global_data.config["keys"]["back_key"])):
if ray.is_key_pressed(global_data.config["keys"]["back_key"]):
if self.song_music is not None:
audio.stop_music_stream(self.song_music)
return self.on_screen_end('PRACTICE_SELECT')
@@ -276,7 +276,7 @@ class PracticePlayer(Player):
self.gauge = None
self.paused = False
def spawn_hit_effects(self, note_type: str, side: str):
def spawn_hit_effects(self, note_type: DrumType, side: Side):
self.lane_hit_effect = LaneHitEffect(note_type, self.is_2p)
self.draw_drum_hit_list.append(PracticeDrumHitEffect(note_type, side, self.is_2p, player_num=self.player_num))

View File

@@ -17,7 +17,6 @@ from libs.transition import Transition
from libs.utils import (
OutlinedText,
get_current_ms,
get_key_code,
global_data,
is_l_don_pressed,
is_l_kat_pressed,
@@ -306,7 +305,7 @@ class SongSelectScreen(Screen):
if not current_box.is_back and get_current_ms() >= song.box.wait + (83.33*3):
self.texture_index = current_box.texture_index
if ray.is_key_pressed(get_key_code(global_data.config["keys"]["back_key"])):
if ray.is_key_pressed(global_data.config["keys"]["back_key"]):
logger.info("Back key pressed, returning to ENTRY screen")
return self.on_screen_end('ENTRY')

View File

@@ -110,7 +110,10 @@ class TwoPlayerGameScreen(GameScreen):
current_time = get_current_ms()
self.transition.update(current_time)
self.current_ms = current_time - self.start_ms
self.start_song(current_time)
if self.transition.is_finished:
self.start_song(self.current_ms)
else:
self.start_ms = current_time - self.tja.metadata.offset*1000
self.update_background(current_time)
if self.song_music is not None: