add balloon pop rainbow

This commit is contained in:
Anthony Samms
2025-09-08 17:54:32 -04:00
parent f80dc77455
commit ffa0005f6b
4 changed files with 49 additions and 9 deletions

View File

@@ -85,7 +85,7 @@ def main():
if global_data.config["video"]["fullscreen"]: if global_data.config["video"]["fullscreen"]:
ray.toggle_fullscreen() ray.toggle_fullscreen()
current_screen = Screens.LOADING current_screen = Screens.GAME
audio.init_audio_device() audio.init_audio_device()

View File

@@ -4,7 +4,7 @@ import os
import tempfile import tempfile
import zipfile import zipfile
from pathlib import Path from pathlib import Path
from typing import Union from typing import Optional, Union
import pyray as ray import pyray as ray
@@ -159,7 +159,7 @@ class TextureWrapper:
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(self, subset: str, texture: str, color: ray.Color=ray.WHITE, frame: int = 0, scale: float = 1.0, center: bool = False,
mirror: str = '', x: float = 0, y: float = 0, x2: float = 0, y2: float = 0, 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, origin: ray.Vector2 = ray.Vector2(0,0), rotation: float = 0, fade: float = 1.1,
index: int = 0) -> None: index: int = 0, src: Optional[ray.Rectangle] = None) -> None:
mirror_x = -1 if mirror == 'horizontal' else 1 mirror_x = -1 if mirror == 'horizontal' else 1
mirror_y = -1 if mirror == 'vertical' else 1 mirror_y = -1 if mirror == 'vertical' else 1
if fade != 1.1: if fade != 1.1:
@@ -167,6 +167,9 @@ class TextureWrapper:
else: else:
final_color = color final_color = color
tex_object = self.textures[subset][texture] tex_object = self.textures[subset][texture]
if src is not None:
source_rect = src
else:
source_rect = ray.Rectangle(0, 0, tex_object.width * mirror_x, tex_object.height * mirror_y) source_rect = ray.Rectangle(0, 0, tex_object.width * mirror_x, tex_object.height * mirror_y)
if center: 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) 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)

View File

