Source code for arcade.geometry

"""
Functions for calculating geometry.
"""

from arcade.sprite import Sprite
from arcade.sprite_list import SpriteList
from typing import List
from arcade.arcade_types import PointList

PRECISION = 2


[docs]def are_polygons_intersecting(poly_a: PointList, poly_b: PointList) -> bool: """ Return True if two polygons intersect. Args: :poly_a (tuple): List of points that define the first polygon. :poly_b (tuple): List of points that define the second polygon. Returns: bool Raises: None """ for polygon in (poly_a, poly_b): for i1 in range(len(polygon)): i2 = (i1 + 1) % len(polygon) projection_1 = polygon[i1] projection_2 = polygon[i2] normal = (projection_2[1] - projection_1[1], projection_1[0] - projection_2[0]) min_a, max_a, min_b, max_b = (None,) * 4 for poly in poly_a: projected = normal[0] * poly[0] + normal[1] * poly[1] if min_a is None or projected < min_a: min_a = projected if max_a is None or projected > max_a: max_a = projected for poly in poly_b: projected = normal[0] * poly[0] + normal[1] * poly[1] if min_b is None or projected < min_b: min_b = projected if max_b is None or projected > max_b: max_b = projected if max_a <= min_b or max_b <= min_a: return False return True
[docs]def check_for_collision(sprite1: Sprite, sprite2: Sprite) -> bool: """ Check for a collision between two sprites. """ if not isinstance(sprite1, Sprite): raise TypeError("Parameter 1 is not an instance of the Sprite class.") if isinstance(sprite2, SpriteList): raise TypeError("Parameter 2 is a instance of the SpriteList instead of a required Sprite. See if you meant to " "call check_for_collision_with_list instead of check_for_collision.") elif not isinstance(sprite2, Sprite): raise TypeError("Parameter 2 is not an instance of the Sprite class.") return _check_for_collision(sprite1, sprite2)
def _check_for_collision(sprite1: Sprite, sprite2: Sprite) -> bool: collision_radius_sum = sprite1.collision_radius + sprite2.collision_radius diff_x = sprite1.position[0] - sprite2.position[0] diff_x2 = diff_x * diff_x if diff_x2 > collision_radius_sum * collision_radius_sum: return False diff_y = sprite1.position[1] - sprite2.position[1] diff_y2 = diff_y * diff_y if diff_y2 > collision_radius_sum * collision_radius_sum: return False # distance = math.sqrt(diff_x * diff_x + diff_y * diff_y) # if distance > collision_radius_sum: # return False distance = diff_x2 + diff_y2 if distance > collision_radius_sum * collision_radius_sum: return False return are_polygons_intersecting(sprite1.points, sprite2.points)
[docs]def check_for_collision_with_list(sprite1: Sprite, sprite_list: SpriteList) -> List[Sprite]: """ Check for a collision between a sprite, and a list of sprites. """ if not isinstance(sprite1, Sprite): raise TypeError("Parameter 1 is not an instance of the Sprite class.") if not isinstance(sprite_list, SpriteList): raise TypeError(f"Parameter 2 is a {type(sprite_list)} instead of expected SpriteList.") if sprite_list.use_spatial_hash: sprite_list_to_check = sprite_list.spatial_hash.get_objects_for_box(sprite1) # checks_saved = len(sprite_list) - len(sprite_list_to_check) else: sprite_list_to_check = sprite_list collision_list = [] for sprite2 in sprite_list_to_check: if sprite1 is not sprite2 and sprite2 not in collision_list: if _check_for_collision(sprite1, sprite2): collision_list.append(sprite2) return collision_list