From c1447c4de2385115e8d535b8a00432f5af63c53a Mon Sep 17 00:00:00 2001 From: Tyler Scott Date: Sat, 5 Feb 2022 07:54:33 +0700 Subject: [PATCH] Add collision detection and response --- main.lua | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/main.lua b/main.lua index 942c174..0d4bc0f 100644 --- a/main.lua +++ b/main.lua @@ -30,6 +30,25 @@ local function get_next_bubble_type(index, remaining_bubble_types) return remaining_bubble_types[love.math.random(#remaining_bubble_types)] end +local function find_nearest_slot(x, y) + local nearest_slot_index = 0 + local min_dist = math.huge + for i = 1, #game.bubble_slots do + local slot = game.bubble_slots[i] + if slot.bubble_type == 0 then + local diff_x = x - slot.x + local diff_y = y - slot.y + local dist = math.sqrt(diff_x * diff_x + diff_y * diff_y) + if dist < min_dist then + min_dist = dist + nearest_slot_index = i + end + end + end + assert(nearest_slot_index ~= 0, "no nearest slot found") + return nearest_slot_index +end + function love.load(arg) game.window_width, game.window_height = love.graphics.getDimensions() @@ -130,8 +149,69 @@ end function love.update(dt) if game.paused then return end if game.next_bubble.velocity_x ~= 0 or game.next_bubble.velocity_y ~= 0 then - game.next_bubble.x = game.next_bubble.x + game.next_bubble.velocity_x * dt - game.next_bubble.y = game.next_bubble.y + game.next_bubble.velocity_y * dt + local next_x = game.next_bubble.x + game.next_bubble.velocity_x * dt + local next_y = game.next_bubble.y + game.next_bubble.velocity_y * dt + local collision_detection_finished = false + + -- collision with ceiling + if next_y - game.bubble_radius <= game.level_top then + local nearest_slot_index = find_nearest_slot(next_x, next_y) + game.next_bubble.x = game.bubble_slots[nearest_slot_index].x + game.next_bubble.y = game.bubble_slots[nearest_slot_index].y + game.next_bubble.velocity_x = 0 + game.next_bubble.velocity_y = 0 + collision_detection_finished = true + end + + -- collision with wall + if not collision_detection_finished then + if next_x + game.bubble_radius >= game.level_right or + next_x - game.bubble_radius <= game.level_left then + local impact_x = game.level_left + game.bubble_radius + if next_x + game.bubble_radius >= game.level_right then + impact_x = game.level_right - game.bubble_radius + end + local dx = impact_x - game.next_bubble.x + local ratio = dx / game.next_bubble.velocity_x * dt + local dy = game.next_bubble.velocity_y * dt * ratio + local impact_y = game.next_bubble.y + dy + local ratio_after_bounce = 1.0 - ratio + game.next_bubble.velocity_x = -game.next_bubble.velocity_x + next_x = impact_x + game.next_bubble.velocity_x * dt * ratio_after_bounce + next_y = impact_y + game.next_bubble.velocity_y * dt * ratio_after_bounce + end + end + + -- collision with another bubble + if not collision_detection_finished then + for i = 1, #game.bubble_slots do + local slot = game.bubble_slots[i] + if slot.bubble_type ~= 0 then + local diff_x = next_x - slot.x + local diff_y = next_y - slot.y + local dist = math.sqrt(diff_x * diff_x + diff_y * diff_y) + if dist <= game.bubble_diameter then + local depth = game.bubble_diameter - dist + local direction_x = diff_x / dist + local direction_y = diff_y / dist + next_x = next_x + direction_x * depth + next_y = next_y + direction_y * depth + local nearest_slot_index = find_nearest_slot(next_x, next_y) + game.next_bubble.x = game.bubble_slots[nearest_slot_index].x + game.next_bubble.y = game.bubble_slots[nearest_slot_index].y + game.next_bubble.velocity_x = 0 + game.next_bubble.velocity_y = 0 + collision_detection_finished = true + break + end + end + end + end + + if not collision_detection_finished then + game.next_bubble.x = next_x + game.next_bubble.y = next_y + end end if game.frame_by_frame then