Add Separating Axis Theorum demo
This commit is contained in:
parent
bfe1ab8ee0
commit
7f33e917d7
77
geom/demos/sat.py
Normal file
77
geom/demos/sat.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
from ..geom import Rect, Polygon
|
||||||
|
from .. import WIDTH, HEIGHT, get_cursor_pos
|
||||||
|
from ..colors import *
|
||||||
|
from ..math import *
|
||||||
|
from ..draw import *
|
||||||
|
|
||||||
|
class SeparatingAxisTheorem:
|
||||||
|
|
||||||
|
title = "Separating Axis Theorem"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.shape1 = Polygon(0, 0, [
|
||||||
|
(0, 60),
|
||||||
|
(60, 0),
|
||||||
|
(0, -60),
|
||||||
|
(-60, 0)
|
||||||
|
])
|
||||||
|
|
||||||
|
self.shape2 = Polygon(*get_cursor_pos(), [
|
||||||
|
(60, 60),
|
||||||
|
(60, -60),
|
||||||
|
(-60, -60),
|
||||||
|
(-60, 60)
|
||||||
|
])
|
||||||
|
|
||||||
|
def render(self, surface):
|
||||||
|
self.shape2.set_position(*get_cursor_pos())
|
||||||
|
|
||||||
|
normals = []
|
||||||
|
|
||||||
|
def add_if_not_exists(normal):
|
||||||
|
for existing in normals:
|
||||||
|
if is_equal(*existing, *normal):
|
||||||
|
return
|
||||||
|
normals.append(normal)
|
||||||
|
|
||||||
|
for normal in self.shape1.get_normals() + self.shape2.get_normals():
|
||||||
|
add_if_not_exists(normal)
|
||||||
|
|
||||||
|
def get_min_max(normal, vertices):
|
||||||
|
_min = float('inf')
|
||||||
|
_max = float('-inf')
|
||||||
|
for vertex in vertices:
|
||||||
|
proj = dot(*normal, *vertex)
|
||||||
|
_min = min(_min, proj)
|
||||||
|
_max = max(_max, proj)
|
||||||
|
return _min, _max
|
||||||
|
|
||||||
|
collisions = []
|
||||||
|
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)
|
||||||
|
|
||||||
|
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.shape1.draw(surface, YELLOW, 4)
|
||||||
|
self.shape2.draw(surface, RED if all(collisions) else WHITE, 4)
|
@ -1,5 +1,5 @@
|
|||||||
import pygame
|
import pygame
|
||||||
from .demos import aabb, vec_proj
|
from .demos import aabb, vec_proj, sat
|
||||||
from . import HEIGHT
|
from . import HEIGHT
|
||||||
from .colors import *
|
from .colors import *
|
||||||
from .draw import text_screen
|
from .draw import text_screen
|
||||||
@ -11,6 +11,7 @@ class Screen:
|
|||||||
vec_proj.VecProj(),
|
vec_proj.VecProj(),
|
||||||
aabb.AABBDistance(),
|
aabb.AABBDistance(),
|
||||||
aabb.PointAABBDistance(),
|
aabb.PointAABBDistance(),
|
||||||
|
sat.SeparatingAxisTheorem(),
|
||||||
]
|
]
|
||||||
self.demo = 0
|
self.demo = 0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user