diff options
| author | tradam <git.tradam.fyi> | 2021-08-16 11:05:47 -0400 |
|---|---|---|
| committer | tradam <git.tradam.fyi> | 2021-08-16 11:05:47 -0400 |
| commit | b4b6817a2a9fce437d83b04eb1bff55bd8c81a90 (patch) | |
| tree | 71859dac1848800a91067818bd58dd7d79df0dd8 /run.rb | |
| parent | d5ccd4ea0d174c733d3fb57f520d261aeccfb8dc (diff) | |
| download | arbitrary-polygon-collision-b4b6817a2a9fce437d83b04eb1bff55bd8c81a90.tar.gz arbitrary-polygon-collision-b4b6817a2a9fce437d83b04eb1bff55bd8c81a90.zip | |
.
Diffstat (limited to 'run.rb')
| -rw-r--r-- | run.rb | 269 |
1 files changed, 146 insertions, 123 deletions
@@ -1,6 +1,19 @@ require 'ruby2d' require 'ruby2d/camera' +# SOURCES FOR MATH USED +# here are the websites I tried to look at, understand, and implement the math from(unsuccessfully) +# +# Currently Main Source: +# http://programmerart.weebly.com/separating-axis-theorem.html +# +# Other sources read through: +# https://dyn4j.org/2010/01/sat/ +# https://www.sevenson.com.au/programming/sat/ +# +# more stuff near the bottom of this link: +# https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection + #DEBUG: used to colour all debug lines unique colours $colors = ['blue', 'teal', 'green', 'lime', 'yellow', 'orange', 'red', 'fuchsia'] @@ -19,29 +32,60 @@ class DebugLines end # The coordinates of the 2 shapes being tested for collision -sv1 = {x1: 275.0 - 275.0, y1: 175.0 - 175.0, - x2: 375.0 - 275.0, y2: 225.0 - 175.0, - x3: 300.0 - 275.0, y3: 350.0 - 175.0, - x4: 250.0 - 275.0, y4: 250.0 - 175.0} - -sv2 = {x1: 200.0, y1: 100.0, +svA = {x1: 200.0, y1: 100.0, x2: 200.0, y2: 200.0, x3: 100.0, y3: 200.0, x4: 100.0, y4: 100.0} +svB = {x1: 275.0 - 275.0, y1: 175.0 - 175.0, + x2: 375.0 - 275.0, y2: 225.0 - 175.0, + x3: 300.0 - 275.0, y3: 350.0 - 175.0, + x4: 250.0 - 275.0, y4: 250.0 - 175.0} + # The 2 shapes being tested for collision -s1 = Camera::Quad.new( - **sv1, - color: 'aqua', + +sA = Camera::Quad.new( + **svA, + color: 'olive', z: 10 ) -s2 = Camera::Quad.new( - **sv2, - color: 'olive', +sB = Camera::Quad.new( + **svB, + color: 'aqua', z: 10 ) +# The hitbox logic +def hitbox_check(shape_a, shape_b) + + # Get normals of both shapes + inverted = build_inverted_edges(shape_b) + inverted.concat(build_inverted_edges(shape_a)) + + #DEBUG + debug_outer_loop(inverted) + + inverted.each_with_index do |line, line_index| + + # Determine max and min of a and b shapes + amax, amin = calculate_minmax(shape_a, line) + bmax, bmin = calculate_minmax(shape_b, line) + + #DEBUG + debug_inner_loop(shape_a, shape_b, line_index, amax, amin, bmax, bmin) + + if (((amin <= bmax) && (amin >= bmin)) || ((bmin <= amax) && (bmin >= amin))) + #next + else + # The logic should end the calculations early once it detects lack of collision + # however for debug purposes this is disabled + #return false + end + end + true +end + # Creates edges out using coordinates and then gets the normal def build_inverted_edges(shape) edges = [] @@ -52,7 +96,7 @@ def build_inverted_edges(shape) vertex_end = shape[index + 1] end edges.push [vertex_end[1] - vertex_start[1], - -vertex_end[0] + vertex_start[0]] + -(vertex_end[0] - vertex_start[0])] end edges end @@ -62,108 +106,87 @@ def vecDotProd(a,b) return (a[0] * b[0]) + (a[1] * b[1]) end -# The hitbox logic -def hitbox_check(shape_a, shape_b) - - # Get normals of both shapes - inverted = build_inverted_edges(shape_b) - inverted.concat(build_inverted_edges(shape_a)) - - #DEBUG - if $i == 0 - puts - puts "debug of inverted edges:" - pp inverted - end - - inverted.each_with_index do |line, line_index| - - # Initialize max and min - amin = vecDotProd(shape_a.first, line) - amax = vecDotProd(shape_a.first, line) - bmin = vecDotProd(shape_b.first, line) - bmax = vecDotProd(shape_b.first, line) - - # Determine max and min of a_shape - shape_a.each_with_index do |vertex, vertex_index| - dot = vecDotProd(vertex, line) - if dot > amax - amax = dot - elsif dot < amin - amin = dot - end - end - - # Determine max and min of b_shape - shape_b.each_with_index do |vertex, vertex_index| - dot = vecDotProd(vertex, line) - if dot > bmax - bmax = dot - elsif dot < bmin - bmin = dot - end +# Calculates the minimum point and maximum point projected onto the line +def calculate_minmax(shape, line) + min = vecDotProd(shape.first, line) + max = vecDotProd(shape.first, line) + shape.each_with_index do |vertex, vertex_index| + dot = vecDotProd(vertex, line) + if dot > max + max = dot + elsif dot < min + min = dot end + end + [max, min] +end - #DEBUG: display the lines, transluscent if they are not "seperating" - # If all lines are transluscent then the logic believes the - # shapes are colliding - if line_index < shape_a.length - DebugLines[line_index].x1 = shape_a[line_index][0] - DebugLines[line_index].y1 = shape_a[line_index][1] - if shape_a[line_index].nil? - DebugLines[line_index].x2 = shape_a[line_index + 1][0] - DebugLines[line_index].y2 = shape_a[line_index + 1][1] - else - DebugLines[line_index].x2 = shape_a[0][0] - DebugLines[line_index].y2 = shape_a[0][1] - end +# Displays debug info(used inside the inverted.each loop) +def debug_inner_loop(shape_a, shape_b, line_index, amax, amin, bmax, bmin) + #DEBUG: display the lines(uninverted), transluscent if they are not "seperating" + # If all lines are transluscent then the logic believes the + # shapes are colliding + if line_index < shape_a.length + DebugLines[line_index].x1 = shape_a[line_index][0] + DebugLines[line_index].y1 = shape_a[line_index][1] + if shape_a[line_index].nil? + DebugLines[line_index].x2 = shape_a[line_index + 1][0] + DebugLines[line_index].y2 = shape_a[line_index + 1][1] else - DebugLines[line_index].x1 = shape_b[line_index - shape_a.length][0] - DebugLines[line_index].y1 = shape_b[line_index - shape_a.length][1] - if shape_a[line_index - shape_a.length + 1].nil? - DebugLines[line_index].x2 = shape_b[0][0] - DebugLines[line_index].y2 = shape_b[0][1] - else - DebugLines[line_index].x2 = shape_b[line_index - shape_a.length + 1][0] - DebugLines[line_index].y2 = shape_b[line_index - shape_a.length + 1][1] - end - end - DebugLines[line_index].color = $colors[line_index % $colors.length] - - #DEBUG: print out line information - if $i == 0 - puts - puts $colors[line_index % $colors.length] - puts line_index - puts "x1 #{DebugLines[line_index].x1}" - puts "y1 #{DebugLines[line_index].y1}" - puts "x2 #{DebugLines[line_index].x2}" - puts "y2 #{DebugLines[line_index].y2}" - puts "(((#{amin} < #{bmax}) && (#{amin} > #{bmin})) || ((#{bmin} < #{amax}) && (#{bmin} > #{amin})))" + DebugLines[line_index].x2 = shape_a[0][0] + DebugLines[line_index].y2 = shape_a[0][1] end - if (((amin <= bmax) && (amin >= bmin)) || ((bmin <= amax) && (bmin >= amin))) - DebugLines[line_index].color.a = 0.2 + else + DebugLines[line_index].x1 = shape_b[line_index - shape_a.length][0] + DebugLines[line_index].y1 = shape_b[line_index - shape_a.length][1] + if shape_a[line_index - shape_a.length + 1].nil? + DebugLines[line_index].x2 = shape_b[0][0] + DebugLines[line_index].y2 = shape_b[0][1] else - DebugLines[line_index].color.a = 1.0 - - # The logic should end the calculations early once it detects lack of collision - # however for debug purposes this is disabled - #return false + DebugLines[line_index].x2 = shape_b[line_index - shape_a.length + 1][0] + DebugLines[line_index].y2 = shape_b[line_index - shape_a.length + 1][1] end + end + DebugLines[line_index].color = $colors[line_index % $colors.length] - #DEBUG: make the debug lines effectively infinitly long - tempx1 = DebugLines[line_index].x1 - tempx2 = DebugLines[line_index].x2 - tempy1 = DebugLines[line_index].y1 - tempy2 = DebugLines[line_index].y2 - DebugLines[line_index].x1 = (tempx1 *(1+1000)/2) + (tempx2 * (1-1000)/2) - DebugLines[line_index].y1 = (tempy1 *(1+1000)/2) + (tempy2 * (1-1000)/2) - DebugLines[line_index].x2 = (tempx2 *(1+1000)/2) + (tempx1 * (1-1000)/2) - DebugLines[line_index].y2 = (tempy2 *(1+1000)/2) + (tempy1 * (1-1000)/2) + #DEBUG: print out line information + if $i == 0 + puts + puts $colors[line_index % $colors.length] + puts line_index + puts "x1 #{DebugLines[line_index].x1}" + puts "y1 #{DebugLines[line_index].y1}" + puts "x2 #{DebugLines[line_index].x2}" + puts "y2 #{DebugLines[line_index].y2}" + puts "(((#{amin} < #{bmax}) && (#{amin} > #{bmin})) || ((#{bmin} < #{amax}) && (#{bmin} > #{amin})))" end - true + if (((amin <= bmax) && (amin >= bmin)) || ((bmin <= amax) && (bmin >= amin))) + DebugLines[line_index].color.a = 0.2 + else + DebugLines[line_index].color.a = 1.0 + end + + #DEBUG: make the debug lines effectively infinitly long + tempx1 = DebugLines[line_index].x1 + tempx2 = DebugLines[line_index].x2 + tempy1 = DebugLines[line_index].y1 + tempy2 = DebugLines[line_index].y2 + DebugLines[line_index].x1 = (tempx1 *(1+1000)/2) + (tempx2 * (1-1000)/2) + DebugLines[line_index].y1 = (tempy1 *(1+1000)/2) + (tempy2 * (1-1000)/2) + DebugLines[line_index].x2 = (tempx2 *(1+1000)/2) + (tempx1 * (1-1000)/2) + DebugLines[line_index].y2 = (tempy2 *(1+1000)/2) + (tempy1 * (1-1000)/2) end +# Displays debug info(used outside the inverted.each loop) +def debug_outer_loop(inverted) + if $i == 0 + puts + puts "debug of inverted edges:" + pp inverted + end +end + + # Move camera on :key_held do |event| if event.key == 'w' @@ -193,31 +216,31 @@ update do $i %= 5 # Update shape 1 position to mouse - s1.x = Camera.coordinate_to_worldspace(get(:mouse_x),0)[0] - s1.y = Camera.coordinate_to_worldspace(0, get(:mouse_y))[1] + sB.x = Camera.coordinate_to_worldspace(get(:mouse_x),0)[0] + sB.y = Camera.coordinate_to_worldspace(0, get(:mouse_y))[1] # Check hitboxes a = hitbox_check( - [[s2.x1, s2.y1], - [s2.x2, s2.y2], - [s2.x3, s2.y3], - [s2.x4, s2.y4]], - [[s1.x1 + s1.x, s1.y1 + s1.y], - [s1.x2 + s1.x, s1.y2 + s1.y], - [s1.x3 + s1.x, s1.y3 + s1.y], - [s1.x4 + s1.x, s1.y4 + s1.y]], + [[sA.x1, sA.y1], + [sA.x2, sA.y2], + [sA.x3, sA.y3], + [sA.x4, sA.y4]], + [[sB.x1 + sB.x, sB.y1 + sB.y], + [sB.x2 + sB.x, sB.y2 + sB.y], + [sB.x3 + sB.x, sB.y3 + sB.y], + [sB.x4 + sB.x, sB.y4 + sB.y]], ) #DEBUG if $i == 0 - pp [[s2.x1, s2.y1], - [s2.x2, s2.y2], - [s2.x3, s2.y3], - [s2.x4, s2.y4]] - pp [[s1.x1 + s1.x, s1.y1 + s1.y], - [s1.x2 + s1.x, s1.y2 + s1.y], - [s1.x3 + s1.x, s1.y3 + s1.y], - [s1.x4 + s1.x, s1.y4 + s1.y]] + pp [[sA.x1, sA.y1], + [sA.x2, sA.y2], + [sA.x3, sA.y3], + [sA.x4, sA.y4]] + pp [[sB.x1 + sB.x, sB.y1 + sB.y], + [sB.x2 + sB.x, sB.y2 + sB.y], + [sB.x3 + sB.x, sB.y3 + sB.y], + [sB.x4 + sB.x, sB.y4 + sB.y]] end end |
