From d8d1400cfc20e5caeaa664e1935da67fbeb2eaee Mon Sep 17 00:00:00 2001 From: Nick Koirala Date: Mon, 1 Dec 2025 23:37:33 +1300 Subject: [PATCH] feat: timing and animation --- lucksmith.lua | 178 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 136 insertions(+), 42 deletions(-) diff --git a/lucksmith.lua b/lucksmith.lua index 7a1e372..213c2e0 100644 --- a/lucksmith.lua +++ b/lucksmith.lua @@ -747,6 +747,7 @@ phase = "choose" phase_time = 0 roll_text = "" damage_applied = false +clash_shown = false current_damage = { player = 0, enemy = 0 @@ -1098,6 +1099,79 @@ enemy_cards = {{ end }} +function sword_clash_animation(player_total, enemy_total) + local clash_position = 120 -- Center of the screen for the clash + local player_start = 50 -- Starting x-position for player swords + local enemy_start = 190 -- Starting x-position for enemy swords + local y_position = 90 -- Y-position for the swords + local sword_speed = 1 -- Speed of sword movement per frame + + -- Initialize sword positions + local player_sword_positions = {} + local enemy_sword_positions = {} + + for i = 1, player_total do + table.insert(player_sword_positions, player_start + (i - 1) * 8) + end + + for i = 1, enemy_total do + table.insert(enemy_sword_positions, enemy_start - (i - 1) * 8) + end + + -- Animate swords moving toward the center + while #player_sword_positions > 0 and #enemy_sword_positions > 0 do + cls(0) -- Clear the screen + + -- Move player swords + for i = #player_sword_positions, 1, -1 do + local x = player_sword_positions[i] + if x + sword_speed < clash_position then + player_sword_positions[i] = x + sword_speed + spr(21, player_sword_positions[i], y_position, 0) + else + -- Sword reaches the clash point + table.remove(player_sword_positions, i) + table.remove(enemy_sword_positions, #enemy_sword_positions) -- Remove one enemy sword + spr(22, clash_position, y_position, 0) -- Explosion sprite + end + end + + -- Move enemy swords + for i = #enemy_sword_positions, 1, -1 do + local x = enemy_sword_positions[i] + if x - sword_speed > clash_position then + enemy_sword_positions[i] = x - sword_speed + spr(21, enemy_sword_positions[i], y_position, 0, 1, 1) -- Flipped horizontally + end + end + + -- Yield for the next frame + coroutine.yield() + end + + -- Pause briefly after the clash + for delay = 1, 150 do + coroutine.yield() + end + + -- Display remaining swords on the winning side + cls(0) -- Clear the screen + if #player_sword_positions > 0 then + for i = 1, #player_sword_positions do + spr(21, clash_position + (i - 1) * 8, y_position, 0) + end + elseif #enemy_sword_positions > 0 then + for i = 1, #enemy_sword_positions do + spr(21, clash_position - (i - 1) * 8, y_position, 0, 1, 1) -- Flipped horizontally + end + end + + -- Hold the final frame for a moment + for delay = 1, 30 do + coroutine.yield() + end +end + -- player's starting hand (random subset) hand = {} card_choice_options = {} -- for level up card selection @@ -1681,6 +1755,8 @@ function TIC() phase = "choose" phase_time = 0 damage_applied = false + clash_shown = false + end elseif phase == "roll" then @@ -1697,10 +1773,12 @@ function TIC() else player.display_roll = player.roll enemy.display_roll = enemy.roll - for i = 1, player.display_roll do + local count = math.min(player.display_roll, (phase_time - 30) // 6) + local enemy_count = math.min(enemy.display_roll, (phase_time - 30) // 6) + for i = 1, count do spr(21, 50 + (i - 1) * 8, 90, 0) -- Player's dice sprites end - for i = 1, enemy.display_roll do + for i = 1, enemy_count do spr(21, 150 - (i - 1) * 8, 90, 0, 1, 1) -- Enemy's dice sprites (flipped) end end @@ -1719,55 +1797,71 @@ function TIC() spr(player_dice_sprite, 50, 60, 0, 1, 0, 0, 2, 2) -- player dice on left, 16x16 spr(enemy_dice_sprite, 150, 60, 0, 1, 0, 0, 2, 2) -- enemy dice on right, 16x16 -elseif phase == "mod" then - -- Draw the roll sprites for the player - local positive_mod = math.max(0, player.roll_mod) - local negative_mod = math.abs(math.min(0, player.roll_mod)) - local adjusted_roll = math.max(0, player.roll - negative_mod) -- Reduce roll by negative mod + elseif phase == "mod" then + -- show dice rolls as sprites + local player_dice_sprite = 256 + (player.display_roll - 1) * 2 + local enemy_dice_sprite = 288 + (enemy.display_roll - 1) * 2 + spr(player_dice_sprite, 50, 60, 0, 1, 0, 0, 2, 2) -- player dice on left, 16x16 + spr(enemy_dice_sprite, 150, 60, 0, 1, 0, 0, 2, 2) -- enemy dice on right, 16x16 + -- Draw the roll sprites for the player + local positive_mod = math.max(0, player.roll_mod) + local negative_mod = math.min(math.abs(math.min(0, player.roll_mod)), player.roll) + local adjusted_roll = math.max(0, player.roll - negative_mod) -- Reduce roll by negative mod - -- Draw adjusted roll (sprite #21) - for i = 1, adjusted_roll do - spr(21, 50 + (i - 1) * 8, 90, 0) -- Player's dice sprites - end + -- Draw adjusted roll (sprite #21) + for i = 1, adjusted_roll do + spr(21, 50 + (i - 1) * 8, 90, 0) -- Player's dice sprites + end - -- Replace the remaining roll with negative mod (sprite #22) - for i = 1, negative_mod do - spr(22, 50 + (adjusted_roll + i - 1) * 8, 90, 0) -- Negative modifier sprite - end + -- Replace the remaining roll with negative mod (sprite #22) + for i = 1, negative_mod do + spr(22, 50 + (adjusted_roll + i - 1) * 8, 90, 0) -- Negative modifier sprite + end - -- Add positive modifiers (sprite #23) - for i = 1, positive_mod do - spr(23, 50 + (adjusted_roll + negative_mod + i - 1) * 8, 90, 0) -- Positive modifier sprite - end + -- Add positive modifiers (sprite #23) + for i = 1, positive_mod do + spr(23, 50 + (adjusted_roll + negative_mod + i - 1) * 8, 90, 0) -- Positive modifier sprite + end - -- Draw the roll sprites for the enemy - positive_mod = math.max(0, enemy.roll_mod) - negative_mod = math.abs(math.min(0, enemy.roll_mod)) - adjusted_roll = math.max(0, enemy.roll - negative_mod) -- Reduce roll by negative mod + -- Draw the roll sprites for the enemy + positive_mod = math.max(0, enemy.roll_mod) + local negative_mod = math.min(math.abs(math.min(0, enemy.roll_mod)), enemy.roll) + adjusted_roll = math.max(0, enemy.roll - negative_mod) -- Reduce roll by negative mod - -- Draw adjusted roll (sprite #21) - for i = 1, adjusted_roll do - spr(21, 150 - (i - 1) * 8, 90, 0, 1, 1) -- Enemy's dice sprites (flipped) - end + -- Draw adjusted roll (sprite #21) + for i = 1, adjusted_roll do + spr(21, 150 - (i - 1) * 8, 90, 0, 1, 1) -- Enemy's dice sprites (flipped) + end - -- Replace the remaining roll with negative mod (sprite #22) - for i = 1, negative_mod do - spr(22, 150 - (adjusted_roll + i - 1) * 8, 90, 0, 1, 1) -- Negative modifier sprite (flipped) - end + -- Replace the remaining roll with negative mod (sprite #22) + for i = 1, negative_mod do + spr(22, 150 - (adjusted_roll + i - 1) * 8, 90, 0, 1, 1) -- Negative modifier sprite (flipped) + end - -- Add positive modifiers (sprite #23) - for i = 1, positive_mod do - spr(23, 150 - (adjusted_roll + negative_mod + i - 1) * 8, 90, 0, 1, 1) -- Positive modifier sprite (flipped) - end - - -- Increment the phase time and transition to the total phase - phase_time = phase_time + 1 - if phase_time > 60 then - phase = "total" - phase_time = 0 - end + -- Add positive modifiers (sprite #23) + for i = 1, positive_mod do + spr(23, 150 - (adjusted_roll + negative_mod + i - 1) * 8, 90, 0, 1, 1) -- Positive modifier sprite (flipped) + end + -- Increment the phase time and transition to the total phase + phase_time = phase_time + 1 + if phase_time > 60 then + phase = "total" + phase_time = 0 + end elseif phase == "total" then + -- show dice rolls as sprites + local player_dice_sprite = 256 + (player.display_roll - 1) * 2 + local enemy_dice_sprite = 288 + (enemy.display_roll - 1) * 2 + spr(player_dice_sprite, 50, 60, 0, 1, 0, 0, 2, 2) -- player dice on left, 16x16 + spr(enemy_dice_sprite, 150, 60, 0, 1, 0, 0, 2, 2) -- enemy dice on right, 16x16 + -- if not clash_shown then + -- clash_shown = true + -- queue_effect(function() + -- sword_clash_animation(player.total, enemy.total) + -- end, 0) + + -- end -- Show total result using sprite #21 for i = 1, player.total do spr(21, 50 + (i - 1) * 8, 90, 0) -- Player's total