/** Checks if the kart was overtaken, and if so plays a sound
*/
void PlayerController::setPosition(int p)
{
    if(m_kart->getPosition()<p)
    {
        World *world = World::getWorld();
        //have the kart that did the passing beep.
        //I'm not sure if this method of finding the passing kart is fail-safe.
        for(unsigned int i = 0 ; i < world->getNumKarts(); i++ )
        {
            Kart *kart = world->getKart(i);
            if(kart->getPosition() == p + 1)
            {
                kart->beep();
                break;
            }
        }
    }
}   // setPosition
Beispiel #2
0
/** Find the position (rank) of every kart
  */
void LinearWorld::updateRacePosition()
{
    // Mostly for debugging:
    beginSetKartPositions();
    const unsigned int kart_amount = m_karts.size();

#ifdef DEBUG
    bool rank_changed = false;
#endif
    
    // NOTE: if you do any changes to this loop, the next loop (see
    // DEBUG_KART_RANK below) needs to have the same changes applied
    // so that debug output is still correct!!!!!!!!!!!
    for (unsigned int i=0; i<kart_amount; i++)
    {
        Kart* kart          = m_karts[i];
        // Karts that are either eliminated or have finished the
        // race already have their (final) position assigned. If
        // these karts would get their rank updated, it could happen
        // that a kart that finished first will be overtaken after
        // crossing the finishing line and become second!
        if(kart->isEliminated() || kart->hasFinishedRace())
        {
            // This is only necessary to support debugging inconsistencies
            // in kart position parameters.
            setKartPosition(i, kart->getPosition());
            continue;
        }
        KartInfo& kart_info = m_kart_info[i];
        
        int p = 1 ;

        const int my_id                = kart->getWorldKartId();
        const int my_laps              = getLapForKart(my_id);
        const float my_progression     = getDistanceDownTrackForKart(my_id);        
        // Count karts ahead of the current kart, i.e. kart that are already finished,
        // have done more laps, or the same number of laps, but a greater distance.
        for (unsigned int j = 0 ; j < kart_amount ; j++)
        {
            if(j == kart->getWorldKartId())  continue; // don't compare a kart with itself
            
            if(m_karts[j]->isEliminated())   continue; // dismiss eliminated karts

            if(!kart->hasFinishedRace() && m_karts[j]->hasFinishedRace())
            {
                p++;
                continue;
            }

            /* has done more or less lapses */
            assert(j==m_karts[j]->getWorldKartId());
            int other_laps = getLapForKart(j);
            if (other_laps !=  my_laps)
            {
                if(other_laps > my_laps)
                {
                    p++; // Other kart has more lapses
                }
                continue;
            }
            // Now both karts have the same number of lapses. Test progression.
            // A kart is ahead if it's driven further, or driven the same
            // distance, but started further to the back.
            float other_progression = getDistanceDownTrackForKart(j);
            if(other_progression > my_progression ||
                (other_progression == my_progression &&
                m_karts[j]->getInitialPosition() > kart->getInitialPosition()) )
            {
                p++;
#if _DEBUG_PRINTS_LIKE_MAD_
                std::cout << "    " << p << " : " << m_karts[j]->getIdent() <<
                        " because he has is further within the track (my progression is " <<
                        my_progression << ", his progression is " << other_progression << ")\n";
#endif
            }
        } //next kart

#ifndef DEBUG
        setKartPosition(i, p);
#else
        rank_changed |= kart->getPosition()!=p;
        if (!setKartPosition(i,p))
        {
            std::cerr << "ERROR, same rank used twice!!\n";

            std::cerr <<  "Info used to decide ranking :\n";
            for (unsigned int d=0; d<kart_amount; d++)
            {
                std::cerr << "   kart " << m_karts[d]->getIdent() << " has finished(" << m_karts[d]->hasFinishedRace()
                          << "), is at lap (" << getLapForKart(d) << "), is at distance("
                          << getDistanceDownTrackForKart(d) << "), is eliminated(" << m_karts[d]->isEliminated() << ")" << std::endl;
            }
                        
            std::cerr <<  "Who has each ranking so far :\n";
            for (unsigned int d=0; d<i; d++)
            {
                std::cerr << "    " << m_karts[d]->getIdent() << " has rank " << m_karts[d]->getPosition() << std::endl;
            }
            
            std::cerr << "    --> And " << kart->getIdent() << " is being set at rank " << p << std::endl;
            history->Save();
            assert(false);
        }
#endif

        // Switch on faster music if not already done so, if the
        // first kart is doing its last lap, and if the estimated
        // remaining time is less than 30 seconds.
        if(!m_faster_music_active                                  &&
           kart_info.m_race_lap == race_manager->getNumLaps()-1    &&
           p==1                                                    &&
           useFastMusicNearEnd()                                   &&
           kart_info.m_estimated_finish > 0                        &&
           kart_info.m_estimated_finish - getTime() < 30.0f              )
        {
            music_manager->switchToFastMusic();
            m_faster_music_active=true;
        }
    }   // for i<kart_amount

    // Define this to get a detailled analyses each time a race position 
    // changes.
#ifdef DEBUG
#undef DEBUG_KART_RANK
#ifdef DEBUG_KART_RANK
    if(rank_changed)
    {
        std::cout << "Counting laps at "<<getTime()<<" seconds.\n";
        for (unsigned int i=0; i<kart_amount; i++)
        {
            Kart* kart          = m_karts[i];
            if(kart->isEliminated() || kart->hasFinishedRace()) continue;
            KartInfo& kart_info = m_kart_info[i];
            int p = 1 ;
            const int my_id                = kart->getWorldKartId();
            const int my_laps              = getLapForKart(my_id);
            const float my_progression     = getDistanceDownTrackForKart(my_id);
            std::cout << "counting karts ahead of " << kart->getIdent() 
                << " (laps "<<m_kart_info[i].m_race_lap<<", progress "
                << my_progression<<").\n";
            for (unsigned int j = 0 ; j < kart_amount ; j++)
            {
                if(j == kart->getWorldKartId())  continue; // don't compare a kart with itself
                if(!kart->hasFinishedRace() && m_karts[j]->hasFinishedRace())
                {
                    p++;
                    std::cout << "    " << p << " : " << m_karts[j]->getIdent() << " because he has finished.\n";
                    continue;
                }
                int other_laps = getLapForKart(j);
                if (other_laps !=  my_laps)
                {
                    if(other_laps > my_laps)
                    {
                        p++; // Other kart has more lapses
                        std::cout << "    " << p << " : " << m_karts[j]->getIdent() << " because he has more laps than me.\n";
                    }
                    continue;
                }
                float other_progression = getDistanceDownTrackForKart(j);
                if(other_progression > my_progression ||
                    (other_progression == my_progression &&
                    m_karts[j]->getInitialPosition() > kart->getInitialPosition()) )
                {
                    p++;
                    std::cout << "    " << p << " : " << m_karts[j]->getIdent() <<
                        " because he is further within the track (my progression is " <<
                        my_progression << ", his progression is " << other_progression << ")\n";
                }
            } //next kart
        }   // for i<kart_amount
        std::cout << "-------------------------------------------\n";
    }   // if rank_changed
#endif
#endif

    endSetKartPositions();
}   // updateRacePosition
Beispiel #3
0
//-----------------------------------------------------------------------------
RaceGUIBase::KartIconDisplayInfo* LinearWorld::getKartsDisplayInfo()
{
    int   laps_of_leader       = -1;
    float time_of_leader       = -1;
    // Find the best time for the lap. We can't simply use
    // the time of the kart at position 1, since the kart
    // might have been overtaken by now
    const unsigned int kart_amount = getNumKarts();
    for(unsigned int i = 0; i < kart_amount ; i++)
    {
        RaceGUIBase::KartIconDisplayInfo& rank_info = m_kart_display_info[i];
        Kart* kart = m_karts[i];

        // reset color
        rank_info.r = 1.0;
        rank_info.g = 1.0;
        rank_info.b = 1.0;
        rank_info.lap = -1;

        if(kart->isEliminated()) continue;
        const float lap_time = getTimeAtLapForKart(kart->getWorldKartId());
        const int current_lap  = getLapForKart( kart->getWorldKartId() );
        rank_info.lap = current_lap;

        if(current_lap > laps_of_leader)
        {
            // more laps than current leader --> new leader and new time computation
            laps_of_leader = current_lap;
            time_of_leader = lap_time;
        } else if(current_lap == laps_of_leader)
        {
            // Same number of laps as leader: use fastest time
            time_of_leader=std::min(time_of_leader,lap_time);
        }
    }

    // we now know the best time of the lap. fill the remaining bits of info
    for(unsigned int i = 0; i < kart_amount ; i++)
    {
        RaceGUIBase::KartIconDisplayInfo& rank_info = m_kart_display_info[i];
        KartInfo& kart_info = m_kart_info[i];
        Kart* kart = m_karts[i];

        const int position = kart->getPosition();

        if(laps_of_leader>0 &&    // Don't compare times when crossing the start line first
           (getTime() - getTimeAtLapForKart(kart->getWorldKartId())<5.0f || rank_info.lap != laps_of_leader) &&
           raceHasLaps())
        {  // Display for 5 seconds
            std::string str;
            if(position == 1)
            {
                str = " " + StringUtils::timeToString( getTimeAtLapForKart(kart->getWorldKartId()) );
            }
            else
            {
                float timeBehind;
                timeBehind = (kart_info.m_race_lap==laps_of_leader
                                ? getTimeAtLapForKart(kart->getWorldKartId())
                                : getTime())
                           - time_of_leader;
                str = "+" + StringUtils::timeToString(timeBehind);
            }
            rank_info.m_text = irr::core::stringw(str.c_str());
        }
        else
        {
            rank_info.m_text = "";
        }

        int numLaps = race_manager->getNumLaps();

        if(kart_info.m_race_lap>=numLaps)
        {  // kart is finished, display in green
            rank_info.g = rank_info.b = 0;
        }
        else if(kart_info.m_race_lap>=0 && numLaps>1)
        {
            rank_info.g = rank_info.b = 1.0f-(float)kart_info.m_race_lap/((float)numLaps-1.0f);
        }
    }   // next kart


    return m_kart_display_info;
}   // getKartsDisplayInfo