/** Called when a mouse click happens. If the click happened while the mouse * was hovering on top of a challenge, the kart will be teleported to * the challenge. * \param x,y Mouse coordinates. */ void OverWorld::onMouseClick(int x, int y) { const OverworldChallenge *challenge = ((RaceGUIOverworld*)getRaceGUI())->getCurrentChallenge(); if(challenge) { // Use the 'get closest start point' rescue function // from WorldWithRank by setting the kart's position to // be the location of the challenge bubble. AbstractKart* kart = getKart(0); kart->setXYZ(challenge->m_position); unsigned int index = getRescuePositionIndex(kart); btTransform s = getRescueTransform(index); const btVector3 &xyz = s.getOrigin(); float angle = atan2(challenge->m_position.X - xyz[0], challenge->m_position.Z - xyz[2]); s.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) ); moveKartTo(kart, s); return; } } // onMouseClick
/** Places a kart that is rescued. It calls getRescuePositionIndex to find * to which rescue position the kart should be moved, then getRescueTransform * to get the position and rotation of this rescue position, and then moves * the kart. * \param kart The kart that is rescued. */ void World::moveKartAfterRescue(AbstractKart* kart) { unsigned int index = getRescuePositionIndex(kart); btTransform t = getRescueTransform(index); moveKartTo(kart, t); } // moveKartAfterRescue
/** Waits till each kart is resting on the ground * * Does simulation steps still all karts reach the ground, i.e. are not * moving anymore */ void World::resetAllKarts() { // Reset the physics 'remaining' time to 0 so that the number // of timesteps is reproducible if doing a physics-based history run getPhysics()->getPhysicsWorld()->resetLocalTime(); // If track checking is requested, check all rescue positions if // they are heigh enough. if(UserConfigParams::m_track_debug) { // Loop over all karts, in case that some karts are dfferent for(unsigned int kart_id=0; kart_id<(unsigned int)m_karts.size(); kart_id++) { for(unsigned int rescue_pos=0; rescue_pos<getNumberOfRescuePositions(); rescue_pos++) { btTransform t = getRescueTransform(rescue_pos); // This will print out warnings if there is no terrain under // the kart, or the kart is being dropped on a reset texture moveKartTo(m_karts[kart_id], t); } // rescue_pos<getNumberOfRescuePositions // Reset the karts back to the original start position. // This call is a bit of an overkill, but setting the correct // transforms, positions, motion state is a bit of a hassle. m_karts[kart_id]->reset(); } // for kart_id<m_karts.size() } // if m_track_debug m_schedule_pause = false; m_schedule_unpause = false; //Project karts onto track from above. This will lower each kart so //that at least one of its wheel will be on the surface of the track for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++) { Vec3 xyz = (*i)->getXYZ(); //start projection from top of kart Vec3 up_offset(0, 0.5f * ((*i)->getKartHeight()), 0); (*i)->setXYZ(xyz+up_offset); bool kart_over_ground = m_track->findGround(*i); if (!kart_over_ground) { Log::error("World", "No valid starting position for kart %d on track %s.", (int)(i-m_karts.begin()), m_track->getIdent().c_str()); if (UserConfigParams::m_artist_debug_mode) { Log::warn("World", "Activating fly mode."); (*i)->flyUp(); continue; } else { exit(-1); } } } bool all_finished=false; // kart->isInRest() is not fully correct, since it only takes the // velocity in count, which might be close to zero when the kart // is just hitting the floor, before being pushed up again by // the suspension. So we just do a longer initial simulation, // which should be long enough for all karts to be firmly on ground. for(int i=0; i<60; i++) m_physics->update(1.f/60.f); // Stil wait will all karts are in rest (and handle the case that a kart // fell through the ground, which can happen if a kart falls for a long // time, therefore having a high speed when hitting the ground. int count = 0; while(!all_finished) { if (count++ > 100) { Log::error("World", "Infinite loop waiting for all_finished?"); break; } m_physics->update(1.f/60.f); all_finished=true; for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++) { if(!(*i)->isInRest()) { Vec3 normal; Vec3 hit_point; const Material *material; // We can't use (*i)->getXYZ(), since this is only defined // after update() was called. Instead we have to get the // real position of the rigid body. btTransform t; (*i)->getBody()->getMotionState()->getWorldTransform(t); // This test can not be done only once before the loop, since // it can happen that the kart falls through the track later! Vec3 to = t.getOrigin()+Vec3(0, -10000, 0); m_track->getTriangleMesh().castRay(t.getOrigin(), to, &hit_point, &material, &normal); if(!material) { Log::error("World", "No valid starting position for kart %d " "on track %s.", (int)(i-m_karts.begin()), m_track->getIdent().c_str()); if (UserConfigParams::m_artist_debug_mode) { Log::warn("World", "Activating fly mode."); (*i)->flyUp(); continue; } else { exit(-1); } } all_finished=false; break; } } } // while for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++) { (*i)->kartIsInRestNow(); } // Initialise the cameras, now that the correct kart positions are set for(unsigned int i=0; i<Camera::getNumCameras(); i++) { Camera::getCamera(i)->setInitialTransform(); } } // resetAllKarts
/** Waits till each kart is resting on the ground * * Does simulation steps still all karts reach the ground, i.e. are not * moving anymore */ void World::resetAllKarts() { // Reset the physics 'remaining' time to 0 so that the number // of timesteps is reproducible if doing a physics-based history run Physics::getInstance()->getPhysicsWorld()->resetLocalTime(); // If track checking is requested, check all rescue positions if // they are high enough. if(UserConfigParams::m_track_debug) { // Loop over all karts, in case that some karts are dfferent for(unsigned int kart_id=0; kart_id<(unsigned int)m_karts.size(); kart_id++) { if (m_karts[kart_id]->isGhostKart()) continue; for(unsigned int rescue_pos=0; rescue_pos<getNumberOfRescuePositions(); rescue_pos++) { btTransform t = getRescueTransform(rescue_pos); // This will print out warnings if there is no terrain under // the kart, or the kart is being dropped on a reset texture moveKartTo(m_karts[kart_id], t); } // rescue_pos<getNumberOfRescuePositions // Reset the karts back to the original start position. // This call is a bit of an overkill, but setting the correct // transforms, positions, motion state is a bit of a hassle. m_karts[kart_id]->reset(); } // for kart_id<m_karts.size() } // if m_track_debug m_schedule_pause = false; m_schedule_unpause = false; //Project karts onto track from above. This will lower each kart so //that at least one of its wheel will be on the surface of the track for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++) { if ((*i)->isGhostKart()) continue; Vec3 xyz = (*i)->getXYZ(); //start projection from top of kart Vec3 up_offset = (*i)->getNormal() * (0.5f * ((*i)->getKartHeight())); (*i)->setXYZ(xyz+up_offset); bool kart_over_ground = Track::getCurrentTrack()->findGround(*i); if (!kart_over_ground) { Log::error("World", "No valid starting position for kart %d on track %s.", (int)(i - m_karts.begin()), Track::getCurrentTrack()->getIdent().c_str()); if (UserConfigParams::m_artist_debug_mode) { Log::warn("World", "Activating fly mode."); (*i)->flyUp(); continue; } else { exit(-1); } } } // Do a longer initial simulation, which should be long enough for all // karts to be firmly on ground. float g = Track::getCurrentTrack()->getGravity(); for (KartList::iterator i = m_karts.begin(); i != m_karts.end(); i++) { if ((*i)->isGhostKart()) continue; (*i)->getBody()->setGravity((*i)->getMaterial()->hasGravity() ? (*i)->getNormal() * -g : Vec3(0, -g, 0)); } for(int i=0; i<60; i++) Physics::getInstance()->update(1.f/60.f); for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++) { (*i)->kartIsInRestNow(); } // Initialise the cameras, now that the correct kart positions are set for(unsigned int i=0; i<Camera::getNumCameras(); i++) { Camera::getCamera(i)->setInitialTransform(); } } // resetAllKarts