diff options
Diffstat (limited to 'src/uqm/gravity.c')
-rw-r--r-- | src/uqm/gravity.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/uqm/gravity.c b/src/uqm/gravity.c new file mode 100644 index 0000000..5a7899c --- /dev/null +++ b/src/uqm/gravity.c @@ -0,0 +1,200 @@ +//Copyright Paul Reiche, Fred Ford. 1992-2002 + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "collide.h" +#include "races.h" +#include "units.h" +#include "libs/log.h" + +//#define DEBUG_GRAVITY + +BOOLEAN +CalculateGravity (ELEMENT *ElementPtr) +{ + BOOLEAN retval, HasGravity; + HELEMENT hTestElement, hSuccElement; + + retval = FALSE; + HasGravity = (BOOLEAN)(CollidingElement (ElementPtr) + && GRAVITY_MASS (ElementPtr->mass_points + 1)); + for (hTestElement = GetHeadElement (); + hTestElement != 0; hTestElement = hSuccElement) + { + BOOLEAN TestHasGravity; + ELEMENT *TestElementPtr; + + LockElement (hTestElement, &TestElementPtr); + if (TestElementPtr != ElementPtr + && CollidingElement (TestElementPtr) + && (TestHasGravity = + GRAVITY_MASS (TestElementPtr->mass_points + 1)) != HasGravity) + { + COUNT abs_dx, abs_dy; + SIZE dx, dy; + + if (!(ElementPtr->state_flags & PRE_PROCESS)) + { + dx = ElementPtr->current.location.x + - TestElementPtr->current.location.x; + dy = ElementPtr->current.location.y + - TestElementPtr->current.location.y; + } + else + { + dx = ElementPtr->next.location.x + - TestElementPtr->next.location.x; + dy = ElementPtr->next.location.y + - TestElementPtr->next.location.y; + } +#ifdef DEBUG_GRAVITY + if (TestElementPtr->state_flags & PLAYER_SHIP) + { + log_add (log_Debug, "CalculateGravity:"); + log_add (log_Debug, "\tdx = %d, dy = %d", dx, dy); + } +#endif /* DEBUG_GRAVITY */ + dx = WRAP_DELTA_X (dx); + dy = WRAP_DELTA_Y (dy); +#ifdef DEBUG_GRAVITY + if (TestElementPtr->state_flags & PLAYER_SHIP) + log_add (log_Debug, "\twrap_dx = %d, wrap_dy = %d", dx, dy); +#endif /* DEBUG_GRAVITY */ + abs_dx = dx >= 0 ? dx : -dx; + abs_dy = dy >= 0 ? dy : -dy; + abs_dx = WORLD_TO_DISPLAY (abs_dx); + abs_dy = WORLD_TO_DISPLAY (abs_dy); +#ifdef DEBUG_GRAVITY + if (TestElementPtr->state_flags & PLAYER_SHIP) + log_add (log_Debug, "\tdisplay_dx = %d, display_dy = %d", + abs_dx, abs_dy); +#endif /* DEBUG_GRAVITY */ + if (abs_dx <= GRAVITY_THRESHOLD + && abs_dy <= GRAVITY_THRESHOLD) + { + DWORD dist_squared; + + dist_squared = (DWORD)(abs_dx * abs_dx) + + (DWORD)(abs_dy * abs_dy); + if (dist_squared <= (DWORD)(GRAVITY_THRESHOLD + * GRAVITY_THRESHOLD)) + { +#ifdef NEVER + COUNT magnitude; + +#define DIFUSE_GRAVITY 175 + dist_squared += (DWORD)abs_dx * (DIFUSE_GRAVITY << 1) + + (DWORD)abs_dy * (DIFUSE_GRAVITY << 1) + + ((DWORD)(DIFUSE_GRAVITY * DIFUSE_GRAVITY) << 1); + if ((magnitude = (COUNT)((DWORD)(GRAVITY_THRESHOLD + * GRAVITY_THRESHOLD) / dist_squared)) == 0) + magnitude = 1; + +#define MAX_MAGNITUDE 6 + else if (magnitude > MAX_MAGNITUDE) + magnitude = MAX_MAGNITUDE; + log_add (log_Debug, "magnitude = %u", magnitude); +#endif /* NEVER */ + +#ifdef DEBUG_GRAVITY + if (TestElementPtr->state_flags & PLAYER_SHIP) + log_add (log_Debug, "dist_squared = %lu", dist_squared); +#endif /* DEBUG_GRAVITY */ + if (TestHasGravity) + { + retval = TRUE; + UnlockElement (hTestElement); + break; + } + else + { + COUNT angle; + + angle = ARCTAN (dx, dy); + DeltaVelocityComponents (&TestElementPtr->velocity, + COSINE (angle, WORLD_TO_VELOCITY (1)), + SINE (angle, WORLD_TO_VELOCITY (1))); + if (TestElementPtr->state_flags & PLAYER_SHIP) + { + STARSHIP *StarShipPtr; + + GetElementStarShip (TestElementPtr, &StarShipPtr); + StarShipPtr->cur_status_flags &= ~SHIP_AT_MAX_SPEED; + StarShipPtr->cur_status_flags |= SHIP_IN_GRAVITY_WELL; + } + } + } + } + } + + hSuccElement = GetSuccElement (TestElementPtr); + UnlockElement (hTestElement); + } + + return (retval); +} + +BOOLEAN +TimeSpaceMatterConflict (ELEMENT *ElementPtr) +{ + HELEMENT hTestElement, hSuccElement; + INTERSECT_CONTROL ElementControl; + + ElementControl.IntersectStamp.origin.x = + WORLD_TO_DISPLAY (ElementPtr->current.location.x); + ElementControl.IntersectStamp.origin.y = + WORLD_TO_DISPLAY (ElementPtr->current.location.y); + ElementControl.IntersectStamp.frame = + SetEquFrameIndex (ElementPtr->current.image.farray[0], + ElementPtr->current.image.frame); + ElementControl.EndPoint = ElementControl.IntersectStamp.origin; + for (hTestElement = GetHeadElement (); + hTestElement != 0; hTestElement = hSuccElement) + { + ELEMENT *TestElementPtr; + + LockElement (hTestElement, &TestElementPtr); + hSuccElement = GetSuccElement (TestElementPtr); + if (TestElementPtr != ElementPtr + && (CollidingElement (TestElementPtr) + /* ship in transition */ + || (TestElementPtr->state_flags & PLAYER_SHIP))) + { + INTERSECT_CONTROL TestElementControl; + + TestElementControl.IntersectStamp.origin.x = + WORLD_TO_DISPLAY (TestElementPtr->current.location.x); + TestElementControl.IntersectStamp.origin.y = + WORLD_TO_DISPLAY (TestElementPtr->current.location.y); + TestElementControl.IntersectStamp.frame = + SetEquFrameIndex (TestElementPtr->current.image.farray[0], + TestElementPtr->current.image.frame); + TestElementControl.EndPoint = TestElementControl.IntersectStamp.origin; + if (DrawablesIntersect (&ElementControl, + &TestElementControl, MAX_TIME_VALUE)) + { + UnlockElement (hTestElement); + + break; + } + } + UnlockElement (hTestElement); + } + + return (hTestElement != 0 ? TRUE : FALSE); +} + |