mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 19:50:12 +01:00
add kusudamas
This commit is contained in:
@@ -185,6 +185,10 @@ class TextureChangeAnimation(BaseAnimation):
|
|||||||
self.delay_saved = delay
|
self.delay_saved = delay
|
||||||
self.attribute = textures[0][2]
|
self.attribute = textures[0][2]
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
super().reset()
|
||||||
|
self.attribute = self.textures[0][2]
|
||||||
|
|
||||||
def update(self, current_time_ms: float) -> None:
|
def update(self, current_time_ms: float) -> None:
|
||||||
super().update(current_time_ms)
|
super().update(current_time_ms)
|
||||||
if not self.is_started:
|
if not self.is_started:
|
||||||
@@ -231,6 +235,7 @@ class TextureResizeAnimation(BaseAnimation):
|
|||||||
self.reverse_delay_saved = reverse_delay
|
self.reverse_delay_saved = reverse_delay
|
||||||
self.ease_in = ease_in
|
self.ease_in = ease_in
|
||||||
self.ease_out = ease_out
|
self.ease_out = ease_out
|
||||||
|
self.attribute = self.initial_size
|
||||||
|
|
||||||
def restart(self) -> None:
|
def restart(self) -> None:
|
||||||
super().restart()
|
super().restart()
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ class Balloon(Note):
|
|||||||
_source_note: Note
|
_source_note: Note
|
||||||
count: int = field(init=False)
|
count: int = field(init=False)
|
||||||
popped: bool = False
|
popped: bool = False
|
||||||
|
is_kusudama: bool = False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self.__dict__)
|
return str(self.__dict__)
|
||||||
@@ -574,11 +575,14 @@ class TJAParser:
|
|||||||
if item in {'5', '6'}:
|
if item in {'5', '6'}:
|
||||||
note = Drumroll(note)
|
note = Drumroll(note)
|
||||||
note.color = 255
|
note.color = 255
|
||||||
elif item in {'7'}:
|
elif item in {'7', '9'}:
|
||||||
count += 1
|
count += 1
|
||||||
if balloon is None:
|
if balloon is None:
|
||||||
raise Exception("Balloon note found, but no count was specified")
|
raise Exception("Balloon note found, but no count was specified")
|
||||||
note = Balloon(note)
|
if item == '9':
|
||||||
|
note = Balloon(note, is_kusudama=True)
|
||||||
|
else:
|
||||||
|
note = Balloon(note)
|
||||||
note.count = 1 if not balloon else balloon.pop(0)
|
note.count = 1 if not balloon else balloon.pop(0)
|
||||||
elif item == '8':
|
elif item == '8':
|
||||||
new_pixels_per_ms = play_note_list[-1].pixels_per_frame_x / (1000 / 60)
|
new_pixels_per_ms = play_note_list[-1].pixels_per_frame_x / (1000 / 60)
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import pyray as ray
|
import pyray as ray
|
||||||
|
|
||||||
from libs.utils import session_data
|
from libs.texture import tex
|
||||||
|
from libs.utils import (
|
||||||
|
get_current_ms,
|
||||||
|
is_l_don_pressed,
|
||||||
|
is_l_kat_pressed,
|
||||||
|
is_r_don_pressed,
|
||||||
|
is_r_kat_pressed,
|
||||||
|
)
|
||||||
|
from scenes.game import KusudamaAnimation
|
||||||
|
|
||||||
|
|
||||||
class DevScreen:
|
class DevScreen:
|
||||||
@@ -12,20 +20,35 @@ class DevScreen:
|
|||||||
def on_screen_start(self):
|
def on_screen_start(self):
|
||||||
if not self.screen_init:
|
if not self.screen_init:
|
||||||
self.screen_init = True
|
self.screen_init = True
|
||||||
|
tex.load_screen_textures('game')
|
||||||
|
self.kusudama = None
|
||||||
|
self.count = 0
|
||||||
|
|
||||||
def on_screen_end(self, next_screen: str):
|
def on_screen_end(self, next_screen: str):
|
||||||
self.screen_init = False
|
self.screen_init = False
|
||||||
session_data.prev_score = 10000
|
|
||||||
session_data.result_score = 100000
|
|
||||||
return next_screen
|
return next_screen
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.on_screen_start()
|
self.on_screen_start()
|
||||||
|
if self.kusudama is not None:
|
||||||
|
self.kusudama.update(get_current_ms(), self.count == 100)
|
||||||
|
if self.kusudama.is_finished:
|
||||||
|
self.kusudama = None
|
||||||
|
if is_l_kat_pressed() or is_r_kat_pressed():
|
||||||
|
self.kusudama = KusudamaAnimation(100)
|
||||||
|
self.count = 0
|
||||||
|
|
||||||
|
if is_l_don_pressed() or is_r_don_pressed():
|
||||||
|
if self.kusudama is not None:
|
||||||
|
self.count += 1
|
||||||
|
self.kusudama.update_count(self.count)
|
||||||
|
|
||||||
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
|
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
|
||||||
return self.on_screen_end('RESULT')
|
return self.on_screen_end('RESULT')
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
pass
|
if self.kusudama is not None:
|
||||||
|
self.kusudama.draw()
|
||||||
|
|
||||||
def draw_3d(self):
|
def draw_3d(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
105
scenes/game.py
105
scenes/game.py
@@ -44,6 +44,7 @@ class GameScreen:
|
|||||||
self.sound_kat = audio.load_sound(sounds_dir / "inst_00_katsu.wav")
|
self.sound_kat = audio.load_sound(sounds_dir / "inst_00_katsu.wav")
|
||||||
self.sound_restart = audio.load_sound(sounds_dir / 'song_select' / 'Skip.ogg')
|
self.sound_restart = audio.load_sound(sounds_dir / 'song_select' / 'Skip.ogg')
|
||||||
self.sound_balloon_pop = audio.load_sound(sounds_dir / "balloon_pop.wav")
|
self.sound_balloon_pop = audio.load_sound(sounds_dir / "balloon_pop.wav")
|
||||||
|
self.sound_kusudama_pop = audio.load_sound(sounds_dir / "kusudama_pop.ogg")
|
||||||
self.sound_result_transition = audio.load_sound(sounds_dir / "result" / "VO_RESULT [1].ogg")
|
self.sound_result_transition = audio.load_sound(sounds_dir / "result" / "VO_RESULT [1].ogg")
|
||||||
|
|
||||||
def init_tja(self, song: Path, difficulty: int):
|
def init_tja(self, song: Path, difficulty: int):
|
||||||
@@ -233,6 +234,7 @@ class Player:
|
|||||||
self.draw_drum_hit_list: list[DrumHitEffect] = []
|
self.draw_drum_hit_list: list[DrumHitEffect] = []
|
||||||
self.drumroll_counter: Optional[DrumrollCounter] = None
|
self.drumroll_counter: Optional[DrumrollCounter] = None
|
||||||
self.balloon_anim: Optional[BalloonAnimation] = None
|
self.balloon_anim: Optional[BalloonAnimation] = None
|
||||||
|
self.kusudama_anim: Optional[KusudamaAnimation] = None
|
||||||
self.base_score_list: list[ScoreCounterAnimation] = []
|
self.base_score_list: list[ScoreCounterAnimation] = []
|
||||||
self.combo_display = Combo(self.combo, get_current_ms())
|
self.combo_display = Combo(self.combo, get_current_ms())
|
||||||
self.score_counter = ScoreCounter(self.score)
|
self.score_counter = ScoreCounter(self.score)
|
||||||
@@ -307,7 +309,7 @@ class Player:
|
|||||||
elif (note.hit_ms <= game_screen.current_ms):
|
elif (note.hit_ms <= game_screen.current_ms):
|
||||||
if note.type == 5 or note.type == 6:
|
if note.type == 5 or note.type == 6:
|
||||||
self.is_drumroll = True
|
self.is_drumroll = True
|
||||||
elif note.type == 7:
|
elif note.type == 7 or note.type == 9:
|
||||||
self.is_balloon = True
|
self.is_balloon = True
|
||||||
|
|
||||||
def draw_note_manager(self, game_screen: GameScreen):
|
def draw_note_manager(self, game_screen: GameScreen):
|
||||||
@@ -353,7 +355,8 @@ class Player:
|
|||||||
if self.combo > self.max_combo:
|
if self.combo > self.max_combo:
|
||||||
self.max_combo = self.combo
|
self.max_combo = self.combo
|
||||||
|
|
||||||
self.draw_arc_list.append(NoteArc(note.type, get_current_ms(), 1, note.type == 3 or note.type == 4) or note.type == 7)
|
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)
|
||||||
|
|
||||||
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)
|
||||||
@@ -372,6 +375,9 @@ class Player:
|
|||||||
def check_balloon(self, game_screen: GameScreen, drum_type: int, note: Balloon):
|
def check_balloon(self, game_screen: GameScreen, drum_type: int, note: Balloon):
|
||||||
if drum_type != 1:
|
if drum_type != 1:
|
||||||
return
|
return
|
||||||
|
if note.is_kusudama:
|
||||||
|
self.check_kusudama(game_screen, note)
|
||||||
|
return
|
||||||
if self.balloon_anim is None:
|
if self.balloon_anim is None:
|
||||||
self.balloon_anim = BalloonAnimation(get_current_ms(), note.count)
|
self.balloon_anim = BalloonAnimation(get_current_ms(), note.count)
|
||||||
self.curr_balloon_count += 1
|
self.curr_balloon_count += 1
|
||||||
@@ -385,6 +391,18 @@ class Player:
|
|||||||
audio.play_sound(game_screen.sound_balloon_pop)
|
audio.play_sound(game_screen.sound_balloon_pop)
|
||||||
self.note_correct(self.play_notes[0])
|
self.note_correct(self.play_notes[0])
|
||||||
|
|
||||||
|
def check_kusudama(self, game_screen: GameScreen, note: Balloon):
|
||||||
|
if self.kusudama_anim is None:
|
||||||
|
self.kusudama_anim = KusudamaAnimation(note.count)
|
||||||
|
self.curr_balloon_count += 1
|
||||||
|
self.total_drumroll += 1
|
||||||
|
self.score += 100
|
||||||
|
self.base_score_list.append(ScoreCounterAnimation(self.player_number, 100))
|
||||||
|
if self.curr_balloon_count == note.count:
|
||||||
|
audio.play_sound(game_screen.sound_kusudama_pop)
|
||||||
|
self.is_balloon = False
|
||||||
|
note.popped = True
|
||||||
|
|
||||||
def check_note(self, game_screen: GameScreen, drum_type: int):
|
def check_note(self, game_screen: GameScreen, drum_type: int):
|
||||||
if len(self.play_notes) == 0:
|
if len(self.play_notes) == 0:
|
||||||
return
|
return
|
||||||
@@ -453,6 +471,11 @@ class Player:
|
|||||||
self.balloon_anim.update(get_current_ms(), self.curr_balloon_count, not self.is_balloon)
|
self.balloon_anim.update(get_current_ms(), self.curr_balloon_count, not self.is_balloon)
|
||||||
if self.balloon_anim.is_finished:
|
if self.balloon_anim.is_finished:
|
||||||
self.balloon_anim = None
|
self.balloon_anim = None
|
||||||
|
if self.kusudama_anim is not None:
|
||||||
|
self.kusudama_anim.update(get_current_ms(), not self.is_balloon)
|
||||||
|
self.kusudama_anim.update_count(self.curr_balloon_count)
|
||||||
|
if self.kusudama_anim.is_finished:
|
||||||
|
self.kusudama_anim = None
|
||||||
|
|
||||||
def handle_input(self, game_screen: GameScreen):
|
def handle_input(self, game_screen: GameScreen):
|
||||||
input_checks = [
|
input_checks = [
|
||||||
@@ -494,9 +517,9 @@ class Player:
|
|||||||
self.draw_drum_hit_list.append(DrumHitEffect(hit_type, self.autoplay_hit_side))
|
self.draw_drum_hit_list.append(DrumHitEffect(hit_type, self.autoplay_hit_side))
|
||||||
audio.play_sound(game_screen.sound_don)
|
audio.play_sound(game_screen.sound_don)
|
||||||
type = note.type
|
type = note.type
|
||||||
if type == 6 or type == 9:
|
if type == 6:
|
||||||
type = 3
|
type = 3
|
||||||
elif type == 5 or type == 7:
|
else:
|
||||||
type = 1
|
type = 1
|
||||||
self.check_note(game_screen, type)
|
self.check_note(game_screen, type)
|
||||||
else:
|
else:
|
||||||
@@ -557,7 +580,7 @@ class Player:
|
|||||||
if is_big:
|
if is_big:
|
||||||
tex.draw_texture('notes', "drumroll_big_tail", x=end_position, y=192, color=color)
|
tex.draw_texture('notes', "drumroll_big_tail", x=end_position, y=192, color=color)
|
||||||
else:
|
else:
|
||||||
tex.draw_texture('notes', "9", frame=0, x=end_position, y=192, color=color)
|
tex.draw_texture('notes', "drumroll_tail", x=end_position, y=192, color=color)
|
||||||
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=192, color=color)
|
tex.draw_texture('notes', str(head.type), frame=current_eighth % 2, x=start_position, y=192, color=color)
|
||||||
|
|
||||||
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + 60, y=323, x2=length)
|
tex.draw_texture('notes', 'moji_drumroll_mid', x=start_position + 60, y=323, x2=length)
|
||||||
@@ -617,7 +640,7 @@ class Player:
|
|||||||
y_position = self.get_position_y(game_screen.current_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
|
y_position = self.get_position_y(game_screen.current_ms, note.load_ms, note.pixels_per_frame_y, note.pixels_per_frame_x)
|
||||||
if isinstance(note, Drumroll):
|
if isinstance(note, Drumroll):
|
||||||
self.draw_drumroll(game_screen, note, current_eighth)
|
self.draw_drumroll(game_screen, note, current_eighth)
|
||||||
elif isinstance(note, Balloon):
|
elif isinstance(note, Balloon) and not note.is_kusudama:
|
||||||
self.draw_balloon(game_screen, note, current_eighth)
|
self.draw_balloon(game_screen, note, current_eighth)
|
||||||
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
tex.draw_texture('notes', 'moji', frame=note.moji, x=x_position - (168//2) + 64, y=323 + y_position)
|
||||||
else:
|
else:
|
||||||
@@ -652,6 +675,8 @@ class Player:
|
|||||||
anim.draw()
|
anim.draw()
|
||||||
if self.balloon_anim is not None:
|
if self.balloon_anim is not None:
|
||||||
self.balloon_anim.draw()
|
self.balloon_anim.draw()
|
||||||
|
if self.kusudama_anim is not None:
|
||||||
|
self.kusudama_anim.draw()
|
||||||
self.score_counter.draw()
|
self.score_counter.draw()
|
||||||
for anim in self.base_score_list:
|
for anim in self.base_score_list:
|
||||||
anim.draw()
|
anim.draw()
|
||||||
@@ -980,6 +1005,74 @@ class BalloonAnimation:
|
|||||||
for i in range(len(counter)):
|
for i in range(len(counter)):
|
||||||
tex.draw_texture('balloon', 'counter', frame=int(counter[i]), color=self.color, x=-(total_width // 2) + (i * 52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
tex.draw_texture('balloon', 'counter', frame=int(counter[i]), color=self.color, x=-(total_width // 2) + (i * 52), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||||
|
|
||||||
|
class KusudamaAnimation:
|
||||||
|
def __init__(self, balloon_total: int):
|
||||||
|
self.balloon_total = balloon_total
|
||||||
|
self.move_down = tex.get_animation(11)
|
||||||
|
self.move_up = tex.get_animation(12)
|
||||||
|
self.renda_move_up = tex.get_animation(13)
|
||||||
|
self.renda_move_down = tex.get_animation(18)
|
||||||
|
self.renda_fade_in = tex.get_animation(14)
|
||||||
|
self.renda_fade_out = tex.get_animation(20)
|
||||||
|
self.stretch_animation = tex.get_animation(15)
|
||||||
|
self.breathing = tex.get_animation(16)
|
||||||
|
self.renda_breathe = tex.get_animation(17)
|
||||||
|
self.open = tex.get_animation(19)
|
||||||
|
self.fade_out = tex.get_animation(21)
|
||||||
|
self.balloon_count = 0
|
||||||
|
self.is_popped = False
|
||||||
|
self.is_finished = False
|
||||||
|
self.move_down.start()
|
||||||
|
self.move_up.start()
|
||||||
|
self.renda_move_up.start()
|
||||||
|
self.renda_move_down.start()
|
||||||
|
self.renda_fade_in.start()
|
||||||
|
self.renda_breathe.start()
|
||||||
|
|
||||||
|
self.open.reset()
|
||||||
|
self.renda_fade_out.reset()
|
||||||
|
self.fade_out.reset()
|
||||||
|
|
||||||
|
def update_count(self, balloon_count: int):
|
||||||
|
if self.balloon_count != balloon_count:
|
||||||
|
self.balloon_count = balloon_count
|
||||||
|
self.stretch_animation.start()
|
||||||
|
self.breathing.start()
|
||||||
|
|
||||||
|
def update(self, current_ms, is_popped: bool):
|
||||||
|
if is_popped and not self.is_popped:
|
||||||
|
self.is_popped = True
|
||||||
|
self.open.start()
|
||||||
|
self.renda_fade_out.start()
|
||||||
|
self.fade_out.start()
|
||||||
|
self.move_down.update(current_ms)
|
||||||
|
self.move_up.update(current_ms)
|
||||||
|
self.renda_move_up.update(current_ms)
|
||||||
|
self.renda_move_down.update(current_ms)
|
||||||
|
self.renda_fade_in.update(current_ms)
|
||||||
|
self.renda_fade_out.update(current_ms)
|
||||||
|
self.fade_out.update(current_ms)
|
||||||
|
self.stretch_animation.update(current_ms)
|
||||||
|
self.breathing.update(current_ms)
|
||||||
|
self.renda_breathe.update(current_ms)
|
||||||
|
self.open.update(current_ms)
|
||||||
|
if self.renda_breathe.is_finished:
|
||||||
|
self.renda_breathe.restart()
|
||||||
|
self.is_finished = self.fade_out.is_finished
|
||||||
|
def draw(self):
|
||||||
|
y = self.move_down.attribute - self.move_up.attribute
|
||||||
|
renda_y = -self.renda_move_up.attribute + self.renda_move_down.attribute + self.renda_breathe.attribute
|
||||||
|
tex.draw_texture('kusudama', 'kusudama', frame=self.open.attribute, y=y, scale=self.breathing.attribute, center=True, fade=self.fade_out.attribute)
|
||||||
|
tex.draw_texture('kusudama', 'renda', y=renda_y, fade=min(self.renda_fade_in.attribute, self.renda_fade_out.attribute))
|
||||||
|
|
||||||
|
if self.move_up.is_finished and not self.is_popped:
|
||||||
|
counter = str(max(0, self.balloon_total - self.balloon_count))
|
||||||
|
if counter == '0':
|
||||||
|
return
|
||||||
|
total_width = len(counter) * 150
|
||||||
|
for i in range(len(counter)):
|
||||||
|
tex.draw_texture('kusudama', 'counter', frame=int(counter[i]), x=-(total_width // 2) + (i * 150), y=-self.stretch_animation.attribute, y2=self.stretch_animation.attribute)
|
||||||
|
|
||||||
class Combo:
|
class Combo:
|
||||||
def __init__(self, combo: int, current_ms: float):
|
def __init__(self, combo: int, current_ms: float):
|
||||||
self.combo = combo
|
self.combo = combo
|
||||||
|
|||||||
Reference in New Issue
Block a user