/** Determine the nearest kart or item and update the current target * accordingly. */ void Swatter::chooseTarget() { // TODO: for the moment, only handle karts... const World *world = World::getWorld(); Kart *closest_kart = NULL; float min_dist2 = FLT_MAX; for(unsigned int i=0; i<world->getNumKarts(); i++) { Kart *kart = world->getKart(i); // TODO: isSwatterReady(), isSquashable()? if(kart->isEliminated() || kart==m_kart) continue; // don't squash an already hurt kart if (kart->isInvulnerable() || kart->isSquashed()) continue; float dist2 = (kart->getXYZ()-m_kart->getXYZ()).length2(); if(dist2<min_dist2) { min_dist2 = dist2; closest_kart = kart; } } m_target = closest_kart; // may be NULL }
/** Squash karts or items that are around the end position (determined using * a joint) of the swatter. */ void Swatter::squashThingsAround() { const KartProperties* kp = m_kart->getKartProperties(); // Square of the minimum distance float min_dist2 = kp->getSwatterDistance2(); const World* world = World::getWorld(); // Get the node corresponding to the joint at the center of the swatter // (by swatter, I mean the thing hold in the hand, not the whole thing) scene::ISceneNode* swatter_node = m_scene_node->getJointNode("Swatter"); assert(swatter_node); Vec3 swatter_pos = swatter_node->getAbsolutePosition(); m_swat_sound->position(swatter_pos); m_swat_sound->play(); // Squash karts around for(unsigned int i=0; i<world->getNumKarts(); i++) { Kart *kart = world->getKart(i); // TODO: isSwatterReady() if(kart->isEliminated() || kart==m_kart) continue; // don't swat an already hurt kart if (kart->isInvulnerable() || kart->isSquashed()) continue; float dist2 = (kart->getXYZ()-swatter_pos).length2(); if(dist2 >= min_dist2) continue; // too far away, ignore this kart kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown()); if (kart->getAttachment()->getType()==Attachment::ATTACH_BOMB) { // make bomb explode kart->getAttachment()->update(10000); HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion"); if(m_kart->getController()->isPlayerController()) he->setPlayerKartHit(); projectile_manager->addHitEffect(he); m_kart->handleExplosion(m_kart->getXYZ(), /*direct_hit*/ true); } // if kart has bomb attached World::getWorld()->kartHit(kart->getWorldKartId()); } // for i < num_kartrs // TODO: squash items }
/** General update function called once per frame. This updates the kart * sectors, which are then used to determine the kart positions. * \param dt Time step size. */ void LinearWorld::update(float delta) { // run generic parent stuff that applies to all modes. It // especially updates the kart positions. WorldWithRank::update(delta); if (m_last_lap_sfx_playing && m_last_lap_sfx->getStatus() != SFXManager::SFX_PLAYING) { music_manager->getCurrentMusic()->resetTemporaryVolume(); m_last_lap_sfx_playing = false; } const unsigned int kart_amount = getNumKarts(); // Do stuff specific to this subtype of race. // ------------------------------------------ for(unsigned int n=0; n<kart_amount; n++) { KartInfo& kart_info = m_kart_info[n]; Kart* kart = m_karts[n]; // Nothing to do for karts that are currently being rescued or eliminated if(kart->playingEmergencyAnimation()) continue; // ---------- deal with sector data --------- // update sector variables int prev_sector = kart_info.m_track_sector; m_track->getQuadGraph().findRoadSector(kart->getXYZ(), &kart_info.m_track_sector); kart_info.m_on_road = kart_info.m_track_sector != QuadGraph::UNKNOWN_SECTOR; if(kart_info.m_on_road) { kart_info.m_last_valid_sector = kart_info.m_track_sector; kart_info.m_last_valid_race_lap = kart_info.m_race_lap; } else { // Kart off road. Find the closest sector instead. kart_info.m_track_sector = m_track->getQuadGraph().findOutOfRoadSector(kart->getXYZ(), prev_sector ); } // Update track coords (=progression) m_track->getQuadGraph().spatialToTrack(&kart_info.m_curr_track_coords, kart->getXYZ(), kart_info.m_track_sector ); } // for n // Update all positions. This must be done after _all_ karts have // updated their position and laps etc, otherwise inconsistencies // (like two karts at same position) can occur. // --------------------------------------------------------------- updateRacePosition(); for (unsigned int i=0; i<kart_amount; i++) { // ---------- update rank ------ if (m_karts[i]->hasFinishedRace() || m_karts[i]->isEliminated()) continue; // During the last lap update the estimated finish time. // This is used to play the faster music, and by the AI if (m_kart_info[i].m_race_lap == race_manager->getNumLaps()-1) { m_kart_info[i].m_estimated_finish = estimateFinishTimeForKart(m_karts[i]); } checkForWrongDirection(i); } #ifdef DEBUG // FIXME: Debug output in case that the double position error occurs again. std::vector<int> pos_used; pos_used.resize(kart_amount+1, -99); for(unsigned int i=0; i<kart_amount; i++) { if(pos_used[m_karts[i]->getPosition()]!=-99) { for(unsigned int j =0; j<kart_amount; j++) { printf("kart id=%d, position=%d, finished=%d, laps=%d, distanceDownTrack=%f %s\n", j, m_karts[j]->getPosition(), m_karts[j]->hasFinishedRace(), m_kart_info[j].m_race_lap, getDistanceDownTrackForKart(m_karts[j]->getWorldKartId()), (m_karts[j]->getPosition() == m_karts[i]->getPosition() ? "<--- !!!" : "")); } } pos_used[m_karts[i]->getPosition()]=i; } #endif } // update