Add animation restart method and new backgrounds

This commit adds a new `restart()` method to animation classes to properly
reset their state, avoiding the need to recreate animations. It also adds
several new background variations and improves background selection.
This commit is contained in:
Yonokid
2025-06-18 23:11:17 -04:00
parent 6c8cdb9fad
commit c1081d255b
8 changed files with 354 additions and 68 deletions

View File

@@ -23,6 +23,10 @@ class BaseAnimation():
"""Update the animation based on the current time."""
pass
def restart(self) -> None:
self.start_ms = get_current_ms()
self.is_finished = False
def _ease_in(self, progress: float, ease_type: str) -> float:
if ease_type == "quadratic":
return progress * progress
@@ -57,9 +61,18 @@ class FadeAnimation(BaseAnimation):
super().__init__(duration, delay)
self.initial_opacity = initial_opacity
self.final_opacity = final_opacity
self.initial_opacity_saved = initial_opacity
self.final_opacity_saved = final_opacity
self.ease_in = ease_in
self.ease_out = ease_out
self.reverse_delay = reverse_delay
self.reverse_delay_saved = reverse_delay
def restart(self):
super().restart()
self.reverse_delay = self.reverse_delay_saved
self.initial_opacity = self.initial_opacity_saved
self.final_opacity = self.final_opacity_saved
def update(self, current_time_ms: float):
elapsed_time = current_time_ms - self.start_ms
@@ -90,11 +103,20 @@ class MoveAnimation(BaseAnimation):
ease_in: Optional[str] = None, ease_out: Optional[str] = None):
super().__init__(duration, delay)
self.reverse_delay = reverse_delay
self.reverse_delay_saved = reverse_delay
self.total_distance = total_distance
self.start_position = start_position
self.total_distance_saved = total_distance
self.start_position_saved = start_position
self.ease_in = ease_in
self.ease_out = ease_out
def restart(self):
super().restart()
self.reverse_delay = self.reverse_delay_saved
self.total_distance = self.total_distance_saved
self.start_position = self.start_position_saved
def update(self, current_time_ms: float):
elapsed_time = current_time_ms - self.start_ms
if elapsed_time < self.delay:
@@ -120,6 +142,7 @@ class TextureChangeAnimation(BaseAnimation):
super().__init__(duration)
self.textures = textures
self.delay = delay
def update(self, current_time_ms: float):
elapsed_time = current_time_ms - self.start_ms - self.delay
if elapsed_time <= self.duration:
@@ -151,6 +174,16 @@ class TextureResizeAnimation(BaseAnimation):
self.initial_size = initial_size
self.final_size = final_size
self.reverse_delay = reverse_delay
self.initial_size_saved = initial_size
self.final_size_saved = final_size
self.reverse_delay_saved = reverse_delay
def restart(self):
super().restart()
self.reverse_delay = self.reverse_delay_saved
self.initial_size = self.initial_size_saved
self.final_size = self.final_size_saved
def update(self, current_time_ms: float):
elapsed_time = current_time_ms - self.start_ms

View File

