Allow rotating shape in SAT

Moved rendering of separating axes to function
Calculate overlaps instead of binary collision, write min distance to
resolve collision
This commit is contained in:
Matt Low 2020-11-15 00:24:44 +04:00
parent 3296d3a582
commit 5dfd84a2f6
2 changed files with 41 additions and 22 deletions

View File

@ -7,7 +7,6 @@ HEIGHT = 720
surface = None
screen = None
def init():
pygame.display.set_caption("Geom Demo")
pygame.mouse.set_visible(False)
@ -37,3 +36,6 @@ def loop():
def get_cursor_pos():
return sub(*pygame.mouse.get_pos(), WIDTH / 2, HEIGHT / 2)
def get_inputs():
return pygame.key.get_pressed()

View File

@ -1,9 +1,10 @@
from ..geom import Rect, Polygon
from .. import WIDTH, HEIGHT, get_cursor_pos
from .. import WIDTH, HEIGHT, get_cursor_pos, get_inputs
from ..colors import *
from ..math import *
from ..draw import *
class SeparatingAxisTheorem:
title = "Separating Axis Theorem"
@ -23,9 +24,35 @@ class SeparatingAxisTheorem:
(-60, 60)
])
def render(self, surface):
def handle_input(self):
self.shape2.set_position(*get_cursor_pos())
inputs = get_inputs()
if inputs[pygame.K_q]:
self.shape2.rotate((1/60) * -90)
if inputs[pygame.K_e]:
self.shape2.rotate((1/60) * 90)
def draw_axis(self, surface, normal, colliding, min1, max1, min2, max2):
offset = scale(*rnormal(*normal), 300)
# axis
line(surface, WHITE,
add(*scale(*reverse(*normal), 1000), *offset),
add(*scale(*normal, 1000), *offset))
# shape 1
line(surface, YELLOW if not colliding else RED,
add(*scale(*normal, min1), *offset),
add(*scale(*normal, max1), *offset), 5)
# shape 2
line(surface, YELLOW if not colliding else RED,
add(*scale(*normal, min2), *offset),
add(*scale(*normal, max2), *offset), 5)
def render(self, surface):
self.handle_input()
normals = []
def add_if_not_exists(normal):
@ -46,32 +73,22 @@ class SeparatingAxisTheorem:
_max = max(_max, proj)
return _min, _max
collisions = []
overlaps = []
for normal in normals:
min1, max1 = get_min_max(normal,
self.shape1.get_translated_vertices())
min2, max2 = get_min_max(normal,
self.shape2.get_translated_vertices())
colliding = max1 > min2 and max2 > min1
collisions.append(colliding)
overlap = max(min2 - max1, min1 - max2)
overlaps.append(overlap)
offset = scale(*rnormal(*normal), 300)
# axis
line(surface, WHITE,
add(*scale(*reverse(*normal), 1000), *offset),
add(*scale(*normal, 1000), *offset))
# shape 1
line(surface, YELLOW if not colliding else RED,
add(*scale(*normal, min1), *offset),
add(*scale(*normal, max1), *offset), 5)
# shape 2
line(surface, YELLOW if not colliding else RED,
add(*scale(*normal, min2), *offset),
add(*scale(*normal, max2), *offset), 5)
self.draw_axis(surface, normal, overlap < 0, min1, max1, min2, max2)
colliding = all(overlap < 0 for overlap in overlaps)
if colliding:
text_screen(surface, WHITE, (10, HEIGHT - 20),
f"Min Distance to Resolve: {max(overlaps)}")
self.shape1.draw(surface, YELLOW, 4)
self.shape2.draw(surface, RED if all(collisions) else WHITE, 4)
self.shape2.draw(surface, RED if colliding else WHITE, 4)