/** Initializes the soccer world. It sets up the data structure * to keep track of points etc. for each kart. */ void SoccerWorld::init() { m_kart_team_map.clear(); m_kart_position_map.clear(); WorldWithRank::init(); m_display_rank = false; m_goal_timer = 0.0f; m_ball_hitter = -1; m_ball = NULL; m_ball_body = NULL; m_goal_target = race_manager->getMaxGoal(); m_goal_sound = SFXManager::get()->createSoundSource("goal_scored"); 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; m_ball = obj; m_ball_body = m_ball->getPhysicalObject()->getBody(); // Handle one ball only break; } if (!m_ball) Log::fatal("SoccerWorld","Ball is missing in soccer field, abort."); m_bgd.init(m_ball->getPhysicalObject()->getRadius()); } // init
/** * Checks the soccer balls to see if they crossed the line and trigger the goal accordingly. */ void CheckGoal::update(float dt) { World *world = World::getWorld(); assert(world); Track* track = world->getTrack(); assert(track); TrackObjectManager* tom = track->getTrackObjectManager(); assert(tom); PtrVector<TrackObject>& objects = tom->getObjects(); unsigned int ball_index = 0; for(int i=0; i<objects.size(); i++) { TrackObject* obj = objects.get(i); if(!obj->isSoccerBall()) continue; const Vec3 &xyz = obj->getPresentation<TrackObjectPresentationMesh>()->getNode()->getPosition(); if(isTriggered(m_previous_position[ball_index], xyz, ball_index)) { if(UserConfigParams::m_check_debug) printf("CHECK: Goal check structure %d triggered for object %s.\n", m_index, obj->getPresentation<TrackObjectPresentationMesh>()->getNode()->getDebugName()); trigger(ball_index); } m_previous_position[ball_index] = xyz; ball_index++; } }
/** Called when a soccer game is restarted. */ void SoccerWorld::reset() { WorldWithRank::reset(); if(race_manager->hasTimeTarget()) { WorldStatus::setClockMode(WorldStatus::CLOCK_COUNTDOWN, race_manager->getTimeTarget()); m_count_down_reached_zero = false; } else WorldStatus::setClockMode(CLOCK_CHRONO); m_can_score_points = true; m_red_goal = 0; m_blue_goal = 0; m_red_scorers.clear(); m_red_score_times.clear(); m_blue_scorers.clear(); m_blue_score_times.clear(); m_ball_hitter = -1; m_ball = NULL; m_red_defender = -1; m_blue_defender = -1; m_ball_invalid_timer = 0.0f; 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; m_ball = obj; // Handle one ball only break; } if (!m_ball) Log::fatal("SoccerWorld","Ball is missing in soccer field, abort."); if (m_goal_sound != NULL && m_goal_sound->getStatus() == SFXBase::SFX_PLAYING) { m_goal_sound->stop(); } initKartList(); resetAllPosition(); resetBall(); } // reset
/** Called when a battle is restarted. */ void SoccerWorld::reset() { WorldWithRank::reset(); if(race_manager->hasTimeTarget()) { WorldStatus::setClockMode(WorldStatus::CLOCK_COUNTDOWN, race_manager->getTimeTarget()); countDownReachedZero = false; } else WorldStatus::setClockMode(CLOCK_CHRONO); m_can_score_points = true; memset(m_team_goals, 0, sizeof(m_team_goals)); // Reset original positions for the soccer balls TrackObjectManager* tom = getTrack()->getTrackObjectManager(); assert(tom); m_redScorers.clear(); m_redScoreTimes.clear(); m_blueScorers.clear(); m_blueScoreTimes.clear(); m_lastKartToHitBall = -1; 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(); } if (m_goal_sound != NULL && m_goal_sound->getStatus() == SFXBase::SFX_PLAYING) { m_goal_sound->stop(); } initKartList(); } // reset
//----------------------------------------------------------------------------- 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