From df8c5ed43b5513916eff1b3f25e0bba6a50c8826 Mon Sep 17 00:00:00 2001 From: Roderic Morris Date: Wed, 29 Oct 2008 16:33:29 +0000 Subject: replace collision detection function (by Chuck Miller) --- ChangeLog | 8 +++ src/game-server/being.cpp | 7 +-- src/game-server/collisiondetection.cpp | 100 +++++++++++++++++++++++++++++++-- src/game-server/monster.cpp | 4 +- 4 files changed, 107 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index f18eaee..a6e70c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-10-29 Chuck Miller + + * src/game-server/collisiondetection.cpp, src/game-server/monster.cpp, + src/game-server/being.cpp: Replaced the collision detection function + due to it being broken, I left it in the source, just commented out if + someone wants to try to fix it later on. In other news, this patch + now makes it possible to hit them pesty maggots + 2008-10-27 Bjørn Lindeijer * src/account-server/serverhandler.cpp, diff --git a/src/game-server/being.cpp b/src/game-server/being.cpp index 130f1a7..c9bec84 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 110ef57..6529952 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 #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 f9cb179..9a6de34 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( -- cgit