Source code for arcade.hitbox.simple

from PIL.Image import Image

from arcade.types import Point, Point2List

from .base import HitBoxAlgorithm


[docs] class SimpleHitBoxAlgorithm(HitBoxAlgorithm): """ Simple hit box algorithm. This algorithm attempts to trim out transparent pixels from an image to create a hit box. """
[docs] def calculate(self, image: Image, **kwargs) -> Point2List: """ Given an RGBA image, this returns points that make up a hit box around it. Attempts to trim out transparent pixels. Args: image: Image get hit box from. """ if image.mode != "RGBA": raise ValueError("Image mode is not RGBA. image.convert('RGBA') is needed.") # Convert the image into one channel alpha since we don't care about RGB values image = image.getchannel("A") bbox = image.getbbox() # If there is no bounding box the image is empty if bbox is None: return self.create_bounding_box(image) left_border, top_border, right_border, bottom_border = bbox right_border -= 1 bottom_border -= 1 def _check_corner_offset( start_x: int, start_y: int, x_direction: int, y_direction: int ) -> int: bad = False offset = 0 while not bad: y = start_y + (offset * y_direction) x = start_x for _ in range(offset + 1): alpha = image.getpixel((x, y)) # print(f"({x}, {y}) = {my_pixel} | ", end="") if alpha != 0: bad = True break y -= y_direction x += x_direction # print(f" - {bad}") if not bad: offset += 1 # print(f"offset: {offset}") return offset def _r(point: tuple[float, float], height: int, width: int) -> Point: return point[0] - width / 2, (height - point[1]) - height / 2 top_left_corner_offset = _check_corner_offset(left_border, top_border, 1, 1) top_right_corner_offset = _check_corner_offset(right_border, top_border, -1, 1) bottom_left_corner_offset = _check_corner_offset(left_border, bottom_border, 1, -1) bottom_right_corner_offset = _check_corner_offset(right_border, bottom_border, -1, -1) p1 = left_border + top_left_corner_offset, top_border p2 = (right_border + 1) - top_right_corner_offset, top_border p3 = (right_border + 1), top_border + top_right_corner_offset p4 = (right_border + 1), (bottom_border + 1) - bottom_right_corner_offset p5 = (right_border + 1) - bottom_right_corner_offset, (bottom_border + 1) p6 = left_border + bottom_left_corner_offset, (bottom_border + 1) p7 = left_border, (bottom_border + 1) - bottom_left_corner_offset p8 = left_border, top_border + top_left_corner_offset result = [] h = image.height w = image.width result.append(_r(p7, h, w)) if bottom_left_corner_offset: result.append(_r(p6, h, w)) result.append(_r(p5, h, w)) if bottom_right_corner_offset: result.append(_r(p4, h, w)) result.append(_r(p3, h, w)) if top_right_corner_offset: result.append(_r(p2, h, w)) result.append(_r(p1, h, w)) if top_left_corner_offset: result.append(_r(p8, h, w)) # Remove duplicates return tuple(dict.fromkeys(result)) # type: ignore