title screen works

This commit is contained in:
Yonokid
2024-09-10 00:43:38 -04:00
parent cb20f408ac
commit 1843ca9a49
5 changed files with 291 additions and 71 deletions

3
.gitignore vendored
View File

@@ -1,2 +1,3 @@
Songs Songs
__pycache__ __pycache__
attract_videos

View File

@@ -191,7 +191,6 @@ class GameScreen:
self.song_music = ray.load_music_stream(self.tja.wave) self.song_music = ray.load_music_stream(self.tja.wave)
ray.play_music_stream(self.song_music) ray.play_music_stream(self.song_music)
self.start_ms = get_current_ms() - self.tja.offset*1000 self.start_ms = get_current_ms() - self.tja.offset*1000
self.profiler = Profiler()
def update(self): def update(self):
ray.update_music_stream(self.song_music) ray.update_music_stream(self.song_music)
@@ -199,7 +198,7 @@ class GameScreen:
self.player_1.update(self) self.player_1.update(self)
def draw(self): def draw(self):
self.profiler.profile(self.player_1.draw, (self)) self.player_1.draw(self)
class Player: class Player:
def __init__(self, game_screen, player_number, difficulty): def __init__(self, game_screen, player_number, difficulty):

View File

@@ -1,6 +1,7 @@
import time import time
import os import os
import pyray as ray import pyray as ray
import cv2
from collections import deque from collections import deque
@@ -303,6 +304,8 @@ class tja_parser:
elif '#GOGOEND' in part: elif '#GOGOEND' in part:
self.gogo_time = False self.gogo_time = False
continue continue
elif '#LYRIC' in part:
continue
#Unrecognized commands will be skipped for now #Unrecognized commands will be skipped for now
elif '#' in part: elif '#' in part:
continue continue
@@ -408,6 +411,12 @@ class Animation:
elif self.type == 'text_stretch': elif self.type == 'text_stretch':
self.text_stretch(current_ms, self.text_stretch(current_ms,
self.duration) self.duration)
elif self.type == 'texture_resize':
self.texture_resize(current_ms,
self.duration,
initial_size=self.params.get('initial_size', 1.0),
final_size=self.params.get('final_size', 1.0),
delay=self.params.get('delay', 0.0))
def fade(self, current_ms, duration, initial_opacity, final_opacity, delay, ease_in, ease_out): def fade(self, current_ms, duration, initial_opacity, final_opacity, delay, ease_in, ease_out):
def ease_out_progress(progress, ease): def ease_out_progress(progress, ease):
@@ -478,67 +487,124 @@ class Animation:
else: else:
self.attribute = 0 self.attribute = 0
self.is_finished = True self.is_finished = True
def texture_resize(self, current_ms, duration, initial_size, final_size, delay):
import cv2 elapsed_time = current_ms - self.start_ms
if elapsed_time < delay:
self.attribute = initial_size
elapsed_time -= delay
if elapsed_time >= duration:
self.attribute = final_size
self.is_finished = True
elif elapsed_time < duration:
progress = elapsed_time / duration
self.attribute = initial_size + ((final_size - initial_size) * progress)
else:
self.attribute = final_size
self.is_finished = True
class VideoPlayer: class VideoPlayer:
def __init__(self, path, loop_start=None): def __init__(self, path, loop_start=None):
video_path = path self.video_path = path
audio_path = path[:-4] + '.ogg' self.start_ms = None
self.loop_start = loop_start self.loop_start = loop_start
self.cap = cv2.VideoCapture(video_path)
fps = self.cap.get(cv2.CAP_PROP_FPS)
self.frame_texture = None
self.frame_time = (1.0 / fps) * 1000
self.start_ms = get_current_ms()
self.audio = ray.load_music_stream(audio_path)
if loop_start is None:
self.audio.looping = False
self.is_finished = [False, False]
ray.play_music_stream(self.audio)
self.current_frame = None
self.last_frame = self.current_frame
self.frame_index = 0
self.frames = []
self.cap = cv2.VideoCapture(self.video_path)
self.fps = self.cap.get(cv2.CAP_PROP_FPS)
self.is_finished = [False, False]
audio_path = path[:-4] + '.ogg'
self.audio = ray.load_music_stream(audio_path)
def convert_frames_background(self, index):
if not self.cap.isOpened(): if not self.cap.isOpened():
print("Error: Could not open video file.") raise ValueError("Error: Could not open video file.")
return
total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
if len(self.frames) == total_frames:
return 0
self.cap.set(cv2.CAP_PROP_POS_FRAMES, index)
success, frame = self.cap.read()
timestamp = (index / self.fps * 1000)
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
new_frame = ray.Image(frame_rgb.tobytes(), frame_rgb.shape[1], frame_rgb.shape[0], 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
self.frames.append((timestamp, new_frame))
print(len(self.frames), total_frames)
def convert_frames(self):
'''
if ray.file_exists(path[:-4] + '.pkl'):
self.object_file = path[:-4] + '.pkl'
with open(self.object_file, 'rb') as f:
self.frames = pickle.load(f)
print(f"Loaded {path[:-4] + '.pkl'}")
else:
self.object_file = None
if self.object_file is None:
'''
if not self.cap.isOpened():
raise ValueError("Error: Could not open video file.")
frame_count = 0
success, frame = self.cap.read()
while success:
timestamp = (frame_count / self.fps * 1000)
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
new_frame = ray.Image(frame_rgb.tobytes(), frame_rgb.shape[1], frame_rgb.shape[0], 1, ray.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
self.frames.append((timestamp, new_frame))
success, frame = self.cap.read()
frame_count += 1
self.cap.release()
print(f"Extracted {len(self.frames)} frames.")
'''
with open(path[:-4] + '.pkl', 'wb') as f:
pickle.dump(self.frames, f)
'''
self.start_ms = get_current_ms()
def update(self): def update(self):
current_ms = get_current_ms() if self.start_ms is None:
elapsed_time = current_ms - self.start_ms self.start_ms = get_current_ms()
ray.play_music_stream(self.audio)
if self.frames == []:
self.convert_frames()
ray.update_music_stream(self.audio) ray.update_music_stream(self.audio)
if not ray.is_music_stream_playing(self.audio): time_played = ray.get_music_time_played(self.audio) / ray.get_music_time_length(self.audio)
if time_played > 0.95:
self.is_finished[1] = True self.is_finished[1] = True
if elapsed_time >= self.frame_time: if self.frame_index == len(self.frames)-1:
ret, frame = self.cap.read() self.is_finished[0] = True
return
timestamp, frame = self.frames[self.frame_index][0], self.frames[self.frame_index][1]
if not ret: if self.start_ms is not None:
# Reset to the loop start frame elapsed_time = get_current_ms() - self.start_ms
if self.loop_start == None: if elapsed_time >= timestamp:
self.is_finished[0] = True self.current_frame = ray.load_texture_from_image(frame)
else: if self.last_frame != self.current_frame and self.last_frame is not None:
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.loop_start) ray.unload_texture(self.last_frame)
ret, frame = self.cap.read() # Read the frame at loop start self.frame_index += 1
if not ret: self.last_frame = self.current_frame
return # If still not successful, return
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = ray.Image(frame_rgb.tobytes(), frame_rgb.shape[1], frame_rgb.shape[0], 1, ray.PIXELFORMAT_UNCOMPRESSED_R8G8B8)
new_texture = ray.load_texture_from_image(image)
# Unload the previous texture if it exists
if self.frame_texture:
ray.unload_texture(self.frame_texture)
# Assign the new texture to the instance variable
self.frame_texture = new_texture
self.start_ms = current_ms
def draw(self): def draw(self):
if self.frame_texture: if self.current_frame is not None:
ray.draw_texture(self.frame_texture, 0, 0, ray.WHITE) ray.draw_texture(self.current_frame, 0, 0, ray.WHITE)
def __del__(self): def __del__(self):
# Ensure resources are cleaned up when the instance is deleted if hasattr(self, 'current_frame') and self.current_frame:
if self.frame_texture: ray.unload_texture(self.current_frame)
ray.unload_texture(self.frame_texture) if hasattr(self, 'last_frame') and self.last_frame:
self.cap.release() ray.unload_texture(self.last_frame)

View File

@@ -42,12 +42,15 @@ def main():
start_song = False start_song = False
while not ray.window_should_close(): while not ray.window_should_close():
ray.begin_drawing() ray.begin_drawing()
ray.clear_background(ray.WHITE) screen = screen_mapping[current_screen]
if screen == title_screen:
ray.clear_background(ray.BLACK)
else:
ray.clear_background(ray.WHITE)
if ray.is_key_pressed(ray.KeyboardKey.KEY_F11): if ray.is_key_pressed(ray.KeyboardKey.KEY_F11):
ray.toggle_fullscreen() ray.toggle_fullscreen()
screen = screen_mapping[current_screen]
if screen == game_screen and not start_song: if screen == game_screen and not start_song:
game_screen.init_tja(sys.argv[1], sys.argv[2]) game_screen.init_tja(sys.argv[1], sys.argv[2])
start_song = True start_song = True

187
title.py
View File

@@ -2,6 +2,8 @@ import pyray as ray
import numpy as np import numpy as np
import vlc import vlc
import cv2 import cv2
import os
import random
from global_funcs import Animation, VideoPlayer, get_current_ms from global_funcs import Animation, VideoPlayer, get_current_ms
class TitleScreen: class TitleScreen:
@@ -9,7 +11,14 @@ class TitleScreen:
self.width = width self.width = width
self.height = height self.height = height
self.op_video = VideoPlayer('Videos\\OP.mp4') self.op_video = VideoPlayer('Videos\\OP.mp4')
self.attract_videos = []
for root, folder, files in os.walk('Videos\\attract_videos'):
for file in files:
if file.endswith('.mp4'):
self.attract_videos.append(VideoPlayer(root + '\\' + file))
self.current_attract_video = None
self.warning = None self.warning = None
self.scene = None
self.load_textures() self.load_textures()
def load_textures(self): def load_textures(self):
@@ -32,39 +41,61 @@ class TitleScreen:
self.texture_warning_bachi = ray.load_texture('Graphics\\lumendata\\attract\\keikoku\\keikoku_img00019.png') self.texture_warning_bachi = ray.load_texture('Graphics\\lumendata\\attract\\keikoku\\keikoku_img00019.png')
self.texture_warning_bachi_hit = ray.load_texture('Graphics\\lumendata\\attract\\keikoku\\keikoku_img00018.png') self.texture_warning_bachi_hit = ray.load_texture('Graphics\\lumendata\\attract\\keikoku\\keikoku_img00018.png')
self.texture_warning_x_1 = ray.load_texture('Graphics\\lumendata\\attract\\keikoku\\keikoku_img00014.png')
self.texture_warning_x_2 = ray.load_texture('Graphics\\lumendata\\attract\\keikoku\\keikoku_img00015.png')
self.sound_bachi_swipe = ray.load_sound('Sounds\\title\\SE_ATTRACT_2.ogg') self.sound_bachi_swipe = ray.load_sound('Sounds\\title\\SE_ATTRACT_2.ogg')
self.sound_bachi_hit = ray.load_sound('Sounds\\title\\SE_ATTRACT_3.ogg') self.sound_bachi_hit = ray.load_sound('Sounds\\title\\SE_ATTRACT_3.ogg')
self.sound_warning_message = ray.load_sound('Sounds\\title\\VO_ATTRACT_3.ogg')
self.sound_warning_error = ray.load_sound('Sounds\\title\\SE_ATTRACT_1.ogg')
def animation_manager(self): self.texture_black = ray.load_texture('Graphics\\lumendata\\attract\\movie\\movie_img00000.png')
if self.warning is not None:
self.warning.update(get_current_ms(), self)
def update(self): def scene_manager(self):
self.animation_manager()
if self.op_video is not None: if self.op_video is not None:
self.scene = 'Opening Video'
self.op_video.update() self.op_video.update()
if all(self.op_video.is_finished): if all(self.op_video.is_finished):
self.op_video = None self.op_video = None
self.warning = WarningBoard(get_current_ms(), self) self.warning = WarningBoard(get_current_ms(), self)
elif self.warning is not None:
self.scene = 'Warning Board'
self.warning.update(get_current_ms(), self)
if self.warning.is_finished:
self.warning = None
self.current_attract_video = random.choice(self.attract_videos)
elif self.current_attract_video is not None:
self.scene = 'Attract Video'
self.current_attract_video.update()
if all(self.current_attract_video.is_finished):
self.current_attract_video = None
self.op_video = VideoPlayer('Videos\\OP.mp4')
def update(self):
self.scene_manager()
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER): if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
return "ENTRY" return "ENTRY"
return None return None
def draw_animation(self):
if self.warning is not None:
self.warning.draw(self)
def draw(self): def draw(self):
if self.op_video is not None: if self.op_video is not None:
self.op_video.draw() self.op_video.draw()
return elif self.warning is not None:
bg_source = ray.Rectangle(0, 0, self.texture_bg.width, self.texture_bg.height) bg_source = ray.Rectangle(0, 0, self.texture_bg.width, self.texture_bg.height)
bg_dest = ray.Rectangle(0, 0, self.width, self.height) bg_dest = ray.Rectangle(0, 0, self.width, self.height)
ray.draw_texture_pro(self.texture_bg, bg_source, bg_dest, ray.Vector2(0,0), 0, ray.WHITE) ray.draw_texture_pro(self.texture_bg, bg_source, bg_dest, ray.Vector2(0,0), 0, ray.WHITE)
self.draw_animation() self.warning.draw(self)
elif self.current_attract_video is not None:
self.current_attract_video.draw()
ray.draw_text(f"Scene: {self.scene}", 20, 40, 20, ray.BLUE)
class WarningBoard: class WarningBoard:
def __init__(self, current_ms, title_screen): def __init__(self, current_ms, title_screen):
self.start_ms = current_ms self.start_ms = current_ms
self.error_time = 4250
self.move_animation_1 = Animation(current_ms, 266.67, 'move') self.move_animation_1 = Animation(current_ms, 266.67, 'move')
self.move_animation_1.params['start_position'] = -720 self.move_animation_1.params['start_position'] = -720
self.move_animation_1.params['total_distance'] = title_screen.height + ((title_screen.height - title_screen.texture_warning.height)//2) + 20 self.move_animation_1.params['total_distance'] = title_screen.height + ((title_screen.height - title_screen.texture_warning.height)//2) + 20
@@ -83,22 +114,104 @@ class WarningBoard:
self.fade_animation_1.params['delay'] = 266.67 self.fade_animation_1.params['delay'] = 266.67
self.fade_animation_1.params['initial_opacity'] = 0.0 self.fade_animation_1.params['initial_opacity'] = 0.0
self.fade_animation_1.params['final_opacity'] = 1.0 self.fade_animation_1.params['final_opacity'] = 1.0
self.fade_animation_2 = Animation(current_ms, 500, 'fade')
self.fade_animation_2.params['initial_opacity'] = 0.0
self.fade_animation_2.params['final_opacity'] = 1.0
self.fade_animation_2.params['delay'] = 500
self.fade_animation_3 = Animation(current_ms, 50, 'fade')
self.fade_animation_3.params['delay'] = 16.67
self.fade_animation_3.params['initial_opacity'] = 0.75
self.resize_animation_1 = Animation(current_ms, 166.67, 'texture_resize')
self.resize_animation_1.params['initial_size'] = 1.0
self.resize_animation_1.params['final_size'] = 1.5
self.resize_animation_1.params['delay'] = self.error_time
self.resize_animation_2 = Animation(current_ms, 166.67, 'texture_resize')
self.resize_animation_2.params['initial_size'] = 1.5
self.resize_animation_2.params['final_size'] = 1.0
self.resize_animation_2.params['delay'] = self.error_time + 166.67
self.fade_animation_4 = Animation(current_ms, 166.67, 'fade')
self.fade_animation_4.params['delay'] = self.error_time
self.fade_animation_4.params['initial_opacity'] = 0.0
self.fade_animation_4.params['final_opacity'] = 1.0
self.fade_animation_5 = Animation(current_ms, 166.67, 'fade')
self.fade_animation_5.params['delay'] = self.error_time + 166.67 + 166.67
self.fade_animation_5.params['initial_opacity'] = 1.0
self.fade_animation_5.params['final_opacity'] = 0.0
self.fade_animation_6 = Animation(current_ms, 166.67, 'fade')
self.fade_animation_6.params['delay'] = self.error_time + 166.67 + 166.67
self.fade_animation_6.params['initial_opacity'] = 0.0
self.fade_animation_6.params['final_opacity'] = 1.0
self.resize_animation_3 = Animation(current_ms, 233.34, 'texture_resize')
self.resize_animation_3.params['initial_size'] = 0.5
self.resize_animation_3.params['final_size'] = 1.5
self.fade_animation_7 = Animation(current_ms, 116.67, 'fade')
self.fade_animation_7.params['initial_opacity'] = 0.0
self.fade_animation_7.params['final_opacity'] = 1.0
self.fade_animation_8 = Animation(current_ms, 116.67, 'fade')
self.fade_animation_8.params['delay'] = 116.67
self.fade_animation_8.params['initial_opacity'] = 1.0
self.fade_animation_8.params['final_opacity'] = 0.0
self.source_rect = ray.Rectangle(0, 0, title_screen.texture_black.width, title_screen.texture_black.height)
self.dest_rect = ray.Rectangle(0, 0, title_screen.width, title_screen.height)
self.character_time = 0 self.character_time = 0
self.character_index_val = 0 self.character_index_val = 0
self.hit_played = False self.hit_played = False
self.error_played = False
self.is_finished = False
self.attract_frame_index = 0
def load_next_attract(self, title_screen):
if title_screen.current_attract_video.convert_frames_background(self.attract_frame_index) == 0:
return 0
self.attract_frame_index += 1
def update(self, current_ms, title_screen): def update(self, current_ms, title_screen):
self.move_animation_1.update(current_ms) self.move_animation_1.update(current_ms)
self.move_animation_2.update(current_ms) self.move_animation_2.update(current_ms)
self.move_animation_3.update(current_ms) self.move_animation_3.update(current_ms)
self.fade_animation_1.update(current_ms) self.fade_animation_1.update(current_ms)
self.fade_animation_2.update(current_ms)
self.fade_animation_3.update(current_ms)
self.fade_animation_4.update(current_ms)
self.fade_animation_5.update(current_ms)
self.fade_animation_6.update(current_ms)
self.resize_animation_1.update(current_ms)
self.resize_animation_2.update(current_ms)
delay = 566.67 delay = 566.67
if delay <= current_ms - self.start_ms and self.character_index(1) != 8: elapsed_time = current_ms - self.start_ms
if not ray.is_sound_playing(title_screen.sound_bachi_swipe): if self.character_index(1) != 8:
self.fade_animation_2.params['delay'] = elapsed_time + 500
if delay <= elapsed_time and not ray.is_sound_playing(title_screen.sound_bachi_swipe):
ray.play_sound(title_screen.sound_warning_message)
ray.play_sound(title_screen.sound_bachi_swipe) ray.play_sound(title_screen.sound_bachi_swipe)
elif self.character_index(1) == 8 and not self.hit_played: elif self.character_index(1) == 8:
self.hit_played = True if not self.hit_played:
ray.play_sound(title_screen.sound_bachi_hit) self.hit_played = True
ray.play_sound(title_screen.sound_bachi_hit)
self.resize_animation_3.start_ms = current_ms
self.fade_animation_8.start_ms = current_ms
self.resize_animation_3.update(current_ms)
self.fade_animation_7.update(current_ms)
self.fade_animation_8.update(current_ms)
if self.error_time + 166.67 <= elapsed_time and not self.error_played:
self.error_played = True
ray.play_sound(title_screen.sound_warning_error)
if self.fade_animation_2.is_finished:
self.is_finished = True
def character_index(self, index): def character_index(self, index):
elapsed_time = get_current_ms() - self.start_ms elapsed_time = get_current_ms() - self.start_ms
@@ -118,6 +231,8 @@ class WarningBoard:
elif elapsed_time >= delay + self.character_time: elif elapsed_time >= delay + self.character_time:
new_index = animation[self.character_index_val][index] new_index = animation[self.character_index_val][index]
self.character_index_val += 1 self.character_index_val += 1
self.fade_animation_3.start_ms = get_current_ms()
self.fade_animation_3.duration = int(animation[self.character_index_val][0])
self.character_time += animation[self.character_index_val][0] self.character_time += animation[self.character_index_val][0]
return new_index return new_index
else: else:
@@ -133,9 +248,45 @@ class WarningBoard:
ray.draw_texture(title_screen.texture_warning, 0, int(y), ray.WHITE) ray.draw_texture(title_screen.texture_warning, 0, int(y), ray.WHITE)
fade = ray.fade(ray.WHITE, self.fade_animation_1.attribute) fade = ray.fade(ray.WHITE, self.fade_animation_1.attribute)
fade_2 = ray.fade(ray.WHITE, self.fade_animation_1.attribute if self.fade_animation_1.attribute < 0.75 else 0.75) fade_2 = ray.fade(ray.WHITE, self.fade_animation_1.attribute if self.fade_animation_1.attribute < 0.75 else 0.75)
ray.draw_texture(title_screen.texture_warning_x_2, 150, 200, ray.fade(ray.WHITE, self.fade_animation_6.attribute))
ray.draw_texture(title_screen.texture_warning_ch1_base, 135, int(y)+title_screen.texture_warning_ch1[0].height+110, fade_2) ray.draw_texture(title_screen.texture_warning_ch1_base, 135, int(y)+title_screen.texture_warning_ch1[0].height+110, fade_2)
ray.draw_texture(title_screen.texture_warning_ch1[self.character_index(2)], 115, int(y)+150, fade) ray.draw_texture(title_screen.texture_warning_ch1[self.character_index(2)], 115, int(y)+150, fade)
ray.draw_texture(title_screen.texture_warning_ch2_base, 360, int(y)+title_screen.texture_warning_ch2[0].height+60, fade_2) ray.draw_texture(title_screen.texture_warning_ch2_base, 360, int(y)+title_screen.texture_warning_ch2[0].height+60, fade_2)
if 0 < self.character_index(1):
ray.draw_texture(title_screen.texture_warning_ch2[self.character_index(1)-1], 315, int(y)+100, ray.fade(ray.WHITE, self.fade_animation_3.attribute))
ray.draw_texture(title_screen.texture_warning_ch2[self.character_index(1)], 315, int(y)+100, fade) ray.draw_texture(title_screen.texture_warning_ch2[self.character_index(1)], 315, int(y)+100, fade)
if self.character_index(1) == 8: if self.character_index(1) == 8:
ray.draw_texture(title_screen.texture_warning_bachi, 350, int(y)+135, ray.WHITE) ray.draw_texture(title_screen.texture_warning_bachi, 350, int(y)+135, ray.WHITE)
if self.resize_animation_1.is_finished:
scale = self.resize_animation_2.attribute
width = title_screen.texture_warning_x_1.width
height = title_screen.texture_warning_x_1.height
x_x = 150 + (width//2) - ((width * scale)//2)
x_y = 200 + (height//2) - ((height * scale)//2)
fade = ray.fade(ray.WHITE, self.fade_animation_5.attribute)
else:
scale = self.resize_animation_1.attribute
width = title_screen.texture_warning_x_1.width
height = title_screen.texture_warning_x_1.height
x_x = 150 + (width//2) - ((width * scale)//2)
x_y = 200 + (height//2) - ((height * scale)//2)
fade = ray.fade(ray.WHITE, self.fade_animation_4.attribute)
x_source = ray.Rectangle(0, 0, width, height)
x_dest = ray.Rectangle(x_x, x_y, width*scale, height*scale)
ray.draw_texture_pro(title_screen.texture_warning_x_1, x_source, x_dest, ray.Vector2(0,0), 0, fade)
scale = self.resize_animation_3.attribute
width = title_screen.texture_warning_bachi_hit.width
height = title_screen.texture_warning_bachi_hit.height
hit_x = 350 + (width//2) - ((width * scale)//2)
hit_y = 225 + (height//2) - ((height * scale)//2)
hit_source = ray.Rectangle(0, 0, width, height)
hit_dest = ray.Rectangle(hit_x, hit_y, width*scale, height*scale)
if self.fade_animation_7.is_finished:
fade = ray.fade(ray.WHITE, self.fade_animation_8.attribute)
else:
fade = ray.fade(ray.WHITE, self.fade_animation_7.attribute)
ray.draw_texture_pro(title_screen.texture_warning_bachi_hit, hit_source, hit_dest, ray.Vector2(0,0), 0, fade)
ray.draw_texture_pro(title_screen.texture_black, self.source_rect, self.dest_rect, ray.Vector2(0,0), 0, ray.fade(ray.WHITE, self.fade_animation_2.attribute))