diff options
Diffstat (limited to 'src/Collision')
| -rw-r--r-- | src/Collision/Collision.php | 141 | 
1 files changed, 141 insertions, 0 deletions
diff --git a/src/Collision/Collision.php b/src/Collision/Collision.php new file mode 100644 index 0000000..a896777 --- /dev/null +++ b/src/Collision/Collision.php @@ -0,0 +1,141 @@ +<?php + +namespace App\Collision; + + +class Collision +{ +    protected const BUFFER = 0.1; + +    public static function circleRectangle(int $c_radius, int $c_x, int $c_y, int $r_w, int $r_h, int $r_x, int $r_y): bool +    { +        $test_x = $c_x; +        $test_y = $c_y; + +        if ($c_x < $r_x) { +            $test_x = $r_x; +        } elseif ($c_x > $r_x + $r_w) { +            $test_x = $r_x + $r_w; +        } + +        if ($c_y < $r_y) { +            $test_y = $r_y; +        } elseif ($c_y > $r_y + $r_h) { +            $test_y = $r_y + $r_h; +        } + +        $dist_x = $c_x - $test_x; +        $dist_y = $c_y - $test_y; + +        $distance = sqrt( ($dist_x * $dist_y) + ($dist_y * $dist_y) ); + +        if ($distance <= $c_radius) { +            return true; +        } + +        return false; +    } + +    public static function circleWorld(int $c_radius, int $c_x, int $c_y, int $w_w, int $w_h, int $w_x, int $w_y): bool +    { +        if (static::circleOutsideRectangle($c_radius, $c_x, $c_y, $w_w, $w_h, $w_x, $w_y)) { +            return true; +        } + +        if (static::lineCircle($w_x, $w_x, $w_y, $w_y+$w_h, $c_x, $c_y, $c_radius)) { +            return true; +        } + +        if (static::lineCircle($w_x+$w_w, $w_x+$w_w, $w_y, $w_y+$w_h, $c_x, $c_y, $c_radius)) { +            return true; +        } + +        if (static::lineCircle($w_x, $w_x+$w_w, $w_y, $w_y, $c_x, $c_y, $c_radius)) { +            return true; +        } + +        if (static::lineCircle($w_x, $w_x+$w_w, $w_y+$w_h, $w_y+$w_h, $c_x, $c_y, $c_radius)) { +            return true; +        } + +        return false; + +    } + +    public static function circleOutsideRectangle(int $c_radius, int $c_x, int $c_y, int $w_w, int $w_h, int $w_x, int $w_y) +    { +        if ($c_x + $c_radius < $w_x) { +            return true; +        } + +        if ($c_x - $c_radius > $w_x + $w_w) { +            return true; +        } + +        if ($c_y + $c_radius < $w_y) { +            return true; +        } + +        if ($c_y - $c_radius > $w_y + $w_h) { +            return true; +        } + +        return false; +    } + +    public static function lineCircle(int $x_1, int $x_2, int $y_1, int $y_2, int $c_x, int $c_y, int $c_radius): bool +    { +        if (static::pointCircle($x_1, $y_1, $c_x, $c_y, $c_radius)) { +            return true; +        } + +        if (static::pointCircle($x_2, $y_2, $c_x, $c_y, $c_radius)) { +            return true; +        } + +        $length = static::distance($x_1, $x_2, $y_1, $y_2); + +        $dot = ((($c_x - $x_1) * ($x_2 - $x_1)) + (($c_y - $y_1) * ($y_2 - $y_1))) / ($length * $length); +        $dot = number_format($dot, 4); + +        $closest_x = $x_1 + ($dot * ($x_2 - $x_1)); +        $closest_y = $y_1 +_($dot * ($y_2 - $y_1)); + +        if (!static::linePoint($x_1, $x_2, $y_1, $y_2, $closest_x, $closest_y)) { +            return false; +        } + +        $distance = static::distance($closest_x, $c_x, $closest_y, $c_y); + +        return $distance <= $c_radius; +    } + +    public static function linePoint(int $x_1, int $x_2, int $y_1, int $y_2, int $p_x, int $p_y) +    { +        $d_1 = static::distance($p_x, $x_1, $p_y, $y_1); +        $d_2 = static::distance($p_x, $x_2, $p_y, $y_2); + +        $length = static::distance($x_1, $x_2, $y_1, $y_2); + +        return $d_1 + $d_2 >= $length - static::BUFFER +            && $d_1 + $d_2 <= $length + static::BUFFER; +    } + +    public static function pointCircle(int $p_x, int $p_y, int $c_x, int $c_y, int $c_radius): bool +    { +        $distance = static::distance($p_x, $c_x, $p_y, $c_y); + +        return $distance <= $c_radius; +    } + +    public static function distance(int $x_1, int $x_2, int $y_1, int $y_2): float +    { +        $d_x = $x_1 - $x_2; +        $d_y = $y_1 - $y_2; + +        return number_format( +            sqrt( ($d_x * $d_x) + ($d_y * $d_y)), +            2 +        ); +    } +}  | 
