예제 #1
0
void Game::HandleAI(float msecs)
{
    // Run AI for computer planes
    for (int i = activePlayers_; i < TotalPlayers(); i ++)
    {
        // Bail if it's dying or stalled. We're not allowing sniping while stalling, the
        // bots are just too good a shot
        Plane *current = &players_[i];
        if (current->IsDying() || current->IsStalled())
            continue;

        // Find the closets enemy plane
        Plane *target = NULL;
        float currentRange = 9999;
        for (int j = 0; j < TotalPlayers(); j ++)
        {
            if (j == i) // Can't target self
                continue;

            // We're currently ignoring respawning players. May remove this later to make
            // the AI more aggressive
            if (currentRange > current->GetPosition().Distance(players_[j].GetPosition())
                && !players_[j].IsDying() && !players_[j].IsStalled() && !players_[j].IsInvincible())
            {
                target = &players_[j];
                currentRange = current->GetPosition().Distance(target->GetPosition());
            }
        }

        if (target == NULL) // Level off if we don't have a target
        {
            float targetAngle = 0;
            if (targetAngle > current->GetRotation())
                current->TurnLeft(msecs);
            else
                current->TurnRight(msecs);
        }
        else
        {
            // Plot an intercept course!
            Vector2 currentPosition = current->GetPosition();
            Vector2 targetPosition = target->GetPosition();
            Vector2 interceptPoint = Vector2::CollisionPoint(currentPosition, current->GetVelocity(), targetPosition, target->GetVelocity());

            // If the target is running parallel to us, go for them
            //if (interceptPoint.x == 0 && interceptPoint.y == 0)
            //    interceptPoint = targetPosition;
            
            // If the target is in front of us, try and lead it
            // Calculate time for bullet to reach intercept point
            Vector2 bulletStartPos = currentPosition + current->GetVelocity().Normalise() * (20 + MAX_SPEED + 0.5f);
            float bulletTravelTime = (bulletStartPos - interceptPoint).Length() / BULLET_SPEED;
            // Calculate target position at that time
            Vector2 projectedTargetPos = targetPosition + (target->GetVelocity() * bulletTravelTime);

            // Decide if it's worth a shot
            if (interceptPoint.Distance(projectedTargetPos) < 20)
            {
                Bullet *bullet = current->Fire();
                if (bullet != NULL)
                    bullets_.push_back(bullet);
            }

            // Don't play chicken
            // TODO: Turn away from collisions

            // Don't derp
            // TODO: Don't run into the ground

            // Attempt to maneuver for a better shot
            Vector2 currentVelocity = current->GetVelocity().Normalise();
            Vector2 targetVelocity = (currentPosition - projectedTargetPos).Normalise();

            float diffAngle = currentVelocity.Cross(targetVelocity);

            if (diffAngle < 0)
                current->TurnLeft(msecs);
            else
                current->TurnRight(msecs);

            if (DEBUG_RENDERER)
            {
                glBegin(GL_QUADS);
                    glColor3f(0, 0, 0);
                    glVertex2f(interceptPoint.x - 2, interceptPoint.y - 2);
                    glVertex2f(interceptPoint.x + 2, interceptPoint.y - 2);
                    glVertex2f(interceptPoint.x + 2, interceptPoint.y + 2);
                    glVertex2f(interceptPoint.x - 2, interceptPoint.y + 2);
                glEnd();

                glBegin(GL_QUADS);
                    glColor3f(1, 0, 1);
                    glVertex2f(projectedTargetPos.x - 15, projectedTargetPos.y - 15);
                    glVertex2f(projectedTargetPos.x + 15, projectedTargetPos.y - 15);
                    glVertex2f(projectedTargetPos.x + 15, projectedTargetPos.y + 15);
                    glVertex2f(projectedTargetPos.x - 15, projectedTargetPos.y + 15);
                glEnd();
            }
        }
    }
}
예제 #2
0
//----------------------------------------------------------------------------
bool Mgc::SeparatePointSets2D (int iQuantity0, const Vector2* akVertex0,
    int iQuantity1, const Vector2* akVertex1, Line2& rkSeprLine)
{
    // construct convex hull of point set 0
    ConvexHull2D kHull0(iQuantity0,akVertex0);
    kHull0.ByDivideAndConquer();
    int iEdgeQuantity0 = kHull0.GetQuantity();
    const int* aiEdge0 = kHull0.GetIndices();

    // construct convex hull of point set 1
    ConvexHull2D kHull1(iQuantity1,akVertex1);
    kHull1.ByDivideAndConquer();
    int iEdgeQuantity1 = kHull1.GetQuantity();
    const int* aiEdge1 = kHull1.GetIndices();

    // test edges of hull 0 for possible separation of points
    int j0, j1, iI0, iI1, iSide0, iSide1;
    Vector2 kDiff;
    for (j1 = 0, j0 = iEdgeQuantity0-1; j1 < iEdgeQuantity0; j0 = j1++)
    {
        // lookup edge (assert: iI0 != iI1 )
        iI0 = aiEdge0[j0];
        iI1 = aiEdge0[j1];

        // compute potential separating line (assert: (xNor,yNor) != (0,0))
        kDiff = akVertex0[iI1] - akVertex0[iI0];
        rkSeprLine.Normal() = kDiff.Cross();
        rkSeprLine.Constant() = rkSeprLine.Normal().Dot(akVertex0[iI0]);

        // determine if hull 1 is on same side of line
        iSide1 = OnSameSide(rkSeprLine,iEdgeQuantity1,aiEdge1,akVertex1);
        if ( iSide1 )
        {
            // determine which side of line hull 0 lies
            iSide0 = WhichSide(rkSeprLine,iEdgeQuantity0,aiEdge0,akVertex0);

            if ( iSide0*iSide1 <= 0 )  // line separates hulls
                return true;
        }
    }

    // test edges of hull 1 for possible separation of points
    for (j1 = 0, j0 = iEdgeQuantity1-1; j1 < iEdgeQuantity1; j0 = j1++)
    {
        // lookup edge (assert: iI0 != iI1 )
        iI0 = aiEdge1[j0];
        iI1 = aiEdge1[j1];

        // compute perpendicular to edge (assert: (xNor,yNor) != (0,0))
        kDiff = akVertex1[iI1] - akVertex1[iI0];
        rkSeprLine.Normal() = kDiff.Cross();
        rkSeprLine.Constant() = rkSeprLine.Normal().Dot(akVertex1[iI0]);

        // determine if hull 0 is on same side of line
        iSide0 = OnSameSide(rkSeprLine,iEdgeQuantity0,aiEdge0,akVertex0);
        if ( iSide0 )
        {
            // determine which side of line hull 1 lies
            iSide1 = WhichSide(rkSeprLine,iEdgeQuantity1,aiEdge1,akVertex1);

            if ( iSide0*iSide1 <= 0 )  // line separates hulls
                return true;
        }
    }

    return false;
}