add input locking, fix more bugs

This commit is contained in:
Anthony Samms
2025-09-18 11:48:16 -04:00
parent 92e6197fd2
commit 97ea7112fa
10 changed files with 100 additions and 71 deletions

View File

@@ -1,6 +1,8 @@
import time
from typing import Any, Optional
from libs.global_data import global_data
def rounded(num: float) -> int:
sign = 1 if (num >= 0) else -1
@@ -15,7 +17,7 @@ def get_current_ms() -> int:
class BaseAnimation():
def __init__(self, duration: float, delay: float = 0.0, loop: bool = False) -> None:
def __init__(self, duration: float, delay: float = 0.0, loop: bool = False, lock_input: bool = False) -> None:
"""
Initialize a base animation.
@@ -32,6 +34,7 @@ class BaseAnimation():
self.attribute = 0
self.is_started = False
self.loop = loop
self.lock_input = lock_input
def __repr__(self):
return str(self.__dict__)
@@ -43,11 +46,15 @@ class BaseAnimation():
"""Update the animation based on the current time."""
if self.loop and self.is_finished:
self.restart()
if self.lock_input and self.is_finished:
global_data.input_locked = False
def restart(self) -> None:
self.start_ms = get_current_ms()
self.is_finished = False
self.delay = self.delay_saved
if self.lock_input:
global_data.input_locked = True
def start(self) -> None:
self.is_started = True
@@ -55,9 +62,13 @@ class BaseAnimation():
def pause(self):
self.is_started = False
if self.lock_input:
global_data.input_locked = False
def unpause(self):
self.is_started = True
if self.lock_input:
global_data.input_locked = True
def reset(self):
self.restart()
@@ -91,10 +102,10 @@ class BaseAnimation():
class FadeAnimation(BaseAnimation):
def __init__(self, duration: float, initial_opacity: float = 1.0, loop: bool = False,
final_opacity: float = 0.0, delay: float = 0.0,
lock_input: bool = False, final_opacity: float = 0.0, delay: float = 0.0,
ease_in: Optional[str] = None, ease_out: Optional[str] = None,
reverse_delay: Optional[float] = None) -> None:
super().__init__(duration, delay=delay, loop=loop)
super().__init__(duration, delay=delay, loop=loop, lock_input=lock_input)
self.initial_opacity = initial_opacity
self.attribute = initial_opacity
self.final_opacity = final_opacity
@@ -139,10 +150,10 @@ class FadeAnimation(BaseAnimation):
class MoveAnimation(BaseAnimation):
def __init__(self, duration: float, total_distance: int = 0, loop: bool = False,
start_position: int = 0, delay: float = 0.0,
lock_input: bool = False, start_position: int = 0, delay: float = 0.0,
reverse_delay: Optional[float] = None,
ease_in: Optional[str] = None, ease_out: Optional[str] = None) -> None:
super().__init__(duration, delay=delay, loop=loop)
super().__init__(duration, delay=delay, loop=loop, lock_input=lock_input)
self.reverse_delay = reverse_delay
self.reverse_delay_saved = reverse_delay
self.total_distance = total_distance
@@ -184,8 +195,8 @@ class MoveAnimation(BaseAnimation):
class TextureChangeAnimation(BaseAnimation):
def __init__(self, duration: float, textures: list[tuple[float, float, int]],
loop: bool = False, delay: float = 0.0) -> None:
super().__init__(duration, loop=loop)
loop: bool = False, lock_input: bool = False, delay: float = 0.0) -> None:
super().__init__(duration, loop=loop, lock_input=lock_input)
self.textures = textures
self.delay = delay
self.delay_saved = delay
@@ -212,8 +223,8 @@ class TextureChangeAnimation(BaseAnimation):
self.is_finished = True
class TextStretchAnimation(BaseAnimation):
def __init__(self, duration: float, loop: bool = False,) -> None:
super().__init__(duration, loop=loop)
def __init__(self, duration: float, loop: bool = False, lock_input: bool = False) -> None:
super().__init__(duration, loop=loop, lock_input=lock_input)
def update(self, current_time_ms: float) -> None:
if not self.is_started:
return
@@ -230,11 +241,11 @@ class TextStretchAnimation(BaseAnimation):
class TextureResizeAnimation(BaseAnimation):
def __init__(self, duration: float, initial_size: float = 1.0,
loop: bool = False,
loop: bool = False, lock_input: bool = False,
final_size: float = 0.0, delay: float = 0.0,
reverse_delay: Optional[float] = None,
ease_in: Optional[str] = None, ease_out: Optional[str] = None) -> None:
super().__init__(duration, delay=delay, loop=loop)
super().__init__(duration, delay=delay, loop=loop, lock_input=lock_input)
self.initial_size = initial_size
self.final_size = final_size
self.reverse_delay = reverse_delay

View File

@@ -1,10 +1,10 @@
from libs.animation import Animation
from libs.utils import global_data
from libs.utils import global_tex
class Chara2D:
def __init__(self, index: int, bpm: float, path: str = 'chara'):
self.name = "chara_" + str(index)
self.tex = global_data.tex
self.tex = global_tex
self.anims = dict()
self.bpm = bpm
self.current_anim = 'normal'

26
libs/global_data.py Normal file
View File

@@ -0,0 +1,26 @@
from dataclasses import dataclass, field
from pathlib import Path
@dataclass
class Modifiers:
auto: bool = False
speed: float = 1.0
display: bool = False
inverse: bool = False
random: int = 0
@dataclass
class GlobalData:
selected_song: Path = Path()
songs_played: int = 0
config: dict = field(default_factory=lambda: dict())
song_hashes: dict[str, list[dict]] = field(default_factory=lambda: dict()) #Hash to path
song_paths: dict[Path, str] = field(default_factory=lambda: dict()) #path to hash
song_progress: float = 0.0
total_songs: int = 0
hit_sound: int = 0
player_num: int = 1
input_locked: bool = False
modifiers: Modifiers = field(default_factory=lambda: Modifiers())
global_data = GlobalData()

View File

@@ -1,7 +1,7 @@
from enum import Enum
import pyray as ray
from libs.utils import OutlinedText, global_data
from libs.utils import OutlinedText, global_tex
class Nameplate:
@@ -18,7 +18,7 @@ class Nameplate:
self.name.unload()
self.title.unload()
def draw(self, x: int, y: int, fade: float = 1.0):
tex = global_data.tex
tex = global_tex
tex.draw_texture('nameplate', 'shadow', x=x, y=y, fade=min(0.5, fade))
if self.player_num == -1:
frame = 2
@@ -52,9 +52,9 @@ class Indicator:
WAIT = 3
def __init__(self, state: State):
self.state = state
self.don_fade = global_data.tex.get_animation(6)
self.blue_arrow_move = global_data.tex.get_animation(7)
self.blue_arrow_fade = global_data.tex.get_animation(8)
self.don_fade = global_tex.get_animation(6)
self.blue_arrow_move = global_tex.get_animation(7)
self.blue_arrow_fade = global_tex.get_animation(8)
def update(self, current_time_ms: float):
self.don_fade.update(current_time_ms)
@@ -62,7 +62,7 @@ class Indicator:
self.blue_arrow_fade.update(current_time_ms)
def draw(self, x: int, y: int, fade=1.0):
tex = global_data.tex
tex = global_tex
tex.draw_texture('indicator', 'background', x=x, y=y, fade=fade)
tex.draw_texture('indicator', 'text', frame=self.state.value, x=x, y=y, fade=fade)
tex.draw_texture('indicator', 'drum_face', index=self.state.value, x=x, y=y, fade=fade)

View File

@@ -1,16 +1,16 @@
import pyray as ray
from libs.utils import OutlinedText, global_data
from libs.utils import OutlinedText, global_tex
class Transition:
def __init__(self, title: str, subtitle: str, is_second: bool = False) -> None:
self.is_finished = False
self.rainbow_up = global_data.tex.get_animation(0)
self.mini_up = global_data.tex.get_animation(1)
self.chara_down = global_data.tex.get_animation(2)
self.song_info_fade = global_data.tex.get_animation(3)
self.song_info_fade_out = global_data.tex.get_animation(4)
self.rainbow_up = global_tex.get_animation(0)
self.mini_up = global_tex.get_animation(1)
self.chara_down = global_tex.get_animation(2)
self.song_info_fade = global_tex.get_animation(3)
self.song_info_fade_out = global_tex.get_animation(4)
self.title = OutlinedText(title, 40, ray.WHITE, ray.BLACK, outline_thickness=5)
self.subtitle = OutlinedText(subtitle, 30, ray.WHITE, ray.BLACK, outline_thickness=5)
self.is_second = is_second
@@ -38,7 +38,7 @@ class Transition:
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))
offset = 816 - self.rainbow_up.attribute
global_data.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)
texture = self.title.texture
y = 1176 - texture.height//2 - int(self.rainbow_up.attribute) - offset
@@ -53,16 +53,16 @@ class Transition:
total_offset = 0
if self.is_second:
total_offset = 816
global_data.tex.draw_texture('rainbow_transition', 'rainbow_bg_bottom', y=-self.rainbow_up.attribute - total_offset)
global_data.tex.draw_texture('rainbow_transition', 'rainbow_bg_top', y=-self.rainbow_up.attribute - total_offset)
global_data.tex.draw_texture('rainbow_transition', 'rainbow_bg', 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', y=-self.rainbow_up.attribute - total_offset)
offset = self.chara_down.attribute
chara_offset = 0
if self.is_second:
offset = self.chara_down.attribute - self.mini_up.attribute//3
chara_offset = 408
global_data.tex.draw_texture('rainbow_transition', 'chara_left', x=-self.mini_up.attribute//2 - chara_offset, y=-self.mini_up.attribute + offset - total_offset)
global_data.tex.draw_texture('rainbow_transition', 'chara_right', x=self.mini_up.attribute//2 + chara_offset, y=-self.mini_up.attribute + offset - total_offset)
global_data.tex.draw_texture('rainbow_transition', 'chara_center', y=-self.rainbow_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)
global_tex.draw_texture('rainbow_transition', 'chara_right', x=self.mini_up.attribute//2 + chara_offset, y=-self.mini_up.attribute + offset - total_offset)
global_tex.draw_texture('rainbow_transition', 'chara_center', y=-self.rainbow_up.attribute + offset - total_offset)
self.draw_song_info()

View File

@@ -1,12 +1,10 @@
import ctypes
import hashlib
import math
import os
import sys
import tempfile
import time
import zipfile
from dataclasses import dataclass, field
from dataclasses import dataclass
from libs.global_data import global_data
from functools import lru_cache
from pathlib import Path
from typing import Any, Optional
@@ -89,6 +87,8 @@ def save_config(config: dict[str, Any]) -> None:
tomlkit.dump(config, f)
def is_l_don_pressed() -> bool:
if global_data.input_locked:
return False
keys = global_data.config["keys"]["left_don"]
gamepad_buttons = global_data.config["gamepad"]["left_don"]
for key in keys:
@@ -111,6 +111,8 @@ def is_l_don_pressed() -> bool:
return False
def is_r_don_pressed() -> bool:
if global_data.input_locked:
return False
keys = global_data.config["keys"]["right_don"]
gamepad_buttons = global_data.config["gamepad"]["right_don"]
for key in keys:
@@ -135,6 +137,8 @@ def is_r_don_pressed() -> bool:
return False
def is_l_kat_pressed() -> bool:
if global_data.input_locked:
return False
keys = global_data.config["keys"]["left_kat"]
gamepad_buttons = global_data.config["gamepad"]["left_kat"]
for key in keys:
@@ -159,6 +163,8 @@ def is_l_kat_pressed() -> bool:
return False
def is_r_kat_pressed() -> bool:
if global_data.input_locked:
return False
keys = global_data.config["keys"]["right_kat"]
gamepad_buttons = global_data.config["gamepad"]["right_kat"]
for key in keys:
@@ -182,14 +188,6 @@ def is_r_kat_pressed() -> bool:
return False
@dataclass
class Modifiers:
auto: bool = False
speed: float = 1.0
display: bool = False
inverse: bool = False
random: int = 0
@dataclass
class SessionData:
selected_difficulty: int = 0
@@ -205,26 +203,11 @@ class SessionData:
prev_score: int = 0
session_data = SessionData()
global_tex = TextureWrapper()
def reset_session():
return SessionData()
@dataclass
class GlobalData:
selected_song: Path = Path()
tex: TextureWrapper = field(default_factory=lambda: TextureWrapper())
songs_played: int = 0
config: dict = field(default_factory=lambda: dict())
song_hashes: dict[str, list[dict]] = field(default_factory=lambda: dict()) #Hash to path
song_paths: dict[Path, str] = field(default_factory=lambda: dict()) #path to hash
song_progress: float = 0.0
total_songs: int = 0
hit_sound: int = 0
player_num: int = 1
modifiers: Modifiers = field(default_factory=lambda: Modifiers())
global_data = GlobalData()
text_cache = set()
if not Path('cache/image').exists():
if not Path('cache').exists():