@@ -12,7 +12,7 @@ class Background:
self.screen_width = screen_width
self.screen_height = screen_height
self.donbg = DonBG.create(self.screen_width, self.screen_height, random.randint(6, 6), 1)
self.bg_normal = BGNormal.create(self.screen_width, self.screen_height, 1)
self.bg_normal = BGNormal.create(self.screen_width, self.screen_height, random.randint(1, 5))
self.bg_fever = BGFever.create(self.screen_width, self.screen_height, 4)
self.footer = Footer(self.screen_width, self.screen_height, random.randint(1, 3))
self.is_clear = False
@@ -50,7 +50,7 @@ class DonBGBase:
self.is_clear = is_clear
self.move.update(current_time_ms)
if self.move.is_finished:
self.move = Animation.create_move(3000, start_position=0, total_distance=-self.textures[self.name + f'_{self.player_num}p'][0].width)
self.move.restart()
class DonBG1(DonBGBase):
def __init__(self, index: int, screen_width: int, screen_height: int, player_num: int):
@@ -60,7 +60,7 @@ class DonBG1(DonBGBase):
super().update(current_time_ms, is_clear)
self.overlay_move.update(current_time_ms)
if self.overlay_move.is_finished:
self.overlay_move = Animation.create_move(1000, start_position=0, total_distance=20, reverse_delay=0)
self.overlay_move.restart()
def draw(self):
texture_index = 0
if self.is_clear:
@@ -81,7 +81,7 @@ class DonBG6(DonBGBase):
super().update(current_time_ms, is_clear)
self.overlay_move.update(current_time_ms)
if self.overlay_move.is_finished:
self.overlay_move = Animation.create_move(1000, start_position=0, total_distance=20, reverse_delay=0)
self.overlay_move.restart()
def draw(self):
texture_index = 0
if self.is_clear:
@@ -103,7 +103,7 @@ class BGNormal:
@staticmethod
def create(screen_width: int, screen_height: int, index: int):
map = [None, BGNormal1]
map = [None, BGNormal1, BGNormal2, BGNormal3, BGNormal4, BGNormal5]
selected_obj = map[index]
return selected_obj(index, screen_width, screen_height)
@@ -117,15 +117,156 @@ class BGNormalBase:
class BGNormal1(BGNormalBase):
def __init__(self, index: int, screen_width: int, screen_height: int):
super().__init__(index, screen_width, screen_height)
self.flicker = Animation.create_fade(16.67*2, initial_opacity=0.5, final_opacity=0.25, reverse_delay=0)
self.flicker = Animation.create_fade(16.67*4, initial_opacity=0.5, final_opacity=0.4, reverse_delay=0)
def update(self, current_time_ms: float):
self.flicker.update(current_time_ms)
if self.flicker.is_finished:
self.flicker = Animation.create_fade(16.67*2, initial_opacity=0.5, final_opacity=0.25, reverse_delay=0)
self.flicker.restart()
def draw(self):
ray.draw_texture(self.textures[self.name][0], 0, 360, ray.WHITE)
ray.draw_texture(self.textures[self.name][1], 0, 360, ray.fade(ray.WHITE, self.flicker.attribute))
class BGNormal2(BGNormalBase):
def __init__(self, index: int, screen_width: int, screen_height: int):
super().__init__(index, screen_width, screen_height)
self.flicker = Animation.create_fade(16.67*4, initial_opacity=0.5, final_opacity=0.4, reverse_delay=0)
def update(self, current_time_ms: float):
self.flicker.update(current_time_ms)
if self.flicker.is_finished:
self.flicker.restart()
def draw(self):
ray.draw_texture(self.textures[self.name][0], 0, 360, ray.WHITE)
ray.draw_texture(self.textures[self.name][1], 0, 360, ray.fade(ray.WHITE, self.flicker.attribute))
class BGNormal3(BGNormalBase):
def __init__(self, index: int, screen_width: int, screen_height: int):
super().__init__(index, screen_width, screen_height)
self.flicker = Animation.create_fade(16.67*10, initial_opacity=0.5, final_opacity=0.4, reverse_delay=0)
def update(self, current_time_ms):
self.flicker.update(current_time_ms)
if self.flicker.is_finished:
self.flicker.restart()
def draw(self):
src = ray.Rectangle(0, 0, self.textures[self.name][0].width, self.textures[self.name][0].height)
dest = ray.Rectangle(0, 360, self.screen_width, self.textures[self.name][0].height)
ray.draw_texture_pro(self.textures[self.name][0], src, dest, ray.Vector2(0, 0), 0, ray.WHITE)
ray.draw_texture(self.textures[self.name][3], (self.screen_width//2) - (self.textures[self.name][3].width//2), 360, ray.WHITE)
ray.draw_texture(self.textures[self.name][6], 0, 360, ray.WHITE)
src = ray.Rectangle(0, 0, -self.textures[self.name][7].width, self.textures[self.name][7].height)
dest = ray.Rectangle((self.screen_width//2) - 170, 490, self.textures[self.name][7].width, self.textures[self.name][7].height)
ray.draw_texture_pro(self.textures[self.name][7], src, dest, ray.Vector2(0, 0), 0, ray.WHITE)
ray.draw_texture(self.textures[self.name][7], (self.screen_width//2) + 50, 490, ray.WHITE)
#Orange
color = ray.fade(ray.WHITE, self.flicker.attribute)
ray.draw_texture(self.textures[self.name][1], (self.screen_width//2) + 180, 300, color)
ray.draw_texture(self.textures[self.name][1], (self.screen_width//2) - 380, 300, color)
#Red Green Orange
ray.draw_texture(self.textures[self.name][2], (self.screen_width//2) - 220, 350, color)
ray.draw_texture(self.textures[self.name][4], (self.screen_width//2) - 100, 350, color)
ray.draw_texture(self.textures[self.name][1], (self.screen_width//2) + 10, 350, color)
#Yellow
ray.draw_texture(self.textures[self.name][5], (self.screen_width//2) - 220, 500, color)
ray.draw_texture(self.textures[self.name][5], (self.screen_width//2) + 10, 500, color)
ray.draw_texture(self.textures[self.name][9], (self.screen_width//2) - 320, 520, ray.WHITE)
ray.draw_texture(self.textures[self.name][10], 100, 360, ray.WHITE)
ray.draw_texture(self.textures[self.name][11], self.screen_width - 100 - self.textures[self.name][11].width, 360, ray.WHITE)
class BGNormal4(BGNormalBase):
class Petal:
def __init__(self):
self.spawn_point = self.random_excluding_range()
duration = random.randint(1400, 2000)
self.move_y = Animation.create_move(duration, total_distance=360)
self.move_x = Animation.create_move(duration, total_distance=random.randint(-300, 300))
def random_excluding_range(self):
while True:
num = random.randint(0, 1280)
if num < 260 or num > 540:
return num
def update(self, current_time_ms):
self.move_x.update(current_time_ms)
self.move_y.update(current_time_ms)
def draw(self, texture):
ray.draw_texture(texture, self.spawn_point + int(self.move_x.attribute), 360+int(self.move_y.attribute), ray.fade(ray.WHITE, 0.75))
def __init__(self, index: int, screen_width: int, screen_height: int):
super().__init__(index, screen_width, screen_height)
self.flicker = Animation.create_fade(16.67*3, initial_opacity=0.5, final_opacity=0.4, reverse_delay=0)
self.turtle_move = Animation.create_move(3333*2, start_position=screen_width+112, total_distance=-(screen_width+(112*4)))
textures = ((0, 100, 3), (100, 200, 4), (200, 300, 5), (300, 400, 6), (400, 500, 7), (500, 600, 8))
self.turtle_change = Animation.create_texture_change(600, textures=textures)
self.petals = {self.Petal(), self.Petal(), self.Petal(), self.Petal(), self.Petal()}
def update(self, current_time_ms: float):
self.flicker.update(current_time_ms)
if self.flicker.is_finished:
self.flicker.restart()
self.turtle_move.update(current_time_ms)
if self.turtle_move.is_finished:
self.turtle_move.restart()
self.turtle_change.update(current_time_ms)
if self.turtle_change.is_finished:
self.turtle_change.restart()
for petal in self.petals:
petal.update(current_time_ms)
if petal.move_y.is_finished:
self.petals.remove(petal)
self.petals.add(self.Petal())
def draw(self):
ray.draw_texture(self.textures[self.name][0], 0, 360, ray.WHITE)
ray.draw_texture(self.textures[self.name][2], self.screen_width//2 - 20, 380, ray.WHITE)
ray.draw_texture(self.textures[self.name][self.turtle_change.attribute], int(self.turtle_move.attribute), 550, ray.WHITE)
ray.draw_texture(self.textures[self.name][9], 0, 360, ray.WHITE)
for petal in self.petals:
petal.draw(self.textures[self.name][10])
class BGNormal5(BGNormalBase):
def __init__(self, index: int, screen_width: int, screen_height: int):
super().__init__(index, screen_width, screen_height)
self.flicker = Animation.create_fade(16.67*10, initial_opacity=0.75, final_opacity=0.4, reverse_delay=0)
def update(self, current_time_ms: float):
self.flicker.update(current_time_ms)
if self.flicker.is_finished:
self.flicker.restart()
def draw(self):
ray.draw_texture(self.textures[self.name][0], 0, 360, ray.WHITE)
ray.draw_texture(self.textures[self.name][13], -35, 340, ray.WHITE)
ray.draw_texture(self.textures[self.name][12], 103, 380, ray.WHITE)
ray.draw_texture(self.textures[self.name][11], 241, 400, ray.WHITE)
ray.draw_texture(self.textures[self.name][10], 380, 380, ray.WHITE)
ray.draw_texture(self.textures[self.name][9], 518, 340, ray.WHITE)
ray.draw_texture(self.textures[self.name][4], 657, 340, ray.WHITE)
ray.draw_texture(self.textures[self.name][5], 795, 380, ray.WHITE)
ray.draw_texture(self.textures[self.name][6], 934, 400, ray.WHITE)
ray.draw_texture(self.textures[self.name][7], 1072, 380, ray.WHITE)
ray.draw_texture(self.textures[self.name][8], 1211, 340, ray.WHITE)
color = ray.fade(ray.WHITE, self.flicker.attribute)
ray.draw_texture(self.textures[self.name][14], -35 - 10, 340 - 10, color)
ray.draw_texture(self.textures[self.name][14], 103 - 10, 380 - 10, color)
ray.draw_texture(self.textures[self.name][14], 241 - 10, 400 - 10, color)
ray.draw_texture(self.textures[self.name][14], 380 - 10, 380 - 10, color)
ray.draw_texture(self.textures[self.name][14], 518 - 10, 340 - 10, color)
ray.draw_texture(self.textures[self.name][14], 657 - 10, 340 - 10, color)
ray.draw_texture(self.textures[self.name][14], 795 - 10, 380 - 10, color)
ray.draw_texture(self.textures[self.name][14], 934 - 10, 400 - 10, color)
ray.draw_texture(self.textures[self.name][14], 1072 - 10, 380 - 10, color)
ray.draw_texture(self.textures[self.name][14], 1211 - 10, 340 - 10, color)
ray.draw_texture(self.textures[self.name][3], (self.screen_width//2) - (self.textures[self.name][3].width//2), 360+172, ray.fade(ray.WHITE, 0.75))
ray.draw_texture(self.textures[self.name][1], 50, 600, ray.fade(ray.WHITE, 0.75))
ray.draw_texture(self.textures[self.name][1], self.screen_width-50 - self.textures[self.name][2].width, 600, ray.fade(ray.WHITE, 0.75))
ray.draw_texture(self.textures[self.name][2], self.screen_width-50 - self.textures[self.name][2].width, 600, ray.WHITE)
ray.draw_texture(self.textures[self.name][2], 50, 600, ray.WHITE)
class BGFever:
@staticmethod
@@ -149,10 +290,10 @@ class BGFever4(BGFeverBase):
def update(self, current_time_ms: float):
self.vertical_move.update(current_time_ms)
if self.vertical_move.is_finished:
self.vertical_move = Animation.create_move(1300, start_position=0, total_distance=50, reverse_delay=0)
self.vertical_move.restart()
self.horizontal_move.update(current_time_ms)
if self.horizontal_move.is_finished:
self.horizontal_move = Animation.create_move(5000, start_position=0, total_distance=self.textures[self.name][2].width)
self.horizontal_move.restart()
def draw(self):
texture = self.textures[self.name][0]
for i in range(0, self.screen_width + texture.width, texture.width):

View File

@@ -63,7 +63,6 @@ def load_all_textures_from_zip(zip_path: Path) -> dict[str, list[ray.Texture]]:
result_dict[true_filename][index] = texture
return result_dict
def rounded(num: float) -> int:
sign = 1 if (num >= 0) else -1
num = abs(num)
@@ -114,14 +113,16 @@ def save_config(config: dict[str, Any]) -> None:
tomlkit.dump(config, f)
def is_l_don_pressed() -> bool:
keys = global_data.config["keybinds"]["left_don"]
keys = global_data.config["keys"]["left_don"]
gamepad_buttons = global_data.config["gamepad"]["left_don"]
for key in keys:
if ray.is_key_pressed(ord(key)):
return True
if ray.is_gamepad_available(0):
if ray.is_gamepad_button_pressed(0, 16):
return True
for button in gamepad_buttons:
if ray.is_gamepad_button_pressed(0, button):
return True
mid_x, mid_y = (1280//2, 720)
allowed_gestures = {ray.Gesture.GESTURE_TAP, ray.Gesture.GESTURE_DOUBLETAP}
@@ -134,14 +135,16 @@ def is_l_don_pressed() -> bool:
return False
def is_r_don_pressed() -> bool:
keys = global_data.config["keybinds"]["right_don"]
keys = global_data.config["keys"]["right_don"]
gamepad_buttons = global_data.config["gamepad"]["right_don"]
for key in keys:
if ray.is_key_pressed(ord(key)):
return True
if ray.is_gamepad_available(0):
if ray.is_gamepad_button_pressed(0, 17):
return True
for button in gamepad_buttons:
if ray.is_gamepad_button_pressed(0, button):
return True
mid_x, mid_y = (1280//2, 720)
allowed_gestures = {ray.Gesture.GESTURE_TAP, ray.Gesture.GESTURE_DOUBLETAP}
@@ -154,14 +157,16 @@ def is_r_don_pressed() -> bool:
return False
def is_l_kat_pressed() -> bool:
keys = global_data.config["keybinds"]["left_kat"]
keys = global_data.config["keys"]["left_kat"]
gamepad_buttons = global_data.config["gamepad"]["left_kat"]
for key in keys:
if ray.is_key_pressed(ord(key)):
return True
if ray.is_gamepad_available(0):
if ray.is_gamepad_button_pressed(0, 10):
return True
for button in gamepad_buttons:
if ray.is_gamepad_button_pressed(0, button):
return True
mid_x, mid_y = (1280//2, 720)
allowed_gestures = {ray.Gesture.GESTURE_TAP, ray.Gesture.GESTURE_DOUBLETAP}
@@ -174,14 +179,16 @@ def is_l_kat_pressed() -> bool:
return False
def is_r_kat_pressed() -> bool:
keys = global_data.config["keybinds"]["right_kat"]
keys = global_data.config["keys"]["right_kat"]
gamepad_buttons = global_data.config["gamepad"]["right_kat"]
for key in keys:
if ray.is_key_pressed(ord(key)):
return True
if ray.is_gamepad_available(0):
if ray.is_gamepad_button_pressed(0, 12):
return True
for button in gamepad_buttons:
if ray.is_gamepad_button_pressed(0, button):
return True
mid_x, mid_y = (1280//2, 720)
allowed_gestures = {ray.Gesture.GESTURE_TAP, ray.Gesture.GESTURE_DOUBLETAP}