bool Airport::At(Plane &plane) { int x, y; plane.GetPosition(x, y); if ( x == position.x && y == position.y) if (plane.GetHeading() == (heading ^ 4)) if (plane.GetAltitude() == 0) return true; return false; }
bool Navaid::At(Plane &plane) { int x, y; plane.GetPosition(x, y); if (( x == position.x || y == position.y) && plane.ClearedToLand()) { plane.SetClearedToLand(false); plane.SetHeading(heading); plane.SetAltitude(0); return true; } return false; }
int Board::GetPlaneIndex(int x, int y) { x = x/TextWidth; y = y/TextHeight; for (std::set<Plane *>::iterator it = planesIn.begin(); it != planesIn.end(); ++it) { int x1, y1; Plane *plane = *it; plane->GetPosition(x1, y1); if (x1 == x && y1 == y) return plane->GetName() - 'A'; } return -1; }
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(); } } } }
std::string Board::Timed() { std::string rv; In(); for (std::set<Plane *>::iterator it = planesIn.begin(); it != planesIn.end();) { Plane *plane = *it; int n = plane->GetDestination(); bool atFix; if (n >= 10) { navAids[n-10]->At(*plane); atFix = airports[n-10]->At(*plane); if (atFix) { if (plane->GetHeading() == airports[n-10]->GetHeading() ^ 4) { it = planesIn.erase(it); planesDone.insert(plane); continue; } } } else { atFix = fixes[n]->At(*plane); } if (plane->GetAltitude() == 0) { bool at = false; int x, y; int x1, y1; plane->GetPosition(x, y); airports[0]->GetPosition(x1,y1); if (x == x1 && y == y1) at = true; airports[1]->GetPosition(x1,y1); if (x == x1 && y == y1) at = true; if (at) { rv = "Skimmed airport without landing!"; } } if (plane->Move(time)) { if (atFix && plane->OffBoard()) { it = planesIn.erase(it); planesDone.insert(plane); continue; } else if (plane->OffBoard()) { // game over, exit in wrong place if (plane->GetAltitude() < 5) rv = std::string(plane->GetName()) + " left control area at wrong altitude"; else { if ((plane->GetDestination() < 10 && plane->GetHeading() != (fixes[plane->GetDestination()]->GetHeading() ^ 4)) || (plane->GetDestination() >9 && plane->GetHeading() != (airports[plane->GetDestination()-10]->GetHeading() ^ 4))) rv = std::string(plane->GetName()) + " left control area at wrong heading"; else rv = std::string(plane->GetName()) + " left control area at wrong place"; } } } ++it; } for (std::set<Plane *>::iterator it = planesDisplay.begin(); it != planesDisplay.end();) { Plane *plane = *it; if (plane->GetStartTime() <= time) { it = planesDisplay.erase(it); planesIn.insert(plane); continue; } ++it; } if (rv == "") { for (std::set<Plane *>::iterator it1 = planesIn.begin(); rv == "" && it1 != planesIn.end(); ++it1) { Plane *left = *it1; for (std::set<Plane *>::iterator it2 = it1; rv == "" && it2 != planesIn.end(); ++it2) { Plane *right = *it2; if (it1 != it2) { if (left->GetAltitude() == right->GetAltitude()) { int x,y; right->GetPosition(x, y); if (left->dist(x, y) < 4) rv = std::string("Conflict between ") + left->GetName() + " and " + right->GetName(); } } } } } if (rv == "") { for (std::set<Plane *>::iterator it = planesIn.begin(); rv == "" && it != planesIn.end(); ++it) { Plane *plane = *it; if (plane->GetFuel() < 0) { rv = std::string(plane->GetName()) + " out of fuel!"; } } } // game over, they win! if (rv == "" && planesIn.size() == 0 && planesOut.size() ==0 && planesDisplay.size() == 0) rv = "You Won!"; // game over, timeout if (rv == "" && ++time >= maxTime) rv = "Time is up!"; return rv; }
bool Fix::At(Plane &plane) { int x, y; plane.GetPosition(x, y); return (x == position.x || y == position.y) && plane.GetAltitude() >= 5 && (heading ^ 4) == plane.GetHeading(); }