summaryrefslogtreecommitdiff
path: root/src/uqm/collide.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/collide.c')
-rw-r--r--src/uqm/collide.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/uqm/collide.c b/src/uqm/collide.c
new file mode 100644
index 0000000..7275e42
--- /dev/null
+++ b/src/uqm/collide.c
@@ -0,0 +1,183 @@
+//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 "element.h"
+#include "races.h"
+#include "units.h"
+#include "libs/mathlib.h"
+#include "libs/log.h"
+
+
+//#define DEBUG_COLLIDE
+
+void
+collide (ELEMENT *ElementPtr0, ELEMENT *ElementPtr1)
+{
+ SIZE speed;
+ SIZE dx0, dy0, dx1, dy1, dx_rel, dy_rel;
+ SIZE TravelAngle0, TravelAngle1, ImpactAngle0, ImpactAngle1;
+ SIZE RelTravelAngle, Directness;
+
+ dx_rel = ElementPtr0->next.location.x
+ - ElementPtr1->next.location.x;
+ dy_rel = ElementPtr0->next.location.y
+ - ElementPtr1->next.location.y;
+ ImpactAngle0 = ARCTAN (dx_rel, dy_rel);
+ ImpactAngle1 = NORMALIZE_ANGLE (ImpactAngle0 + HALF_CIRCLE);
+
+ GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0);
+ TravelAngle0 = GetVelocityTravelAngle (&ElementPtr0->velocity);
+ GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1);
+ TravelAngle1 = GetVelocityTravelAngle (&ElementPtr1->velocity);
+ dx_rel = dx0 - dx1;
+ dy_rel = dy0 - dy1;
+ RelTravelAngle = ARCTAN (dx_rel, dy_rel);
+ speed = square_root ((long)dx_rel * dx_rel + (long)dy_rel * dy_rel);
+
+ Directness = NORMALIZE_ANGLE (RelTravelAngle - ImpactAngle0);
+ if (Directness <= QUADRANT || Directness >= HALF_CIRCLE + QUADRANT)
+ /* shapes just scraped each other but still collided,
+ * they will collide again unless we fudge it.
+ */
+ {
+ Directness = HALF_CIRCLE;
+ ImpactAngle0 = TravelAngle0 + HALF_CIRCLE;
+ ImpactAngle1 = TravelAngle1 + HALF_CIRCLE;
+ }
+
+#ifdef DEBUG_COLLIDE
+ log_add (log_Debug, "Centers: <%d, %d> <%d, %d>",
+ ElementPtr0->next.location.x, ElementPtr0->next.location.y,
+ ElementPtr1->next.location.x, ElementPtr1->next.location.y);
+ log_add (log_Debug, "RelTravelAngle : %d, ImpactAngles <%d, %d>",
+ RelTravelAngle, ImpactAngle0, ImpactAngle1);
+#endif /* DEBUG_COLLIDE */
+
+ if (ElementPtr0->next.location.x == ElementPtr0->current.location.x
+ && ElementPtr0->next.location.y == ElementPtr0->current.location.y
+ && ElementPtr1->next.location.x == ElementPtr1->current.location.x
+ && ElementPtr1->next.location.y == ElementPtr1->current.location.y)
+ {
+ if (ElementPtr0->state_flags & ElementPtr1->state_flags & DEFY_PHYSICS)
+ {
+ ImpactAngle0 = TravelAngle0 + (HALF_CIRCLE - OCTANT);
+ ImpactAngle1 = TravelAngle1 + (HALF_CIRCLE - OCTANT);
+ ZeroVelocityComponents (&ElementPtr0->velocity);
+ ZeroVelocityComponents (&ElementPtr1->velocity);
+ }
+ ElementPtr0->state_flags |= (DEFY_PHYSICS | COLLISION);
+ ElementPtr1->state_flags |= (DEFY_PHYSICS | COLLISION);
+#ifdef DEBUG_COLLIDE
+ log_add (log_Debug, "No movement before collision -- "
+ "<(%d, %d) = %d, (%d, %d) = %d>",
+ dx0, dy0, ImpactAngle0 - OCTANT, dx1, dy1,
+ ImpactAngle1 - OCTANT);
+#endif /* DEBUG_COLLIDE */
+ }
+
+ {
+ SIZE mass0, mass1;
+ long scalar;
+
+ mass0 = ElementPtr0->mass_points /* << 2 */;
+ mass1 = ElementPtr1->mass_points /* << 2 */;
+ scalar = (long)SINE (Directness, speed << 1) * (mass0 * mass1);
+
+ if (!GRAVITY_MASS (ElementPtr0->mass_points + 1))
+ {
+ if (ElementPtr0->state_flags & PLAYER_SHIP)
+ {
+ STARSHIP *StarShipPtr;
+
+ GetElementStarShip (ElementPtr0, &StarShipPtr);
+ StarShipPtr->cur_status_flags &=
+ ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED);
+ if (!(ElementPtr0->state_flags & DEFY_PHYSICS))
+ {
+ if (ElementPtr0->turn_wait < COLLISION_TURN_WAIT)
+ ElementPtr0->turn_wait += COLLISION_TURN_WAIT;
+ if (ElementPtr0->thrust_wait < COLLISION_THRUST_WAIT)
+ ElementPtr0->thrust_wait += COLLISION_THRUST_WAIT;
+ }
+ }
+
+ speed = (SIZE)(scalar / ((long)mass0 * (mass0 + mass1)));
+ DeltaVelocityComponents (&ElementPtr0->velocity,
+ COSINE (ImpactAngle0, speed),
+ SINE (ImpactAngle0, speed));
+
+ GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0);
+ if (dx0 < 0)
+ dx0 = -dx0;
+ if (dy0 < 0)
+ dy0 = -dy0;
+
+ if (VELOCITY_TO_WORLD (dx0 + dy0) < SCALED_ONE)
+ SetVelocityComponents (&ElementPtr0->velocity,
+ COSINE (ImpactAngle0,
+ WORLD_TO_VELOCITY (SCALED_ONE) - 1),
+ SINE (ImpactAngle0,
+ WORLD_TO_VELOCITY (SCALED_ONE) - 1));
+ }
+
+ if (!GRAVITY_MASS (ElementPtr1->mass_points + 1))
+ {
+ if (ElementPtr1->state_flags & PLAYER_SHIP)
+ {
+ STARSHIP *StarShipPtr;
+
+ GetElementStarShip (ElementPtr1, &StarShipPtr);
+ StarShipPtr->cur_status_flags &=
+ ~(SHIP_AT_MAX_SPEED | SHIP_BEYOND_MAX_SPEED);
+ if (!(ElementPtr1->state_flags & DEFY_PHYSICS))
+ {
+ if (ElementPtr1->turn_wait < COLLISION_TURN_WAIT)
+ ElementPtr1->turn_wait += COLLISION_TURN_WAIT;
+ if (ElementPtr1->thrust_wait < COLLISION_THRUST_WAIT)
+ ElementPtr1->thrust_wait += COLLISION_THRUST_WAIT;
+ }
+ }
+
+ speed = (SIZE)(scalar / ((long)mass1 * (mass0 + mass1)));
+ DeltaVelocityComponents (&ElementPtr1->velocity,
+ COSINE (ImpactAngle1, speed),
+ SINE (ImpactAngle1, speed));
+
+ GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1);
+ if (dx1 < 0)
+ dx1 = -dx1;
+ if (dy1 < 0)
+ dy1 = -dy1;
+
+ if (VELOCITY_TO_WORLD (dx1 + dy1) < SCALED_ONE)
+ SetVelocityComponents (&ElementPtr1->velocity,
+ COSINE (ImpactAngle1,
+ WORLD_TO_VELOCITY (SCALED_ONE) - 1),
+ SINE (ImpactAngle1,
+ WORLD_TO_VELOCITY (SCALED_ONE) - 1));
+ }
+#ifdef DEBUG_COLLIDE
+ GetCurrentVelocityComponents (&ElementPtr0->velocity, &dx0, &dy0);
+ GetCurrentVelocityComponents (&ElementPtr1->velocity, &dx1, &dy1);
+ log_add (log_Debug, "After: <%d, %d> <%d, %d>\n",
+ dx0, dy0, dx1, dy1);
+#endif /* DEBUG_COLLIDE */
+ }
+}
+