@@ -43,6 +43,7 @@ class GameScreen:
self.end_ms = 0 self.end_ms = 0
self.start_delay = 1000 self.start_delay = 1000
self.song_started = False self.song_started = False
self.mask_shader = ray.load_shader("", "shader/mask.fs")
def load_sounds(self): def load_sounds(self):
sounds_dir = Path("Sounds") sounds_dir = Path("Sounds")
@@ -86,6 +87,8 @@ class GameScreen:
self.movie = None self.movie = None
self.song_music = None self.song_music = None
tex.load_screen_textures('game') tex.load_screen_textures('game')
ray.set_shader_value_texture(self.mask_shader, ray.get_shader_location(self.mask_shader, "texture0"), tex.textures['balloon']['rainbow_mask'].texture)
ray.set_shader_value_texture(self.mask_shader, ray.get_shader_location(self.mask_shader, "texture1"), tex.textures['balloon']['rainbow'].texture)
self.load_sounds() self.load_sounds()
self.init_tja(global_data.selected_song, session_data.selected_difficulty) self.init_tja(global_data.selected_song, session_data.selected_difficulty)
self.song_info = SongInfo(session_data.song_title, 'TEST') self.song_info = SongInfo(session_data.song_title, 'TEST')
@@ -372,14 +375,14 @@ class Player:
self.max_combo = self.combo self.max_combo = self.combo
if note.type != 9: if note.type != 9:
self.draw_arc_list.append(NoteArc(note.type, get_current_ms(), 1, note.type == 3 or note.type == 4) or note.type == 7) self.draw_arc_list.append(NoteArc(note.type, get_current_ms(), 1, note.type == 3 or note.type == 4 or note.type == 7, note.type == 7))
if note in self.current_notes_draw: if note in self.current_notes_draw:
index = self.current_notes_draw.index(note) index = self.current_notes_draw.index(note)
self.current_notes_draw.pop(index) self.current_notes_draw.pop(index)
def check_drumroll(self, drum_type: int, game_screen: GameScreen): def check_drumroll(self, drum_type: int, game_screen: GameScreen):
self.draw_arc_list.append(NoteArc(drum_type, get_current_ms(), 1, drum_type == 3 or drum_type == 4)) self.draw_arc_list.append(NoteArc(drum_type, get_current_ms(), 1, drum_type == 3 or drum_type == 4, False))
self.curr_drumroll_count += 1 self.curr_drumroll_count += 1
self.total_drumroll += 1 self.total_drumroll += 1
game_screen.background.add_renda() game_screen.background.add_renda()
@@ -711,7 +714,7 @@ class Player:
if self.drumroll_counter is not None: if self.drumroll_counter is not None:
self.drumroll_counter.draw() self.drumroll_counter.draw()
for anim in self.draw_arc_list: for anim in self.draw_arc_list:
anim.draw() anim.draw(game_screen)
for anim in self.gauge_hit_effect: for anim in self.gauge_hit_effect:
anim.draw() anim.draw()
if self.balloon_anim is not None: if self.balloon_anim is not None:
@@ -877,10 +880,12 @@ class GaugeHitEffect:
tex.draw_texture('gauge', 'hit_effect_circle', color=self.color) tex.draw_texture('gauge', 'hit_effect_circle', color=self.color)
class NoteArc: class NoteArc:
def __init__(self, note_type: int, current_ms: float, player_number: int, big: bool): def __init__(self, note_type: int, current_ms: float, player_number: int, big: bool, is_balloon: bool):
self.note_type = note_type self.note_type = note_type
self.is_big = big self.is_big = big
self.is_balloon = is_balloon
self.arc_points = 22 self.arc_points = 22
self.current_progress = 0
self.create_ms = current_ms self.create_ms = current_ms
self.player_number = player_number self.player_number = player_number
curve_height = 425 curve_height = 425
@@ -939,6 +944,8 @@ class NoteArc:
ms_since_call = (current_ms - self.create_ms) / 16.67 ms_since_call = (current_ms - self.create_ms) / 16.67
ms_since_call = max(0, min(ms_since_call, self.arc_points)) ms_since_call = max(0, min(ms_since_call, self.arc_points))
self.current_progress = ms_since_call / self.arc_points
# Calculate desired distance along the path (constant speed) # Calculate desired distance along the path (constant speed)
target_distance = (ms_since_call / self.arc_points) * self.total_path_length target_distance = (ms_since_call / self.arc_points) * self.total_path_length
@@ -962,7 +969,21 @@ class NoteArc:
self.x_i = self.end_x self.x_i = self.end_x
self.y_i = self.end_y self.y_i = self.end_y
def draw(self): def draw(self, game_screen: GameScreen):
if self.is_balloon:
rainbow = tex.textures['balloon']['rainbow']
trail_length_ratio = 0.5
trail_start_progress = max(0, self.current_progress - trail_length_ratio)
trail_end_progress = self.current_progress
if trail_end_progress > trail_start_progress:
crop_start_x = int(trail_start_progress * rainbow.width)
crop_end_x = int(trail_end_progress * rainbow.width)
crop_width = crop_end_x - crop_start_x
if crop_width > 0:
src = ray.Rectangle(crop_start_x, 0, crop_width, rainbow.height)
ray.begin_shader_mode(game_screen.mask_shader)
tex.draw_texture('balloon', 'rainbow_mask', src=src, x=crop_start_x, x2=-rainbow.width + crop_width)
ray.end_shader_mode()
tex.draw_texture('notes', str(self.note_type), x=self.x_i, y=self.y_i) tex.draw_texture('notes', str(self.note_type), x=self.x_i, y=self.y_i)
class DrumrollCounter: class DrumrollCounter:

16
shader/mask.fs Normal file
View File

@@ -0,0 +1,16 @@
#version 330
in vec2 fragTexCoord;
out vec4 fragColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main() {
vec4 maskColor = texture(texture0, fragTexCoord);
vec4 rainbowColor = texture(texture1, fragTexCoord);
if (maskColor.a > 0.0) {
fragColor = rainbowColor;
} else {
fragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
}