00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "game-server/collisiondetection.hpp"
00022
00023 #include <cmath>
00024
00025 #include "point.h"
00026 #include "utils/mathutils.h"
00027
00028 #define D_TO_R 0.0174532925 // PI / 180
00029 #define R_TO_D 57.2957795 // 180 / PI
00030
00031
00032 #define test_degrees(pos,s1,s2) (pos > s1 && pos < s2) || (s1 > s2 && !(pos < s1 && pos > s2))
00033
00034
00035 bool
00036 Collision::circleWithCirclesector(const Point &circlePos, int circleRadius,
00037 const Point &secPos, int secRadius,
00038 float secAngle, float secSize)
00039 {
00040 float targetAngle;
00041
00042
00043 int distX = circlePos.x - secPos.x;
00044 int distY = circlePos.y - secPos.y;
00045 float invDist = utils::math::fastInvSqrt(distX * distX + distY * distY);
00046 float dist = 1.0f / invDist;
00047
00048
00049 if (dist > secRadius + circleRadius) {
00050 return false;
00051 }
00052
00053 if (dist < circleRadius) {
00054 return true;
00055 }
00056
00057
00058 if (distX > 0)
00059 {
00060 targetAngle = asin(-distY * invDist);
00061 } else {
00062 if (distY < 0)
00063 {
00064 targetAngle = M_PI - asin(-distY * invDist);
00065 } else {
00066 targetAngle = -M_PI - asin(-distY * invDist);
00067 }
00068
00069 }
00070
00071
00072 float targetDiff = fabs(targetAngle - secAngle);
00073 if (targetDiff > M_PI)
00074 {
00075 targetDiff = fabs(targetDiff - M_PI * 2);
00076 }
00077
00078
00079
00080 secSize += asin(circleRadius * invDist) * 2;
00081
00082 return (targetDiff < secSize * 0.5f);
00083 }
00084
00085
00086 bool Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius,
00087 const Point §orCenter, int sectorRadius,
00088 int halfTopAngle, int placeAngle)
00089 {
00090 float r1 = sectorRadius,
00091 r2 = diskRadius;
00092
00093 float dx = sectorCenter.x - diskCenter.x,
00094 dy = sectorCenter.y - diskCenter.y;
00095
00096
00097 float d = ((dx * dx) + (dy * dy));
00098
00099
00100 if(d < r2 * r2)
00101 return true;
00102
00103
00104 if(d > ((r1+r2) * (r1+r2)))
00105 return false;
00106
00107 float s1 = placeAngle - halfTopAngle,
00108 s2 = placeAngle + halfTopAngle;
00109
00110 if (s1 >= 360)
00111 s1 -= 360;
00112 if (s1 < 0)
00113 s1 += 360;
00114 if (s2 >= 360)
00115 s2 -= 360;
00116 if (s2 < 0)
00117 s2 += 360;
00118
00119
00120 if(d < r1 * r1)
00121 {
00122
00123 float c2dc1 = atan2(dy,dx) * R_TO_D;
00124 if (c2dc1 < 0)
00125 c2dc1 += 360;
00126
00127 if (test_degrees(c2dc1, s1, s2))
00128 return true;
00129
00130
00131
00132 d = sqrt(d);
00133 r1 = d;
00134 } else {
00135 d = sqrt(d);
00136 }
00137
00138 float a = ((r1*r1) - (r2*r2) + (d*d)) / (2.0 * d);
00139 float axd = (a * dx) / d,
00140 ayd = (a * dy) / d,
00141 h = sqrt((r1*r1) - (a*a));
00142
00143 float ix1 = axd + ((h * dx) / d),
00144 iy1 = ayd - ((h * dy) / d),
00145 ix2 = axd - ((h * dx) / d),
00146 iy2 = ayd + ((h * dy) / d);
00147
00148 float idc1 = atan2(iy1,ix1) * R_TO_D;
00149 if(idc1 < 0)
00150 idc1 += 360;
00151 if(test_degrees(idc1, s1, s2))
00152 return true;
00153
00154 idc1 = atan2(iy2,ix2) * R_TO_D;
00155 if(idc1 < 0)
00156 idc1 += 360;
00157 if(test_degrees(idc1, s1, s2))
00158 return true;
00159
00160
00161 return false;
00162
00163 }
00164
00165
00282 bool
00283 Collision::CircleWithCircle(const Point ¢er1, int radius1,
00284 const Point ¢er2, int radius2)
00285 {
00286 int distx = center1.x - center2.x;
00287 int disty = center1.y - center2.y;
00288 double dist = sqrt((distx * distx) + (disty * disty));
00289 return (dist < radius1 + radius2);
00290 }
00291
00292 bool
00293 Collision::rectWithRect(const Point &pos1, const Point &size1,
00294 const Point &pos2, const Point &size2)
00295 {
00296 return(
00297 pos1.x < (pos2.x + size2.x)
00298 &&
00299 (pos1.x + size1.x) > pos2.x
00300 &&
00301 pos1.y < (pos2.y + size2.y)
00302 &&
00303 (pos1.y + size1.y) > pos2.y
00304 );
00305 }