improve results screen

This commit is contained in:
Yonokid
2025-07-25 20:30:16 -04:00
parent 07867f3ee4
commit fc985ca410
6 changed files with 366 additions and 67 deletions

View File

@@ -1,6 +1,8 @@
import math
from pathlib import Path
import pyray as ray
from raylib import SHADER_UNIFORM_FLOAT
from libs import utils
from libs.animation import Animation
@@ -17,12 +19,17 @@ from libs.utils import (
)
class State:
FAIL = 0
CLEAR = 1
RAINBOW = 2
class ResultScreen:
def __init__(self, width: int, height: int):
self.width = width
self.height = height
self.screen_init = False
self.fade_out = None
self.alpha_shader = ray.load_shader('', 'shader/grayscale_alpha.fs')
def load_textures(self):
zip_file = Path('Graphics/lumendata/enso_result.zip')
@@ -44,8 +51,12 @@ class ResultScreen:
audio.play_sound(self.bgm)
self.fade_in = FadeIn()
self.fade_out = None
self.fade_in_bottom = None
self.gauge = None
self.score_delay = None
self.bottom_characters = BottomCharacters()
self.crown = None
self.state = None
self.score_animator = ScoreAnimator(session_data.result_score)
self.score = -1
self.good = -1
@@ -62,6 +73,10 @@ class ResultScreen:
self.update_index = 0
self.is_skipped = False
self.start_ms = get_current_ms()
if session_data.result_bad == 0:
self.crown_texture = 125
else:
self.crown_texture = 124
def on_screen_end(self):
self.screen_init = False
@@ -112,12 +127,32 @@ class ResultScreen:
self.fade_in.update(get_current_ms())
if self.fade_in.is_finished and self.gauge is None:
self.gauge = Gauge(get_current_ms(), session_data.result_gauge_length)
self.bottom_characters.start()
self.bottom_characters.update(self.state)
if self.bottom_characters.is_finished and self.crown is None:
if self.gauge is not None and self.gauge.gauge_length > 69:
self.crown = Crown()
if self.gauge is not None:
self.gauge.update(get_current_ms())
if self.gauge.is_finished and self.score_delay is None:
self.score_delay = get_current_ms() + 1883
if self.score_delay is not None:
if get_current_ms() > self.score_delay and self.fade_in_bottom is None:
self.fade_in_bottom = Animation.create_fade(333, initial_opacity=0.0, final_opacity=1.0)
if self.gauge is not None:
self.state = self.gauge.state
if self.fade_in_bottom is not None:
self.fade_in_bottom.update(get_current_ms())
alpha_loc = ray.get_shader_location(self.alpha_shader, "ext_alpha")
alpha_value = ray.ffi.new('float*', self.fade_in_bottom.attribute)
ray.set_shader_value(self.alpha_shader, alpha_loc, alpha_value, SHADER_UNIFORM_FLOAT)
if get_current_ms() >= self.start_ms + 5000:
self.handle_input()
@@ -128,6 +163,9 @@ class ResultScreen:
if self.fade_out.is_finished:
return self.on_screen_end()
if self.crown is not None:
self.crown.update(get_current_ms())
def draw_score_info(self):
if self.good > -1:
for i in range(len(str(self.good))):
@@ -146,11 +184,29 @@ class ResultScreen:
ray.draw_texture(self.textures['result'][int(str(self.total_drumroll)[::-1][i]) + 136], 1217-(i*24), 186, ray.WHITE)
def draw_total_score(self):
if self.fade_in is None:
return
if not self.fade_in.is_finished:
return
ray.draw_texture(self.textures['result'][167], 554, 236, ray.WHITE)
if self.score > -1:
for i in range(len(str(self.score))):
ray.draw_texture(self.textures['result'][int(str(self.score)[::-1][i]) + 156], 723-(i*21), 252, ray.WHITE)
def draw_bottom_textures(self):
if self.fade_in_bottom is not None:
src = ray.Rectangle(0, 0, self.textures['result'][328].width, self.textures['result'][328].height)
if self.state == State.FAIL:
dest = ray.Rectangle(0, self.height//2, self.width, self.height//2)
ray.draw_texture_pro(self.textures['result'][329], src, dest, ray.Vector2(0, 0), 0, ray.fade(ray.WHITE, min(0.4, self.fade_in_bottom.attribute)))
else:
dest = ray.Rectangle(0, self.height//2 - 72, self.width, self.height//2)
ray.begin_shader_mode(self.alpha_shader)
ray.draw_texture_pro(self.textures['result'][328], src, dest, ray.Vector2(0, 0), 0, ray.fade(ray.WHITE, self.fade_in_bottom.attribute))
ray.end_shader_mode()
self.bottom_characters.draw(self.textures['result'])
def draw(self):
x = 0
while x < self.width:
@@ -171,6 +227,10 @@ class ResultScreen:
ray.draw_texture(self.textures['result'][175], 532, 98, ray.fade(ray.WHITE, 0.75))
ray.draw_texture(self.textures['result'][233 + session_data.selected_difficulty], 289, 129, ray.WHITE)
self.draw_bottom_textures()
if self.gauge is not None:
self.gauge.draw(self.textures['result'])
@@ -183,12 +243,141 @@ class ResultScreen:
self.draw_score_info()
self.draw_total_score()
if self.crown is not None:
self.crown.draw(self.textures['result'], self.crown_texture)
if self.fade_in is not None:
self.fade_in.draw(self.width, self.height, self.textures['result'][326], self.textures['result'][327])
if self.fade_out is not None:
self.fade_out.draw(self.width, self.height)
class Crown:
def __init__(self):
duration = 466
self.resize = Animation.create_texture_resize(duration, initial_size=3.5, final_size=0.90, ease_in='quadratic')
self.resize_fix = Animation.create_texture_resize(216, initial_size=self.resize.final_size, final_size=1.0, delay=self.resize.duration)
self.white_fadein = Animation.create_fade(133, initial_opacity=0.0, final_opacity=1.0, delay=self.resize.duration + self.resize_fix.duration, reverse_delay=0)
self.gleam = Animation.create_texture_change(400, textures=[(0, 200, 0), (200, 250, 127), (250, 300, 128), (300, 350, 129), (350, 400, 0)], delay=self.resize.duration + self.resize_fix.duration + self.white_fadein.duration)
self.fadein = Animation.create_fade(duration, initial_opacity=0.0, final_opacity=1.0, ease_in='quadratic')
self.sound = audio.load_sound(Path('Sounds/result/SE_RESULT [1].ogg'))
self.sound_played = False
def update(self, current_ms: float):
self.fadein.update(current_ms)
self.resize.update(current_ms)
self.resize_fix.update(current_ms)
self.white_fadein.update(current_ms)
self.gleam.update(current_ms)
if self.resize_fix.is_finished and not self.sound_played:
audio.play_sound(self.sound)
self.sound_played = True
def draw(self, textures: list[ray.Texture], crown_index: int):
scale = self.resize.attribute
if self.resize.is_finished:
scale = self.resize_fix.attribute
texture = textures[crown_index]
x_x = 335 + (texture.width//2) - ((texture.width * scale)//2)
x_y = 150 + (texture.height//2) - ((texture.height * scale)//2)
x_source = ray.Rectangle(0, 0, texture.width, texture.height)
x_dest = ray.Rectangle(x_x, x_y, texture.width*scale, texture.height*scale)
ray.draw_texture_pro(texture, x_source, x_dest, ray.Vector2(0,0), 0, ray.fade(ray.WHITE, self.fadein.attribute))
ray.draw_texture(textures[126], int(x_x), int(x_y), ray.fade(ray.WHITE, self.white_fadein.attribute))
if self.gleam.attribute != 0:
ray.draw_texture(textures[self.gleam.attribute], int(x_x), int(x_y), ray.WHITE)
class BottomCharacters:
def __init__(self):
self.move_up = None
self.move_down = None
self.move_center = None
self.bounce_up = None
self.bounce_down = None
self.flower_up = None
self.state = None
self.flower_index = 341
self.flower_start = None
self.char_1_index = 339
self.char_2_index = 340
self.c_bounce_up = Animation.create_move(266, total_distance=40, ease_in='quadratic')
self.c_bounce_down = Animation.create_move(266, total_distance=40, ease_out='quadratic', delay=self.c_bounce_up.duration)
self.is_finished = False
def start(self):
self.move_up = Animation.create_move(366, total_distance=380, ease_out='cubic')
self.move_down = Animation.create_move(133, total_distance=30, ease_out='cubic', delay=self.move_up.duration-5)
def update(self, state):
self.state = state
if self.state == State.CLEAR or self.state == State.RAINBOW:
self.char_1_index = 345
self.char_2_index = 346
if self.bounce_up is None:
self.bounce_up = Animation.create_move(266, total_distance=40, ease_in='quadratic')
self.bounce_down = Animation.create_move(266, total_distance=40, ease_out='quadratic', delay=self.bounce_up.duration)
self.move_center = Animation.create_move(266, total_distance=450, ease_out='quadratic', delay=self.bounce_down.duration+self.bounce_up.duration)
if self.flower_up is None:
self.flower_up = Animation.create_move(333, total_distance=365, ease_out='quadratic')
self.flower_start = get_current_ms()
elif self.state == State.FAIL:
self.char_1_index = 347
self.char_2_index = 348
if self.move_up is not None:
self.move_up.update(get_current_ms())
if self.move_down is not None:
self.move_down.update(get_current_ms())
self.is_finished = self.move_down.is_finished
if self.bounce_up is not None:
self.bounce_up.update(get_current_ms())
if self.bounce_down is not None:
self.bounce_down.update(get_current_ms())
if self.bounce_down.is_finished and self.bounce_up is not None:
self.bounce_up.restart()
self.bounce_down.restart()
if self.move_center is not None:
self.move_center.update(get_current_ms())
if self.flower_up is not None:
self.flower_up.update(get_current_ms())
if self.flower_start is not None:
if get_current_ms() > self.flower_start + 116*2 + 333:
self.flower_index = 343
elif get_current_ms() > self.flower_start + 116 + 333:
self.flower_index = 342
self.c_bounce_up.update(get_current_ms())
self.c_bounce_down.update(get_current_ms())
if self.c_bounce_down.is_finished:
self.c_bounce_up.restart()
self.c_bounce_down.restart()
def draw_flowers(self, textures: list[ray.Texture]):
if self.flower_up is None:
return
y = 720+textures[self.flower_index].height - int(self.flower_up.attribute)
source_rect = ray.Rectangle(0, 0, textures[self.flower_index].width, textures[self.flower_index].height)
dest_rect = ray.Rectangle(1280-textures[self.flower_index].width, y, textures[self.flower_index].width, textures[self.flower_index].height)
source_rect.width = -textures[self.flower_index].width
ray.draw_texture_pro(textures[self.flower_index], source_rect, dest_rect, ray.Vector2(0, 0), 0, ray.WHITE)
ray.draw_texture(textures[self.flower_index], 0, y, ray.WHITE)
def draw(self, textures: list[ray.Texture]):
if self.move_up is None or self.move_down is None:
return
self.draw_flowers(textures)
y = 720 - int(self.move_up.attribute) + int(self.move_down.attribute)
if self.bounce_up is not None and self.bounce_down is not None:
y = 720 - int(self.move_up.attribute) + int(self.move_down.attribute) + int(self.bounce_up.attribute) - int(self.bounce_down.attribute)
if self.state == State.RAINBOW and self.move_center is not None:
center_y = int(self.c_bounce_up.attribute) - int(self.c_bounce_down.attribute)
ray.draw_texture(textures[344], 1280//2 - textures[344].width//2, (800 - int(self.move_center.attribute)) + int(center_y), ray.WHITE)
ray.draw_texture(textures[self.char_1_index], 125, y, ray.WHITE)
ray.draw_texture(textures[self.char_2_index], 820, y, ray.WHITE)
class FadeIn:
def __init__(self):
@@ -240,6 +429,12 @@ class Gauge:
self.rainbow_animation = None
self.gauge_fade_in = Animation.create_fade(366, initial_opacity=0.0, final_opacity=1.0)
self.is_finished = self.gauge_fade_in.is_finished
if self.gauge_length == 87:
self.state = State.RAINBOW
elif self.gauge_length > 69:
self.state = State.CLEAR
else:
self.state = State.FAIL
def _create_rainbow_anim(self, current_ms):
anim = Animation.create_texture_change((16.67*8) * 3, textures=[((16.67 * 3) * i, (16.67 * 3) * (i + 1), i) for i in range(8)])