diff options
author | Roderic Morris <roderic@ccs.neu.edu> | 2008-10-29 16:33:29 +0000 |
---|---|---|
committer | Roderic Morris <roderic@ccs.neu.edu> | 2008-10-29 16:33:29 +0000 |
commit | df8c5ed43b5513916eff1b3f25e0bba6a50c8826 (patch) | |
tree | c1731c3684781d305a6ae3b9711a4c77a27637b2 /src | |
parent | 3597666677ef714071da9d3ab663e9b8f7b6219e (diff) | |
download | manaserv-df8c5ed43b5513916eff1b3f25e0bba6a50c8826.tar.gz manaserv-df8c5ed43b5513916eff1b3f25e0bba6a50c8826.tar.bz2 manaserv-df8c5ed43b5513916eff1b3f25e0bba6a50c8826.tar.xz manaserv-df8c5ed43b5513916eff1b3f25e0bba6a50c8826.zip |
replace collision detection function (by Chuck Miller)
Diffstat (limited to 'src')
-rw-r--r-- | src/game-server/being.cpp | 7 | ||||
-rw-r--r-- | src/game-server/collisiondetection.cpp | 100 | ||||
-rw-r--r-- | src/game-server/monster.cpp | 4 |
3 files changed, 99 insertions, 12 deletions
diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 130f1a75..c9bec84c 100644 --- a/src/game-server/being.cpp +++ b/src/game-server/being.cpp @@ -144,10 +144,10 @@ void Being::performAttack(Damage const &damage, AttackZone const *attackZone) attackAngle = 270; break; case DIRECTION_LEFT: - attackAngle = 180; + attackAngle = 0; break; case DIRECTION_RIGHT: - attackAngle = 0; + attackAngle = 180; break; default: break; @@ -161,7 +161,6 @@ void Being::performAttack(Damage const &damage, AttackZone const *attackZone) MovingObject *o = *i; Point opos = o->getPosition(); - Effects::show(Effects::FIRE_BURST,getMap(),opos); if (o == this) continue; int type = o->getType(); @@ -176,7 +175,7 @@ void Being::performAttack(Damage const &damage, AttackZone const *attackZone) if (Collision::diskWithCircleSector( opos, o->getSize(), ppos, attackZone->range, - attackZone->angle, attackAngle) + attackZone->angle / 2, attackAngle) ) { victims.push_back(static_cast< Being * >(o)); diff --git a/src/game-server/collisiondetection.cpp b/src/game-server/collisiondetection.cpp index 110ef575..6529952c 100644 --- a/src/game-server/collisiondetection.cpp +++ b/src/game-server/collisiondetection.cpp @@ -20,13 +20,20 @@ * $Id$ */ -#include "collisiondetection.hpp" +#include "game-server/collisiondetection.hpp" #include <cmath> #include "point.h" #include "utils/mathutils.h" +#define D_TO_R 0.0174532925 // PI / 180 +#define R_TO_D 57.2957795 // 180 / PI + +// Tests to see if pos is between s1 degree and s2 +#define test_degrees(pos,s1,s2) (pos > s1 && pos < s2) || (s1 > s2 && !(pos < s1 && pos > s2)) + + bool Collision::circleWithCirclesector(const Point &circlePos, int circleRadius, const Point &secPos, int secRadius, @@ -77,14 +84,95 @@ Collision::circleWithCirclesector(const Point &circlePos, int circleRadius, return (targetDiff < secSize * 0.5f); } + +bool Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius, + const Point §orCenter, int sectorRadius, + int halfTopAngle, int placeAngle) +{ + float r1 = sectorRadius, + r2 = diskRadius; + + float dx = sectorCenter.x - diskCenter.x, + dy = sectorCenter.y - diskCenter.y; + + // d^2 = dx^2 + dy^2 + float d = ((dx * dx) + (dy * dy)); + + // d^2 < r2^2 + if(d < r2 * r2) + return true; // We are right on top of each other + + // d^2 > r1^2 + r2^2 + if(d > ((r1+r2) * (r1+r2))) + return false; // The two circles do not touch + + float s1 = placeAngle - halfTopAngle, + s2 = placeAngle + halfTopAngle; + + if (s1 >= 360) + s1 -= 360; + if (s1 < 0) + s1 += 360; + if (s2 >= 360) + s2 -= 360; + if (s2 < 0) + s2 += 360; + + // Is the center point of circle 2 within circle 1? + if(d < r1 * r1) + { + // Circle 2 degrees in respect to circle 1 + float c2dc1 = atan2(dy,dx) * R_TO_D; + if (c2dc1 < 0) + c2dc1 += 360; + + if (test_degrees(c2dc1, s1, s2)) + return true; + + // Since we are well within range, we might be + // Too close, so we need to make sure two circles intersect + d = sqrt(d); + r1 = d; + } else { + d = sqrt(d); + } + + float a = ((r1*r1) - (r2*r2) + (d*d)) / (2.0 * d); + float axd = (a * dx) / d, + ayd = (a * dy) / d, + h = sqrt((r1*r1) - (a*a)); + + float ix1 = axd + ((h * dx) / d), + iy1 = ayd - ((h * dy) / d), + ix2 = axd - ((h * dx) / d), + iy2 = ayd + ((h * dy) / d); + + float idc1 = atan2(iy1,ix1) * R_TO_D; + if(idc1 < 0) + idc1 += 360; + if(test_degrees(idc1, s1, s2)) + return true; + + idc1 = atan2(iy2,ix2) * R_TO_D; + if(idc1 < 0) + idc1 += 360; + if(test_degrees(idc1, s1, s2)) + return true; + + // If we got to this point, it must be false + return false; + +} + + /** * Collision of a Disk with a Circle-Sector * * For a detailled explanation of this function please see: * http://wiki.themanaworld.org/index.php/Collision_determination - */ + * bool -Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius, +Collision::diskWithCircleSector2(const Point &diskCenter, int diskRadius, const Point §orCenter, int sectorRadius, int halfTopAngle, int placeAngle) { @@ -102,13 +190,13 @@ Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius, float sinBeta = utils::math::cachedSin(placeAngle); float cosBeta = utils::math::cachedCos(placeAngle); - /** + ** * This bounding circle implementation can be used up and until a * half-top-angle of +/- 85 degrees. The bounding circle becomes * infinitly large at 90 degrees. Above about 60 degrees a bounding * half-circle with radius R becomes more efficient. * (The additional check for a region 1 collision can then be scrapped.) - */ + * // Calculating the coordinates of the disk's center in coordinate system 4 float Px1 = Px * cosBeta + Py * sinBeta; @@ -192,7 +280,7 @@ Collision::diskWithCircleSector(const Point &diskCenter, int diskRadius, // but the disk and circle sector don't intersect. return false; } - +*/ bool Collision::CircleWithCircle(const Point ¢er1, int radius1, const Point ¢er2, int radius2) diff --git a/src/game-server/monster.cpp b/src/game-server/monster.cpp index f9cb1794..9a6de34b 100644 --- a/src/game-server/monster.cpp +++ b/src/game-server/monster.cpp @@ -234,8 +234,8 @@ void Monster::update() { case DIRECTION_UP: attackAngle = 90; break; case DIRECTION_DOWN: attackAngle = 270; break; - case DIRECTION_LEFT: attackAngle = 180; break; - case DIRECTION_RIGHT:attackAngle = 0; break; + case DIRECTION_LEFT: attackAngle = 0; break; + case DIRECTION_RIGHT:attackAngle = 180; break; default: break; } if (Collision::diskWithCircleSector( |