float DistancePointShape ( Vector const & V, MultiShape const & S ) { MultiShape::ShapeType type = S.getShapeType(); // ---------- if (type == MultiShape::MST_Sphere) { return DistanceBetween( V, S.getSphere() ); } else if(type == MultiShape::MST_Cylinder) { return DistanceBetween( V, S.getCylinder() ); } else if(type == MultiShape::MST_AxialBox) { return DistanceBetween( V, S.getAxialBox() ); } else if(type == MultiShape::MST_YawedBox) { return DistanceBetween( V, S.getYawedBox() ); } else if(type == MultiShape::MST_OrientedBox) { return DistanceBetween( V, S.getOrientedBox() ); } else { return REAL_MAX; } }
bool Polygon::HasAllEqualSides() const { //simple double side_1, side_2; for (unsigned int i=0;i<points.size()-1;i++) { if (i==points.size()-2) { side_1 = DistanceBetween(points[i],points[i+1]); side_2 = DistanceBetween(points[i+1],points[0]); } else { side_1 = DistanceBetween(points[i],points[i+1]); side_2 = DistanceBetween(points[i+1],points[i+2]); } if (!EqualSides(side_1,side_2)) return false; } return true; }
// --------------------------------------------------------------------------------------------------------------------- bool plasma_tick(const FrameInput& input, FrameOutput& output, FXState& state) { EffectData* data = (EffectData*)state.store; byte r, g; Fix16 mid(8.0f); Fix16 tx1, ty1, tx2, ty2; Fix16 XM1 = data->step.sinMV(0.3f, 3.0f) * data->attractorScales[0]; Fix16 YM1 = data->step.sinMV(0.1f, 2.0f) * data->attractorScales[1]; Fix16 XM2 = data->step.cosMV(0.2f, -3.0f) * data->attractorScales[2]; Fix16 YM2 = data->step.cosMV(0.05f, -5.0f) * data->attractorScales[3]; tx1 = mid + (data->step.sinV(-0.25f) * XM1); ty1 = mid + (data->step.cosV(0.1f) * YM1); tx1 = mid + (data->step.sinMV(-0.5f, 4.0f) * XM2); ty1 = mid + (data->step.cosV(0.1f) * YM2); for (int y=0; y<Constants::FrameHeight; y++) { for (int x=0; x<Constants::FrameWidth; x++) { Fix16 fx((float)x), fy((float)y); fx += fx.sinMV(0.3f, YM1); fy += fy.cosMV(0.3f, XM2); Fix16 dist1 = DistanceBetween(fx, fy, tx1, ty1); Fix16 dist2 = DistanceBetween(fx, fy, tx2, ty2); Fix16 tn = Fix16::atan2(dist1, dist2) * ((data->step.cosM(0.25f) + 2.0f) * 0.8f); tn += data->step * 0.4f; tn += fx.cosMV(0.1f, YM2) * (data->step.sinMV(0.1f, 25.0f) * 0.3f); tn -= fy.sinMV(0.1f, XM1) * (data->step.cosMV(0.1f, 15.0f) * 0.3f); FullSpectrum(tn, r, g); setLED(output.frame, x, y, r, g); } } data->step += 0.1f; return true; }
/*---------------------------------------------------------------------------*/ void ConvertSegmentToPicoFeat(FPOINT *Start, FPOINT *End, FEATURE_SET FeatureSet) { /* ** Parameters: ** Start starting point of pico-feature ** End ending point of pico-feature ** FeatureSet set to add pico-feature to ** Globals: ** classify_pico_feature_length length of a single pico-feature ** Operation: This routine converts an entire segment of an outline ** into a set of pico features which are added to ** FeatureSet. The length of the segment is rounded to the ** nearest whole number of pico-features. The pico-features ** are spaced evenly over the entire segment. ** Return: none (results are placed in FeatureSet) ** Exceptions: none ** History: Tue Apr 30 15:44:34 1991, DSJ, Created. */ FEATURE Feature; FLOAT32 Angle; FLOAT32 Length; int NumFeatures; FPOINT Center; FPOINT Delta; int i; Angle = NormalizedAngleFrom (Start, End, 1.0); Length = DistanceBetween (*Start, *End); NumFeatures = (int) floor (Length / classify_pico_feature_length + 0.5); if (NumFeatures < 1) NumFeatures = 1; /* compute vector for one pico feature */ Delta.x = XDelta (*Start, *End) / NumFeatures; Delta.y = YDelta (*Start, *End) / NumFeatures; /* compute position of first pico feature */ Center.x = Start->x + Delta.x / 2.0; Center.y = Start->y + Delta.y / 2.0; /* compute each pico feature in segment and add to feature set */ for (i = 0; i < NumFeatures; i++) { Feature = NewFeature (&PicoFeatDesc); Feature->Params[PicoFeatDir] = Angle; Feature->Params[PicoFeatX] = Center.x; Feature->Params[PicoFeatY] = Center.y; AddFeature(FeatureSet, Feature); Center.x += Delta.x; Center.y += Delta.y; } } /* ConvertSegmentToPicoFeat */
/* * AttemptFiring * * Have the alien fire at the hero. */ void AttemptFiring (typUnit *unit) { typUnit *missile; /* --- Close enough to shoot at --- */ if (DistanceBetween (hero, unit) < (nScreenWidth / 2)) { /* --- Random chance - less than unit's chance --- */ if ((rand () % 100) < unit->pctFiring) { /* --- Create the missle going after the hero --- */ missile = CreateMissile (unit, hero); /* --- Add to the list of units --- */ unitList = g_list_append (unitList, missile); } } }
/* * CreateMissile * * Missiles are what the aliens fire. They are given * a fixed direction and last a limited amount of time * before they disappear. */ typUnit *CreateMissile (typUnit *alien, typUnit *hero) { float flength; typUnit *missile; /* --- Allocate the memory --- */ missile = (typUnit *) g_malloc (sizeof (typUnit)); /* --- Inialize the structure --- */ missile->bDestroy = FALSE; missile->pctFiring = 0; missile->type = MISSILE; missile->x = alien->x; missile->y = alien->y; /* --- Calculate missile velocity --- */ missile->vx = (float) DistanceBetween (missile, hero) * Direction (missile, hero); missile->vy = (float) (hero->y - alien->y); /* * Adjust missile velocity */ flength = sqrt (missile->vx * missile->vx + missile->vy * missile->vy); if (flength < .1) flength = .1; flength /= 3; missile->vx /= flength; missile->vy /= flength; missile->lockunit = NULL; /* * --- This missile has a life, when it goes to zero, * it gets destroyed. */ missile->life = 60; return (missile); }
int Polygon::AdjacentEqualSides() const { //for kite/arrow int count = 0; double side_1, side_2; for (unsigned int i=0;i<points.size();i++) { if (i==points.size()-1) { side_1 = DistanceBetween(points[i], points[0]); side_2 = DistanceBetween(points[0], points[1]); } else if (i==points.size()-2) { side_1 = DistanceBetween(points[i], points[i+1]); side_2 = DistanceBetween(points[i+1], points[0]); } else { side_1 = DistanceBetween(points[i], points[i+1]); side_2 = DistanceBetween(points[i+1], points[i+2]); } if (EqualSides(side_1,side_2)) { count++; } } return count; }
/* * AIModule * * Contains the logic for each of the units to move. * Some units like landers are looking for people to * pick up. Mutuants hunt down the player. Missiles * just go until they die, etc. */ void AIModule (typUnit *unit) { typUnit *tmp; int bestdist = 50000; typUnit *closest = NULL; GList *node; /* * Alien lander AI logic */ if (unit->type == LANDER) { /* --- if the alien's locked on a person --- */ if (unit->lockunit) { /* --- Move it up. --- */ closest = unit->lockunit; unit->y -= .5; closest->y -= .5; /* --- If alien's made it to the top --- */ if (unit->y - (sprite_lander[0].height / 2) < RADAR_HEIGHT) { /* --- Assimilate human! --- */ unit->y = RADAR_HEIGHT + (sprite_lander[0].height / 2); unit->type = MUTANT; unit->pctFiring = MUTANT_TRIGGER_PCT; unit->lockunit = NULL; closest->bDestroy = TRUE; } return; } /* --- Any people nearby to snatch? --- */ for (node = unitList; node; node = node->next) { tmp = (typUnit *) node->data; if (tmp->type == PERSON && tmp->lockunit == NULL) { /* --- Look for a closer person --- */ if (DistanceBetween (unit, tmp) < bestdist) { closest = tmp; bestdist = DistanceBetween (unit, tmp); } } } /* --- We're locked onto a target --- */ if (bestdist <= 1) { /* --- Scootch it over a bit --- */ unit->vx = 0; unit->x = closest->x; /* * --- Check for a lock... --- */ if ((unit->y + (sprite_lander[0].height / 2) + .8) < (closest->y - (sprite_man[0].height / 2))) { /* --- Come down on it. --- */ unit->y += .5; } else if ((unit->y + (sprite_lander[0].height / 2)) > (closest->y - (sprite_man[0].height / 2))) { unit->y -= .5; } else { /* --- Lock it in --- */ unit->lockunit = closest; closest->lockunit = unit; closest->life = 20; } /* --- Anything in reasonable range? --- */ } else if (bestdist < 20) { /* --- Move towards it --- */ unit->vx = Direction (unit, closest); unit->x += unit->vx; } else { /* * --- Nothing nearby. Move in a random direction. */ if (unit->vx == 0) { if ((rand () % 2) == 0) { unit->vx = 1; } else { unit->vx = -1; } } unit->x += unit->vx; } /* * See if there is anything worth shooting at. */ AttemptFiring (unit); /* * Mutant AI logic */ } else if (unit->type == MUTANT) { /* * --- Lets go crazy. Mutant moves almost randomly yet * slowly towards the player. */ unit->vx = Direction (unit, hero) * ((rand () % 4) + 1); unit->vy = rand () % 5 - 2; /* * If the hero is within smelling distance, move towards * player in the -y- direction. */ if (DistanceBetween (unit, hero) < 200) { if (unit->y < hero->y) unit->vy++; if (unit->y > hero->y) unit->vy--; } /* --- Finally move the unit --- */ Move (unit); /* --- Let the mutant attempt firing --- */ AttemptFiring (unit); /* * --- Missiles and explosions */ } else if ((unit->type == MISSILE) || (unit->type == EXPLOSION)) { /* --- These have a life. Decrement it. --- */ unit->life --; /* --- Move it. --- */ Move (unit); /* --- When it reaches zero, destroy it --- */ if (unit->life <= 0) { unit->bDestroy = TRUE; } /* * Person AI. */ } else if (unit->type == PERSON) { /* * Only time person moves by itself is when it's falling * from the sky after the alien carrying it has been shot. */ if (unit->lockunit == NULL && unit->y < PERSON_HEIGHT) { /* --- Move it down --- */ unit->y += 2; } } }
/* * DisplayOtherUnits * * Display all the units on the screen. First, we need * to move each of the units to their new positions. * Some of this is done in the AI module. * */ void DisplayOtherUnits (GdkPixmap *pixmap, GtkWidget *drawing_area) { typUnit *unit; typUnit *unitHit; GList *node; int xPos; int xPosEnd; typSprite *sprite; /* --- Each unit in the list --- */ for (node = unitList; node; node = node->next) { /* --- Get the unit --- */ unit = (typUnit *) node->data; /* * --- Run the AI module on it to move it --- */ AIModule (unit); /* * If the unit was destroyed by the AI, * don't draw the unit. */ if (unit->bDestroy) { continue; } /* * If there's no sprite for the unit, * we can't draw it now, can we? */ sprite = GetSprite (unit); if (sprite == NULL) continue; /* --- Where on the screen is it going? --- */ xPos = UnitScreenX (unit); /* --- Make sure unit doesn't go out of bounds --- */ AdjustSpriteHeight (unit); /* --- Finally draw unit --- */ DisplaySprite (drawing_area, sprite, (int) (xPos - sprite[0].width / 2), (int) (unit->y - sprite[0].height / 2)); } /* * --- once everyone is painted, fire the lasers. */ for (node = unitList; node; node = node->next) { unit = (typUnit *) node->data; /* --- If this is a laser --- */ if (unit->type == LASER) { /* --- Get starting and ending positions --- */ xPos = ScreenX ((int) unit->x); xPosEnd = xPos + LASER_LENGTH * unit->direction; /* --- See if anything was hit --- */ unitHit = AnyoneBetween ((int) xPos, (int) unit->y, (int) xPosEnd, (int) unit->y); if (unitHit) { /* --- Something was hit --- */ /* --- Laser shot only goes this far --- */ xPosEnd = UnitScreenX (unitHit); /* --- Destroy the unit --- */ unitHit->bDestroy = TRUE; unit->bDestroy = TRUE; /* --- Special effects of destruction --- */ AddExplosion (unitHit); } /* --- Draw the laser --- */ gdk_draw_line (pixmap, penWhite, xPos, unit->y, xPosEnd, unit->y); /* --- Get real coordinates of laser --- */ unit->x = GameX (xPosEnd); /* --- If laser has gone too far... --- */ if (DistanceBetween (unit, hero) > nScreenWidth / 2) { /* --- destroy it --- */ unit->bDestroy = TRUE; } } } }
EarClipper::VertexList::iterator EarClipper::DetermineMutuallyVisibleVertexFromRayCastResult(const FVector2& maxInteriorPoint, const FVector2& intersectionPointOnEdge, VertexList::iterator pointOnEdgeWithMaximumXIter) { VertexList::iterator verticesEnd = vertices.end(); VertexList::iterator mutuallyVisibleVertexIter = verticesEnd; // Form a triangle with P (see explanation of a) above) (P1), the intersection point on // the edge (P2) and the point on the edge with maximum X (P3). // // If no points on the outer polygon fall on this triangle, then P3 is the visible vertex. // // Otherwise, the reflex vertex of the outer polygon that falls into this triangle and // minimizes the angle to the ray (i.e. x axis) is the mutually visible vertex Triangle2D_t checkTriangle(maxInteriorPoint, intersectionPointOnEdge, *(pointOnEdgeWithMaximumXIter->point)); VertexListIteratorList reflexVerticesOnTriangle; bool hasAnyReflexVerticesOnTriangle = false; for (VertexList::iterator vertexIterator = vertices.begin(); vertexIterator != verticesEnd; ++vertexIterator) { if (checkTriangle.PointIsOnPolygon(*(vertexIterator->point), EXPERIMENTAL_TOLERANCE)) { if (GetConvexOrReflexVertexType(vertexIterator) == VertexType::Reflex) { reflexVerticesOnTriangle.push_front(vertexIterator); hasAnyReflexVerticesOnTriangle = true; } } } if (hasAnyReflexVerticesOnTriangle) { mutuallyVisibleVertexIter = reflexVerticesOnTriangle.front(); reflexVerticesOnTriangle.pop_front(); float minDistance = DistanceBetween(*(mutuallyVisibleVertexIter->point), maxInteriorPoint); float minAngle = AngleBetweenRadians(*(mutuallyVisibleVertexIter->point) - maxInteriorPoint, Vec2D::XAxis() ); for (const VertexList::iterator& reflexVertexIter : reflexVerticesOnTriangle) { float angle = AngleBetweenRadians(*(reflexVertexIter->point) - maxInteriorPoint, Vec2D::XAxis() ); float distance = DistanceBetween(*(reflexVertexIter->point), maxInteriorPoint); if (angle < minAngle) { minAngle = angle; mutuallyVisibleVertexIter = reflexVertexIter; minDistance = distance; } else if (angle == minAngle) { if (distance < minDistance) { minAngle = angle; mutuallyVisibleVertexIter = reflexVertexIter; minDistance = distance; } } } } else { mutuallyVisibleVertexIter = pointOnEdgeWithMaximumXIter; } return mutuallyVisibleVertexIter; }