//----------------------------------------------------------------------------- void SoccerWorld::updateAIData() { if (isRaceOver()) return; // Fill the kart distance map m_red_kdm.clear(); m_blue_kdm.clear(); for (unsigned int i = 0; i < m_karts.size(); ++i) { if (UserConfigParams::m_arena_ai_stats && m_karts[i]->getController()->isPlayerController()) continue; if (getKartTeam(m_karts[i]->getWorldKartId()) == SOCCER_TEAM_RED) { Vec3 rd = m_karts[i]->getXYZ() - getBallPosition(); m_red_kdm.push_back(KartDistanceMap(i, rd.length_2d())); } else { Vec3 bd = m_karts[i]->getXYZ() - getBallPosition(); m_blue_kdm.push_back(KartDistanceMap(i, bd.length_2d())); } } // Sort the vectors, so first vector will have the min distance std::sort(m_red_kdm.begin(), m_red_kdm.end()); std::sort(m_blue_kdm.begin(), m_blue_kdm.end()); // Fill Ball and goals data m_bgd.updateBallAndGoal(getBallPosition(), getBallHeading()); } // updateAIData
/** Localize the ball on the navigation mesh. */ void SoccerWorld::updateBallPosition(float dt) { if (isRaceOver()) return; m_ball_position = m_ball->getPresentation<TrackObjectPresentationMesh>() ->getNode()->getPosition(); if (m_track->hasNavMesh()) { m_ball_on_node = BattleGraph::get()->pointToNode(m_ball_on_node, m_ball_position, true/*ignore_vertical*/); if (m_ball_on_node == BattleGraph::UNKNOWN_POLY && World::getWorld()->getPhase() == RACE_PHASE) { m_ball_invalid_timer += dt; // Reset the ball and karts if out of navmesh after 2 seconds if (m_ball_invalid_timer >= 2.0f) { m_ball_invalid_timer = 0.0f; resetBall(); for (unsigned int i = 0; i < m_karts.size(); i++) moveKartAfterRescue(m_karts[i]); } } else m_ball_invalid_timer = 0.0f; } } // updateBallPosition
/** Localize the ball on the navigation mesh. */ void SoccerWorld::updateBallPosition(int ticks) { if (isRaceOver()) return; if (!ballNotMoving()) { // Only update heading if the ball is moving m_ball_heading = atan2f(m_ball_body->getLinearVelocity().getX(), m_ball_body->getLinearVelocity().getZ()); } if (Track::getCurrentTrack()->hasNavMesh()) { m_ball_track_sector ->update(getBallPosition(), true/*ignore_vertical*/); if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE) { m_ball_invalid_timer += ticks; // Reset the ball and karts if out of navmesh after 2 seconds if (m_ball_invalid_timer >= stk_config->time2Ticks(2.0f)) { m_ball_invalid_timer = 0; m_ball->reset(); for (unsigned int i = 0; i < m_karts.size(); i++) moveKartAfterRescue(m_karts[i]); if (UserConfigParams::m_arena_ai_stats) getKart(8)->flyUp(); } } else m_ball_invalid_timer = 0; } } // updateBallPosition
//----------------------------------------------------------------------------- void SoccerWorld::onCheckGoalTriggered(bool first_goal) { if (isRaceOver() || isStartPhase()) return; setPhase(WorldStatus::GOAL_PHASE); m_goal_sound->play(); if (m_ball_hitter != -1) { if (UserConfigParams::m_arena_ai_stats) { const int elapsed_frame = m_goal_frame.empty() ? 0 : std::accumulate(m_goal_frame.begin(), m_goal_frame.end(), 0); m_goal_frame.push_back(m_frame_count - elapsed_frame); } ScorerData sd; sd.m_id = m_ball_hitter; sd.m_correct_goal = isCorrectGoal(m_ball_hitter, first_goal); if (sd.m_correct_goal) { m_karts[m_ball_hitter]->getKartModel() ->setAnimation(KartModel::AF_WIN_START, true/* play_non_loop*/); } else if (!sd.m_correct_goal) { m_karts[m_ball_hitter]->getKartModel() ->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/); } if (first_goal) { // Notice: true first_goal means it's blue goal being shoot, // so red team can score m_red_scorers.push_back(sd); if (race_manager->hasTimeTarget()) { m_red_score_times.push_back(race_manager->getTimeTarget() - getTime()); } else m_red_score_times.push_back(getTime()); } else { m_blue_scorers.push_back(sd); if (race_manager->hasTimeTarget()) { m_blue_score_times.push_back(race_manager->getTimeTarget() - getTime()); } else m_blue_score_times.push_back(getTime()); } } m_ball->reset(); } // onCheckGoalTriggered
/** This is the main interface to update the world. This function calls * update(), and checks then for the end of the race. Note that race over * handling can not necessarily be done in update(), since not all * data structures might have been updated (e.g.LinearWorld must * call World::update() first, to get updated kart positions. If race * over would be handled in World::update, LinearWorld had no opportunity * to update its data structures before the race is finished). * \param dt Time step size. */ void World::updateWorld(float dt) { if (m_schedule_pause) { pause(m_scheduled_pause_phase); m_schedule_pause = false; } else if (m_schedule_unpause) { unpause(); m_schedule_unpause = false; } if (m_self_destruct) { delete this; return; } // Don't update world if a menu is shown or the race is over. if( getPhase() == FINISH_PHASE || getPhase() == IN_GAME_MENU_PHASE ) return; update(dt); if( (!isFinishPhase()) && isRaceOver()) { enterRaceOverState(); } } // updateWorld
//Método principal para atualização do game em tempo real void Game::gameUpdate(){ //Limite de Frame Rate gameWindow.setFramerateLimit(60); //Checa se algum dos players completou as 3 voltas isRaceOver(); //Verifica se a tecla ESC é pressionada, abrindo o menuPause renderPause(); if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) menuPause.abrirMenu(); //Toca a música que será reproduzida durante a corrida raceBGM.playMusic(); raceBGM.setVolume(100); //Ativa os métodos de entrada de keyboard para os controles de ambos os players player[0].ativarMovimentos(0); player[1].ativarMovimentos(1); //Checa todas as colisões possíveis dentro da partida para cada Player checkCollision(0); checkCollision(1); //Checa se os players estão no sentido correto da pista (caso eles percorram ao contrário), seus //carros explodirão player[0].checarSentido(); player[1].checarSentido(); //Checa durante a partida quando a linha de chegada é ultrapassada checkLap(); //Centralizando cada câmera em seu respectivo player player[0].centralizarCamera(); player[1].centralizarCamera(); //Renderizações na tela do Player1 gameWindow.setView(player[0].getCamera()); renderMap(); gameWindow.draw(player[0].getSprite()); gameWindow.draw(player[1].getSprite()); renderProjeteis(); renderGUI(0); //Renderizações na tela do Player 2 gameWindow.setView(player[1].getCamera()); renderMap(); gameWindow.draw(player[1].getSprite()); gameWindow.draw(player[0].getSprite()); renderProjeteis(); renderGUI(1); gameWindow.display(); gameWindow.clear(); }
//----------------------------------------------------------------------------- void SoccerWorld::onCheckGoalTriggered(bool first_goal) { if (isRaceOver() || isStartPhase()) return; setPhase(WorldStatus::GOAL_PHASE); m_goal_sound->play(); if (m_ball_hitter != -1) { ScorerData sd; sd.m_id = m_ball_hitter; sd.m_correct_goal = isCorrectGoal(m_ball_hitter, first_goal); if (sd.m_correct_goal) { m_karts[m_ball_hitter]->getKartModel() ->setAnimation(KartModel::AF_WIN_START, true/* play_non_loop*/); } else if (!sd.m_correct_goal) { m_karts[m_ball_hitter]->getKartModel() ->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/); } if (first_goal) { // Notice: true first_goal means it's blue goal being shoot, // so red team can score m_red_scorers.push_back(sd); if (race_manager->hasTimeTarget()) { m_red_score_times.push_back(race_manager->getTimeTarget() - getTime()); } else m_red_score_times.push_back(getTime()); } else { m_blue_scorers.push_back(sd); if (race_manager->hasTimeTarget()) { m_blue_score_times.push_back(race_manager->getTimeTarget() - getTime()); } else m_blue_score_times.push_back(getTime()); } } m_ball->reset(); } // onCheckGoalTriggered
/** Updates the m_kart_on_node value of each kart to localize it * on the navigation mesh. */ void SoccerWorld::updateKartNodes() { if (isRaceOver()) return; const unsigned int n = getNumKarts(); for (unsigned int i = 0; i < n; i++) { if (m_karts[i]->isEliminated()) continue; m_kart_on_node[i] = BattleGraph::get()->pointToNode(m_kart_on_node[i], m_karts[i]->getXYZ(), false/*ignore_vertical*/); } } // updateKartNodes
/** Localize each kart on the graph using its center xyz. */ void WorldWithRank::updateSectorForKarts() { if (isRaceOver()) return; const unsigned int n = getNumKarts(); assert(n == m_kart_track_sector.size()); for (unsigned int i = 0; i < n; i++) { SpareTireAI* sta = dynamic_cast<SpareTireAI*>(m_karts[i]->getController()); if (!m_karts[i]->isEliminated() || (sta && sta->isMoving())) getTrackSector(i)->update(m_karts[i]->getXYZ()); } } // updateSectorForKarts
//----------------------------------------------------------------------------- void SoccerWorld::updateDefenders() { if (isRaceOver()) return; float distance = 99999.9f; int defender = -1; // Check for red team for (unsigned int i = 0; i < (unsigned)m_karts.size(); ++i) { if (m_karts[i]->getController()->isPlayerController() || getKartTeam(m_karts[i]->getWorldKartId()) != SOCCER_TEAM_RED) continue; Vec3 d = this->getGoalLocation(SOCCER_TEAM_RED, CheckGoal::POINT_CENTER) - m_karts[i]->getXYZ(); if (d.length_2d() <= distance) { defender = i; distance = d.length_2d(); } } if (defender != -1) m_red_defender = defender; distance = 99999.9f; defender = -1; // Check for blue team for (unsigned int i = 0; i < (unsigned)m_karts.size(); ++i) { if (m_karts[i]->getController()->isPlayerController() || getKartTeam(m_karts[i]->getWorldKartId()) != SOCCER_TEAM_BLUE) continue; Vec3 d = this->getGoalLocation(SOCCER_TEAM_BLUE, CheckGoal::POINT_CENTER) - m_karts[i]->getXYZ(); if (d.length_2d() <= distance) { defender = i; distance = d.length_2d(); } } if (defender != -1) m_blue_defender = defender; } // updateDefenders
/** Update the world and the track. * \param dt Time step size. */ void SoccerWorld::update(float dt) { updateBallPosition(dt); if (m_track->hasNavMesh()) { updateKartNodes(); updateAIData(); } WorldWithRank::update(dt); WorldWithRank::updateTrack(dt); if (getPhase() == World::GOAL_PHASE) { if (m_goal_timer == 0.0f) { // Stop all karts for (unsigned int i = 0; i < m_karts.size(); i++) m_karts[i]->setVelocity(btVector3(0, 0, 0)); } m_goal_timer += dt; if (m_goal_timer > 3.0f) { setPhase(WorldStatus::RACE_PHASE); m_goal_timer = 0.0f; if (!isRaceOver()) { // Reset all karts for (unsigned int i = 0; i < m_karts.size(); i++) moveKartAfterRescue(m_karts[i]); if (UserConfigParams::m_arena_ai_stats) getKart(8)->flyUp(); } } } if (UserConfigParams::m_arena_ai_stats) m_frame_count++; } // update
/** Update the world and the track. * \param ticks Physics time steps - should be 1. */ void SoccerWorld::update(int ticks) { updateBallPosition(ticks); if (Track::getCurrentTrack()->hasNavMesh()) { updateSectorForKarts(); updateAIData(); } WorldWithRank::update(ticks); WorldWithRank::updateTrack(ticks); if (getPhase() == World::GOAL_PHASE) { if (m_goal_timer == 0) { // Stop all karts for (unsigned int i = 0; i < m_karts.size(); i++) m_karts[i]->setVelocity(btVector3(0, 0, 0)); } m_goal_timer += ticks; if (m_goal_timer > stk_config->time2Ticks(3.0f)) { setPhase(WorldStatus::RACE_PHASE); m_goal_timer = 0; if (!isRaceOver()) { // Reset all karts for (unsigned int i = 0; i < m_karts.size(); i++) moveKartAfterRescue(m_karts[i]); if (UserConfigParams::m_arena_ai_stats) getKart(8)->flyUp(); } } } if (UserConfigParams::m_arena_ai_stats) m_frame_count++; } // update
/** Update the world and the track. * \param dt Time step size. */ void SoccerWorld::update(float dt) { World *world = World::getWorld(); WorldWithRank::update(dt); WorldWithRank::updateTrack(dt); updateBallPosition(dt); if (m_track->hasNavMesh()) { updateKartNodes(); updateDefenders(); } if (world->getPhase() == World::GOAL_PHASE) { if (m_goal_timer == 0.0f) { // Stop all karts for (unsigned int i = 0; i < m_karts.size(); i++) m_karts[i]->setVelocity(btVector3(0, 0, 0)); } m_goal_timer += dt; if (m_goal_timer > 3.0f) { world->setPhase(WorldStatus::RACE_PHASE); m_goal_timer = 0.0f; if (!isRaceOver()) { // Reset all karts for (unsigned int i = 0; i < m_karts.size(); i++) moveKartAfterRescue(m_karts[i]); } } } } // update
/** Localize the ball on the navigation mesh. */ void SoccerWorld::updateBallPosition(float dt) { if (isRaceOver()) return; if (!ballNotMoving()) { // Only update heading if the ball is moving m_ball_heading = atan2f(m_ball_body->getLinearVelocity().getX(), m_ball_body->getLinearVelocity().getZ()); } if (m_track->hasNavMesh()) { m_ball_on_node = BattleGraph::get()->pointToNode(m_ball_on_node, getBallPosition(), true/*ignore_vertical*/); if (m_ball_on_node == BattleGraph::UNKNOWN_POLY && getPhase() == RACE_PHASE) { m_ball_invalid_timer += dt; // Reset the ball and karts if out of navmesh after 2 seconds if (m_ball_invalid_timer >= 2.0f) { m_ball_invalid_timer = 0.0f; m_ball->reset(); for (unsigned int i = 0; i < m_karts.size(); i++) moveKartAfterRescue(m_karts[i]); if (UserConfigParams::m_arena_ai_stats) getKart(8)->flyUp(); } } else m_ball_invalid_timer = 0.0f; } } // updateBallPosition
/** This is the main interface to update the world. This function calls * update(), and checks then for the end of the race. Note that race over * handling can not necessarily be done in update(), since not all * data structures might have been updated (e.g.LinearWorld must * call World::update() first, to get updated kart positions. If race * over would be handled in World::update, LinearWorld had no opportunity * to update its data structures before the race is finished). * \param dt Time step size. */ void World::updateWorld(float dt) { #ifdef DEBUG assert(m_magic_number == 0xB01D6543); #endif if (m_schedule_pause) { pause(m_scheduled_pause_phase); m_schedule_pause = false; } else if (m_schedule_unpause) { unpause(); m_schedule_unpause = false; } if (m_self_destruct) { delete this; return; } // Don't update world if a menu is shown or the race is over. if( getPhase() == FINISH_PHASE || getPhase() == IN_GAME_MENU_PHASE ) return; try { update(dt); } catch (AbortWorldUpdateException& e) { (void)e; // avoid compiler warning return; } #ifdef DEBUG assert(m_magic_number == 0xB01D6543); #endif if( (!isFinishPhase()) && isRaceOver()) { enterRaceOverState(); } else { if (m_schedule_exit_race) { m_schedule_exit_race = false; race_manager->exitRace(false); race_manager->setAIKartOverride(""); StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance()); if (m_schedule_tutorial) { m_schedule_tutorial = false; race_manager->setNumLocalPlayers(1); race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE); race_manager->setMinorMode (RaceManager::MINOR_MODE_TUTORIAL); race_manager->setNumKarts( 1 ); race_manager->setTrack( "tutorial" ); race_manager->setDifficulty(RaceManager::DIFFICULTY_EASY); race_manager->setReverseTrack(false); // Use keyboard 0 by default (FIXME: let player choose?) InputDevice* device = input_manager->getDeviceManager()->getKeyboard(0); // Create player and associate player with keyboard StateManager::get()->createActivePlayer(PlayerManager::getCurrentPlayer(), device); if (!kart_properties_manager->getKart(UserConfigParams::m_default_kart)) { Log::warn("[World]", "Cannot find kart '%s', will revert to default.", UserConfigParams::m_default_kart.c_str()); UserConfigParams::m_default_kart.revertToDefaults(); } race_manager->setLocalKartInfo(0, UserConfigParams::m_default_kart); // ASSIGN should make sure that only input from assigned devices // is read. input_manager->getDeviceManager()->setAssignMode(ASSIGN); input_manager->getDeviceManager() ->setSinglePlayer( StateManager::get()->getActivePlayer(0) ); delete this; StateManager::get()->enterGameState(); race_manager->setupPlayerKartInfo(); race_manager->startNew(true); } else { delete this; if (race_manager->raceWasStartedFromOverworld()) { OverWorld::enterOverWorld(); } } } } } // updateWorld
//----------------------------------------------------------------------------- void SoccerWorld::onCheckGoalTriggered(bool first_goal) { if (isRaceOver()) return; if (m_can_score_points) { m_team_goals[first_goal ? 0 : 1]++; World *world = World::getWorld(); world->setPhase(WorldStatus::GOAL_PHASE); m_goal_sound->play(); if(m_lastKartToHitBall != -1) { if(first_goal) { m_redScorers.push_back(m_lastKartToHitBall); if(race_manager->hasTimeTarget()) m_redScoreTimes.push_back(race_manager->getTimeTarget() - world->getTime()); else m_redScoreTimes.push_back(world->getTime()); } else { m_blueScorers.push_back(m_lastKartToHitBall); if(race_manager->hasTimeTarget()) m_blueScoreTimes.push_back(race_manager->getTimeTarget() - world->getTime()); else m_blueScoreTimes.push_back(world->getTime()); } } } // Reset original positions for the soccer balls TrackObjectManager* tom = getTrack()->getTrackObjectManager(); assert(tom); PtrVector<TrackObject>& objects = tom->getObjects(); for(unsigned int i=0; i<objects.size(); i++) { TrackObject* obj = objects.get(i); if(!obj->isSoccerBall()) continue; obj->reset(); obj->getPhysicalObject()->reset(); } //Resetting the ball triggers the goal check line one more time. //This ensures that only one goal is counted, and the second is ignored. m_can_score_points = !m_can_score_points; //for(int i=0 ; i < getNumKarts() ; i++ /*if(World::getWorld()->getTrack()->isAutoRescueEnabled() && !getKartAnimation() && fabs(getRoll())>60*DEGREE_TO_RAD && fabs(getSpeed())<3.0f ) { new RescueAnimation(this, true); }*/ // TODO: rescue the karts } // onCheckGoalTriggered
//----------------------------------------------------------------------------- void SoccerWorld::onCheckGoalTriggered(bool first_goal) { if (isRaceOver() || isStartPhase()) return; if (m_can_score_points) { (first_goal ? m_red_goal++ : m_blue_goal++); World *world = World::getWorld(); world->setPhase(WorldStatus::GOAL_PHASE); m_goal_sound->play(); if (m_ball_hitter != -1) { ScorerData sd; sd.m_id = m_ball_hitter; sd.m_correct_goal = isCorrectGoal(m_ball_hitter, first_goal); if (sd.m_correct_goal) { m_karts[m_ball_hitter]->getKartModel() ->setAnimation(KartModel::AF_WIN_START, true/* play_non_loop*/); } else if (!sd.m_correct_goal) { m_karts[m_ball_hitter]->getKartModel() ->setAnimation(KartModel::AF_LOSE_START, true/* play_non_loop*/); } if (first_goal) { // Notice: true first_goal means it's blue goal being shoot, // so red team can score m_red_scorers.push_back(sd); if(race_manager->hasTimeTarget()) { m_red_score_times.push_back(race_manager ->getTimeTarget() - world->getTime()); } else m_red_score_times.push_back(world->getTime()); } else { m_blue_scorers.push_back(sd); if (race_manager->hasTimeTarget()) { m_blue_score_times.push_back(race_manager ->getTimeTarget() - world->getTime()); } else m_blue_score_times.push_back(world->getTime()); } } } resetBall(); //Resetting the ball triggers the goal check line one more time. //This ensures that only one goal is counted, and the second is ignored. m_can_score_points = !m_can_score_points; } // onCheckGoalTriggered
/** Called when a kart must be eliminated. */ void FollowTheLeaderRace::countdownReachedZero() { if(m_leader_intervals.size()>1) m_leader_intervals.erase(m_leader_intervals.begin()); WorldStatus::setTime(m_leader_intervals[0]); // If the leader kart is not the first kart, remove the first // kart, otherwise remove the last kart. int position_to_remove = m_karts[0]->getPosition()==1 ? getCurrentNumKarts() : 1; AbstractKart *kart = getKartAtPosition(position_to_remove); if(!kart || kart->isEliminated()) { fprintf(stderr,"Problem with removing leader: position %d not found\n", position_to_remove); for(unsigned int i=0; i<m_karts.size(); i++) { fprintf(stderr,"kart %d: eliminated %d position %d\n", i,m_karts[i]->isEliminated(), m_karts[i]->getPosition()); } // for i } // else { if(UserConfigParams::m_ftl_debug) { printf("[ftl] Eliminiating kart '%s' at position %d.\n", kart->getIdent().c_str(), position_to_remove); } eliminateKart(kart->getWorldKartId()); // In case that the kart on position 1 was removed, we have // to set the correct position (which equals the remaining // number of karts) for the removed kart, as well as recompute // the position for all other karts if(position_to_remove==1) { // We have to add 1 to the number of karts to get the correct // position, since the eliminated kart was already removed // from the value returned by getCurrentNumKarts (and we have // to remove the kart before we can call updateRacePosition). // Note that we can not call WorldWithRank::setKartPosition // here, since it would not properly support debugging kart // ranks (since this kart would get its position set again // in updateRacePosition). We only set the rank of the eliminated // kart, and updateRacePosition will then call setKartPosition // for the now eliminated kart. kart->setPosition(getCurrentNumKarts()+1); updateRacePosition(); } // Time doesn't make any sense in FTL (and it is not displayed) kart->finishedRace(-1.0f); // Move any camera for this kart to the leader, facing backwards, // so that the eliminated player has something to watch. if (race_manager->getNumPlayers() > 1) { for(unsigned int i=0; i<Camera::getNumCameras(); i++) { Camera *camera = Camera::getCamera(i); if(camera->getKart()==kart) { camera->setMode(Camera::CM_LEADER_MODE); camera->setKart(getKart(0)); } } // for i<number of cameras } } // if kart to eliminate exists // almost over, use fast music if(getCurrentNumKarts()==3) { music_manager->switchToFastMusic(); } if (isRaceOver()) { // Handle special FTL situation: the leader is kart number 3 when // the last kart gets eliminated. In this case kart on position 1 // is eliminated, and the kart formerly on position 2 is on // position 1, the leader now position 2. In this case the kart // on position 1 would get more points for this victory. So if // this is the case, change the position if(m_karts[0]->getPosition()!=1) { // Adjust the position of all still driving karts that // are ahead of the leader by +1, and move the leader // to position 1. for (unsigned int i=1; i<m_karts.size(); i++) { if(!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated() && m_karts[i]->getPosition()<m_karts[0]->getPosition()) { m_karts[i]->setPosition(m_karts[i]->getPosition()+1); } } m_karts[0]->setPosition(1); } // Mark all still racing karts to be finished. for (unsigned int n=0; n<m_karts.size(); n++) { if (!m_karts[n]->isEliminated() && !m_karts[n]->hasFinishedRace()) { m_karts[n]->finishedRace(getTime()); } } } // End of race is detected from World::updateWorld() } // countdownReachedZero