1) Cleaned up and simplified handling of race phase in world.
2) Added a 'final camera': this camera will move forward and turn when a race is finished to show the finishing line. This is currently only enabled for the race track. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1953 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
359f281a4a
commit
a0473ad24b
@ -36,6 +36,7 @@ Camera::Camera(int camera_index, const Kart* kart)
|
||||
|
||||
btVector3 start_pos = m_kart->getPos();
|
||||
sgSetVec3(m_current_pos.xyz, start_pos.getX(), start_pos.getY(), start_pos.getZ());
|
||||
sgSetVec3(m_current_pos.xyz, 0, 0, 0);
|
||||
sgSetVec3(m_current_pos.hpr, 0, 0, 0);
|
||||
|
||||
// FIXME: clipping should be configurable for slower machines
|
||||
@ -96,6 +97,20 @@ void Camera::setScreenPosition(int camera_index)
|
||||
//-----------------------------------------------------------------------------
|
||||
void Camera::setMode(Mode mode)
|
||||
{
|
||||
if(mode==CM_FINAL)
|
||||
{
|
||||
const Track* track=world->getTrack();
|
||||
// If the track doesn't have a final position, ignore this mode
|
||||
if(!track->hasFinalCamera()) return;
|
||||
btVector3 coord(m_current_pos.xyz[0],m_current_pos.xyz[1],
|
||||
m_current_pos.xyz[2]);
|
||||
m_velocity = (track->getCameraPosition()-coord)/1.0f;
|
||||
btVector3 rotation(m_current_pos.hpr[0],m_current_pos.hpr[1],
|
||||
m_current_pos.hpr[2]);
|
||||
// Rotate faster
|
||||
m_angular_velocity = (track->getCameraHPR()-rotation)/1.0f;
|
||||
m_final_time=0.0f;
|
||||
}
|
||||
m_mode = mode;
|
||||
m_last_pitch = 0.0f;
|
||||
if(m_mode==CM_CLOSEUP)
|
||||
@ -119,6 +134,8 @@ void Camera::update (float dt)
|
||||
sgCoord kartcoord;
|
||||
const Kart *kart;
|
||||
|
||||
if(m_mode==CM_FINAL) return finalCamera(dt);
|
||||
|
||||
// First define the position of the kart
|
||||
if(m_mode==CM_LEADER_MODE)
|
||||
{
|
||||
@ -183,6 +200,29 @@ void Camera::update (float dt)
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Camera::finalCamera(float dt)
|
||||
{
|
||||
// Turn/move the camera for 1 second only
|
||||
m_final_time += dt;
|
||||
if( m_final_time<1.0f )
|
||||
{
|
||||
btVector3 coord(m_current_pos.xyz[0],m_current_pos.xyz[1],m_current_pos.xyz[2]);
|
||||
coord += m_velocity*dt;
|
||||
printf("y %f vely %f dt %f\n",coord.getY(), m_velocity.getY(), dt);
|
||||
m_current_pos.xyz[0]=coord.getX();
|
||||
m_current_pos.xyz[1]=coord.getY();
|
||||
m_current_pos.xyz[2]=coord.getZ();
|
||||
btVector3 rotation(m_current_pos.hpr[0],m_current_pos.hpr[1],m_current_pos.hpr[2]);
|
||||
rotation += m_angular_velocity*dt;
|
||||
m_current_pos.hpr[0]=rotation.getX();
|
||||
m_current_pos.hpr[1]=rotation.getY();
|
||||
m_current_pos.hpr[2]=rotation.getZ();
|
||||
m_context->setCamera(&m_current_pos);
|
||||
}
|
||||
} // finalCamera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Camera::apply ()
|
||||
{
|
||||
int width = user_config->m_width ;
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
CM_DRIFTING, // FIXME: drifting behind when accelerating = not yet implemented
|
||||
CM_LEADER_MODE, // for deleted player karts in follow the leader
|
||||
CM_REVERSE, // Camera is pointing backwards
|
||||
CM_FINAL, // Final camera to show the end of the race
|
||||
CM_SIMPLE_REPLAY
|
||||
};
|
||||
protected:
|
||||
@ -47,8 +48,12 @@ protected:
|
||||
float m_current_speed; // current speed of camera
|
||||
float m_last_pitch; // for tiling the camera when going downhill
|
||||
float m_distance; // distance between camera and kart
|
||||
btVector3 m_velocity; // camera velocity for final mode
|
||||
btVector3 m_angular_velocity; // camera angular velocity for final mode
|
||||
float m_final_time; // time when final camera mode started
|
||||
|
||||
|
||||
private:
|
||||
void finalCamera (float dt); // handle the final camera
|
||||
public:
|
||||
Camera (int camera_index, const Kart* kart);
|
||||
void setMode (Mode mode_); /** Set the camera to the given mode */
|
||||
|
@ -162,7 +162,7 @@ void Collectable::hitRedHerring(int n)
|
||||
{
|
||||
Kart *kart = world->getKart(i);
|
||||
if(kart->isEliminated() || kart == m_owner) continue;
|
||||
if(kart->getPosition() == 1 && kart->raceIsFinished())
|
||||
if(kart->getPosition() == 1 && kart->hasFinishedRace())
|
||||
{
|
||||
m_type = COLLECT_PARACHUTE;
|
||||
m_number = 1;
|
||||
|
@ -795,7 +795,7 @@ void RaceGUI::drawLap(Kart* kart, int offset_x, int offset_y,
|
||||
offset_x += (int)(120*ratio_x);
|
||||
offset_y += (int)(70*maxRatio);
|
||||
|
||||
if ( kart->getLap() >= race_manager->getNumLaps())
|
||||
if(kart->hasFinishedRace())
|
||||
{
|
||||
sprintf(str, _("Finished"));
|
||||
font_race->PrintShadow(str, (int)(48*maxRatio), offset_x, offset_y);
|
||||
|
24
src/kart.cpp
24
src/kart.cpp
@ -74,6 +74,7 @@ Kart::Kart (const std::string& kart_name, int position_ ,
|
||||
m_skidmark_right = NULL;
|
||||
m_track_sector = Track::UNKNOWN_SECTOR;
|
||||
sgCopyCoord(&m_reset_pos, &init_pos);
|
||||
|
||||
// Neglecting the roll resistance (which is small for high speeds compared
|
||||
// to the air resistance), maximum speed is reached when the engine
|
||||
// power equals the air resistance force, resulting in this formula:
|
||||
@ -376,6 +377,12 @@ void Kart::doLapCounting ()
|
||||
setTimeAtLap(world->getTime());
|
||||
m_race_lap++ ;
|
||||
}
|
||||
// Race finished
|
||||
// =============
|
||||
if(m_race_lap>=race_manager->getNumLaps())
|
||||
{
|
||||
raceFinished(world->getTime());
|
||||
}
|
||||
// Only do timings if original time was set properly. Driving backwards
|
||||
// over the start line will cause the lap start time to be set to -1.
|
||||
if(m_lap_start_time>=0.0)
|
||||
@ -431,6 +438,14 @@ void Kart::doLapCounting ()
|
||||
}
|
||||
} // doLapCounting
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Kart::raceFinished(float time)
|
||||
{
|
||||
m_finished_race = true;
|
||||
m_finish_time = time;
|
||||
race_manager->RaceFinished(this, time);
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Kart::collectedHerring(Herring* herring)
|
||||
{
|
||||
@ -655,7 +670,7 @@ void Kart::update(float dt)
|
||||
m_curr_pos.xyz,
|
||||
m_track_sector );
|
||||
|
||||
doLapCounting () ;
|
||||
if(!m_finished_race) doLapCounting();
|
||||
processSkidMarks();
|
||||
} // update
|
||||
|
||||
@ -1066,13 +1081,6 @@ void Kart::placeModel ()
|
||||
m_curr_pos.xyz[2] -= offset_z;
|
||||
m_curr_pos.hpr[1] -= offset_pitch;
|
||||
} // placeModel
|
||||
//-----------------------------------------------------------------------------
|
||||
void Kart::setFinishingState(float time)
|
||||
{
|
||||
m_finished_race = true;
|
||||
m_finish_time = time;
|
||||
} // setFinishingState
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float Kart::estimateFinishTime ()
|
||||
{
|
||||
|
@ -142,9 +142,8 @@ public:
|
||||
int getLap () const { return m_race_lap; }
|
||||
int getPosition () const { return m_race_position; }
|
||||
int getInitialPosition () const { return m_initial_position; }
|
||||
void setFinishingState(float time);
|
||||
float getFinishTime () const { return m_finish_time; }
|
||||
bool raceIsFinished () const { return m_finished_race; }
|
||||
float getFinishTime () const { return m_finish_time; }
|
||||
bool hasFinishedRace () const { return m_finished_race; }
|
||||
void endRescue ();
|
||||
float estimateFinishTime ();
|
||||
void processSkidMarks ();
|
||||
@ -207,6 +206,7 @@ public:
|
||||
void forceRescue (bool is_rescue=false);
|
||||
void handleExplosion (const btVector3& pos, bool direct_hit);
|
||||
const std::string& getName () const {return m_kart_properties->getName();}
|
||||
const std::string& getIdent () const {return m_kart_properties->getIdent();}
|
||||
virtual int isPlayerKart () const {return 0; }
|
||||
// addMessages gets called by world to add messages to the gui
|
||||
virtual void addMessages () {};
|
||||
@ -215,7 +215,8 @@ public:
|
||||
virtual void handleZipper ();
|
||||
virtual void crashed () {};
|
||||
virtual void doLapCounting ();
|
||||
virtual void update (float dt );
|
||||
virtual void update (float dt);
|
||||
virtual void raceFinished (float time);
|
||||
};
|
||||
|
||||
class TrafficDriver : public Kart
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <plib/sg.h>
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
|
||||
namespace lisp
|
||||
{
|
||||
@ -139,6 +140,28 @@ namespace lisp
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool get(const char* name, btVector3& val) const
|
||||
{
|
||||
const Lisp* lisp = getLisp(name);
|
||||
if(!lisp)
|
||||
return false;
|
||||
|
||||
lisp = lisp->getCdr();
|
||||
if(!lisp)
|
||||
return false;
|
||||
float f[3];
|
||||
for(int i = 0; i < 3 && lisp; ++i)
|
||||
{
|
||||
const Lisp* m_car = lisp->getCar();
|
||||
if(!m_car)
|
||||
return false;
|
||||
m_car->get(f[i]);
|
||||
lisp = lisp->getCdr();
|
||||
}
|
||||
// Lists are stored in reverse order, so reverse to original order
|
||||
val.setValue(f[2],f[1],f[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool getVector(const char* name, std::vector<T>& vec) const
|
||||
|
@ -53,7 +53,7 @@ protected:
|
||||
btRigidBody* m_body;
|
||||
btDefaultMotionState* m_motion_state;
|
||||
btTransform m_transform;
|
||||
|
||||
btVector3 m_hpr;
|
||||
public:
|
||||
|
||||
Moveable (bool bHasHistory=false);
|
||||
@ -64,9 +64,11 @@ public:
|
||||
const btVector3 &getVelocityLC() const {return m_velocityLC; }
|
||||
virtual void setVelocity(const btVector3& v) {m_body->setLinearVelocity(v); }
|
||||
sgCoord* getCoord () {return &m_curr_pos; }
|
||||
const btVector3 getPos () const {return m_transform.getOrigin(); }
|
||||
const btVector3& getPos () const {return m_transform.getOrigin(); }
|
||||
const btVector3& getRotation() const {return m_hpr; }
|
||||
const sgCoord* getCoord () const {return &m_curr_pos; }
|
||||
const sgVec4* getNormalHOT () const {return m_normal_hot; }
|
||||
const sgCoord* getResetPos () const {return &m_reset_pos; }
|
||||
void setCoord (sgCoord* pos) {sgCopyCoord ( &m_curr_pos,pos); }
|
||||
virtual void placeModel ();
|
||||
virtual void handleZipper () {};
|
||||
|
@ -220,6 +220,20 @@ void PlayerKart::setPosition(int p)
|
||||
Kart::setPosition(p);
|
||||
} // setPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PlayerKart::raceFinished(float time)
|
||||
{
|
||||
Kart::raceFinished(time);
|
||||
m_camera->setMode(Camera::CM_FINAL); // set race over camera
|
||||
RaceGUI* m=(RaceGUI*)menu_manager->getRaceMenu();
|
||||
if(m)
|
||||
{
|
||||
m->addMessage(getPosition()==1 ? _("You won") : _("You finished") ,
|
||||
this, 2.0f, 60);
|
||||
m->addMessage( _("the race!"), this, 2.0f, 60);
|
||||
}
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PlayerKart::handleZipper()
|
||||
{
|
||||
@ -257,7 +271,7 @@ void PlayerKart::addMessages()
|
||||
// Display a warning message if the kart is going back way (unless
|
||||
// the kart has already finished the race).
|
||||
if ((angle_diff > 120.0f || angle_diff < -120.0f) &&
|
||||
getVelocity().getY() > 0.0f && !raceIsFinished() )
|
||||
getVelocity().getY() > 0.0f && !hasFinishedRace() )
|
||||
{
|
||||
m->addMessage(_("WRONG WAY!"), this, -1.0f, 60);
|
||||
} // if angle is too big
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
void handleZipper ();
|
||||
void collectedHerring (Herring* herring);
|
||||
virtual void setPosition (int p);
|
||||
virtual void raceFinished (float time);
|
||||
|
||||
int isPlayerKart () const {return 1;}
|
||||
Camera* getCamera () {return m_camera;}
|
||||
|
@ -219,10 +219,25 @@ void RaceManager::exit_race()
|
||||
} // exit_Race
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::addKartResult(int kart, int pos, float time)
|
||||
// Kart kart has finished the race at the specified time (which can be different
|
||||
// from world->getClock() in case of setting extrapolated arrival times).
|
||||
void RaceManager::RaceFinished(const Kart *kart, float time)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<m_kart_status.size(); i++)
|
||||
{
|
||||
printf("i %d %s %s\n",i,kart->getName().c_str(),m_kart_status[i].m_ident.c_str());
|
||||
if(kart->getIdent()==m_kart_status[i].m_ident) break;
|
||||
} // for i
|
||||
if(i>=m_kart_status.size())
|
||||
{
|
||||
fprintf(stderr, "Kart '%s' not found. Ignored.\n",kart->getName().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// In follow the leader mode, kart 0 does not get any points,
|
||||
// so the position of each kart is actually one better --> decrease pos
|
||||
int pos = kart->getPosition();
|
||||
if(m_race_mode==RM_FOLLOW_LEADER)
|
||||
{
|
||||
pos--;
|
||||
@ -232,11 +247,13 @@ void RaceManager::addKartResult(int kart, int pos, float time)
|
||||
if(pos<=0) pos=stk_config->m_max_karts;
|
||||
}
|
||||
|
||||
m_kart_status[kart].m_score += m_score_for_position[pos-1];
|
||||
m_kart_status[kart].m_last_score = m_score_for_position[pos-1];
|
||||
m_kart_status[kart].m_overall_time += time;
|
||||
m_kart_status[kart].m_last_time = time;
|
||||
} // addKartResult
|
||||
m_kart_status[i].m_score += m_score_for_position[pos-1];
|
||||
m_kart_status[i].m_last_score = m_score_for_position[pos-1];
|
||||
m_kart_status[i].m_overall_time += time;
|
||||
m_kart_status[i].m_last_time = time;
|
||||
m_num_finished_karts ++;
|
||||
if(kart->isPlayerKart()) m_num_finished_players++;
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::restartRace()
|
||||
|
@ -102,46 +102,47 @@ public:
|
||||
RaceManager();
|
||||
~RaceManager();
|
||||
|
||||
void setPlayerKart(unsigned int player, const std::string& kart);
|
||||
void setNumPlayers(int num);
|
||||
void reset();
|
||||
void setGrandPrix(const CupData &cup) { m_cup = cup; }
|
||||
void setDifficulty(Difficulty diff);
|
||||
void setNumLaps(int num) { m_num_laps.clear();
|
||||
m_num_laps.push_back(num); }
|
||||
void setTrack(const std::string& track);
|
||||
void setRaceMode(RaceModeType mode) { m_race_mode = mode; }
|
||||
void setNumKarts(int num) { m_num_karts = num; }
|
||||
void setCoinTarget(int num) { m_coin_target = num; }
|
||||
void addKartResult(int kart, int pos, float time);
|
||||
RaceModeType getRaceMode() const { return m_race_mode; }
|
||||
unsigned int getNumKarts() const { return m_num_karts; }
|
||||
unsigned int getNumPlayers() const { return (int)m_player_karts.size();}
|
||||
int getNumLaps() const { return m_num_laps[m_track_number];}
|
||||
Difficulty getDifficulty() const { return m_difficulty; }
|
||||
const std::string& getTrackName() const { return m_tracks[m_track_number]; }
|
||||
const CupData *getGrandPrix() const { return &m_cup; }
|
||||
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
|
||||
unsigned int getFinishedPlayers() const { return m_num_finished_players; }
|
||||
const std::string& getKartName(int kart) const
|
||||
{ return m_kart_status[kart].m_ident;}
|
||||
const std::string& getHerringStyle() const
|
||||
{ return m_cup.getHerringStyle(); }
|
||||
int getKartScore(int krt) const { return m_kart_status[krt].m_score;}
|
||||
int getPositionScore(int p) const { return m_score_for_position[p-1]; }
|
||||
double getOverallTime(int kart) const { return m_kart_status[kart].m_overall_time;}
|
||||
int getCoinTarget() const { return m_coin_target; }
|
||||
bool isEliminated(int kart) const { return m_kart_status[kart].m_is_eliminated;}
|
||||
bool raceHasLaps() const { return m_race_mode!=RM_FOLLOW_LEADER;}
|
||||
void eliminate(int kart) { m_kart_status[kart].m_is_eliminated=true;}
|
||||
void addFinishedKarts(int num) { m_num_finished_karts += num; }
|
||||
void PlayerFinishes() { m_num_finished_players++; }
|
||||
int allPlayerFinished() const {return m_num_finished_players==m_player_karts.size();}
|
||||
int raceIsActive() const { return m_active_race; }
|
||||
bool isPlayer(int kart) const {return m_kart_status[kart].m_player_id>-1; }
|
||||
void setPlayerKart(unsigned int player, const std::string& kart);
|
||||
void setNumPlayers(int num);
|
||||
void reset();
|
||||
void RaceFinished(const Kart* kart, float time);
|
||||
void setTrack(const std::string& track);
|
||||
void setGrandPrix(const CupData &cup){ m_cup = cup; }
|
||||
void setDifficulty(Difficulty diff);
|
||||
void setNumLaps(int num) { m_num_laps.clear();
|
||||
m_num_laps.push_back(num); }
|
||||
void setRaceMode(RaceModeType mode) { m_race_mode = mode; }
|
||||
void setNumKarts(int num) { m_num_karts = num; }
|
||||
void setCoinTarget(int num) { m_coin_target = num; }
|
||||
RaceModeType getRaceMode() const { return m_race_mode; }
|
||||
unsigned int getNumKarts() const { return m_num_karts; }
|
||||
unsigned int getNumPlayers() const { return (int)m_player_karts.size();}
|
||||
int getNumLaps() const { return m_num_laps[m_track_number];}
|
||||
Difficulty getDifficulty() const { return m_difficulty; }
|
||||
const std::string&
|
||||
getTrackName() const { return m_tracks[m_track_number]; }
|
||||
const CupData
|
||||
*getGrandPrix() const { return &m_cup; }
|
||||
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
|
||||
unsigned int getFinishedPlayers() const { return m_num_finished_players; }
|
||||
const std::string&
|
||||
getKartName(int kart) const { return m_kart_status[kart].m_ident;}
|
||||
const std::string&
|
||||
getHerringStyle() const { return m_cup.getHerringStyle(); }
|
||||
int getKartScore(int krt) const { return m_kart_status[krt].m_score;}
|
||||
int getPositionScore(int p) const { return m_score_for_position[p-1]; }
|
||||
double getOverallTime(int kart) const { return m_kart_status[kart].m_overall_time;}
|
||||
int getCoinTarget() const { return m_coin_target; }
|
||||
bool isEliminated(int kart) const { return m_kart_status[kart].m_is_eliminated;}
|
||||
bool raceHasLaps() const { return m_race_mode!=RM_FOLLOW_LEADER;}
|
||||
void eliminate(int kart) { m_kart_status[kart].m_is_eliminated=true;}
|
||||
int allPlayerFinished() const {return
|
||||
m_num_finished_players==m_player_karts.size(); }
|
||||
int raceIsActive() const { return m_active_race; }
|
||||
bool isPlayer(int kart) const {return m_kart_status[kart].m_player_id>-1; }
|
||||
|
||||
void setMirror() {/*FIXME*/}
|
||||
void setReverse(){/*FIXME*/}
|
||||
void setMirror() {/*FIXME*/}
|
||||
void setReverse(){/*FIXME*/}
|
||||
|
||||
void startNew(); // start new race/GP/...
|
||||
void next(); // start the next race or go back to the start screen
|
||||
|
@ -54,15 +54,16 @@ const int Track::UNKNOWN_SECTOR = -1;
|
||||
// ----------------------------------------------------------------------------
|
||||
Track::Track( std::string filename_, float w, float h, bool stretch )
|
||||
{
|
||||
m_filename = filename_;
|
||||
m_herring_style = "";
|
||||
m_track_2d_width = w;
|
||||
m_track_2d_height = h;
|
||||
m_do_stretch = stretch;
|
||||
m_description = "";
|
||||
m_designer = "";
|
||||
m_screenshot = "";
|
||||
m_top_view = "";
|
||||
m_filename = filename_;
|
||||
m_herring_style = "";
|
||||
m_track_2d_width = w;
|
||||
m_track_2d_height = h;
|
||||
m_do_stretch = stretch;
|
||||
m_description = "";
|
||||
m_designer = "";
|
||||
m_screenshot = "";
|
||||
m_top_view = "";
|
||||
m_has_final_camera = false;
|
||||
|
||||
loadTrack(m_filename);
|
||||
loadDriveline();
|
||||
@ -842,6 +843,10 @@ void Track::loadTrack(std::string filename_)
|
||||
LISP->get ("gravity", m_gravity);
|
||||
LISP->get ("AI-angle-adjust", m_AI_angle_adjustment);
|
||||
LISP->get ("AI-curve-speed-adjust", m_AI_curve_speed_adjustment);
|
||||
// if both camera position and rotation are defined,
|
||||
// set the flag that the track has final camera position
|
||||
m_has_final_camera = LISP->get("camera-final-position", m_camera_final_position);
|
||||
m_has_final_camera &= LISP->get("camera-final-hpr", m_camera_final_hpr);
|
||||
|
||||
// Set the correct paths
|
||||
m_screenshot = file_manager->getTrackFile(m_screenshot, getIdent());
|
||||
|
@ -59,6 +59,9 @@ private:
|
||||
// braking. These factors are used to adjust this.
|
||||
float m_AI_angle_adjustment;
|
||||
float m_AI_curve_speed_adjustment;
|
||||
bool m_has_final_camera;
|
||||
btVector3 m_camera_final_position;
|
||||
btVector3 m_camera_final_hpr;
|
||||
public:
|
||||
enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 };
|
||||
|
||||
@ -192,6 +195,9 @@ public:
|
||||
const std::string& getScreenshotFile () const {return m_screenshot; }
|
||||
const std::vector<SGfloat>& getWidth () const {return m_path_width; }
|
||||
const std::string& getHerringStyle () const {return m_herring_style; }
|
||||
bool hasFinalCamera () const {return m_has_final_camera; }
|
||||
const btVector3& getCameraPosition () const {return m_camera_final_position;}
|
||||
const btVector3& getCameraHPR () const {return m_camera_final_hpr; }
|
||||
void getStartCoords (unsigned int pos, sgCoord* coords) const;
|
||||
void getTerrainInfo(const btVector3 &pos, float *hot, btVector3* normal,
|
||||
const Material **material) const;
|
||||
|
342
src/world.cpp
342
src/world.cpp
@ -258,36 +258,7 @@ void World::update(float dt)
|
||||
unlock_manager->raceFinished();
|
||||
return;
|
||||
}
|
||||
// Add times to highscore list. First compute the order of karts,
|
||||
// so that the timing of the fastest kart is added first (otherwise
|
||||
// someone might get into the highscore list, only to be kicked out
|
||||
// again by a faster kart in the same race), which might be confusing
|
||||
// if we ever decide to display a message (e.g. during a race)
|
||||
unsigned int *index = new unsigned int[m_kart.size()];
|
||||
for (unsigned int i=0; i<m_kart.size(); i++ )
|
||||
{
|
||||
index[m_kart[i]->getPosition()-1] = i;
|
||||
}
|
||||
|
||||
for(unsigned int pos=0; pos<m_kart.size(); pos++)
|
||||
{
|
||||
// Only record times for player karts
|
||||
if(!m_kart[index[pos]]->isPlayerKart()) continue;
|
||||
|
||||
PlayerKart *k = (PlayerKart*)m_kart[index[pos]];
|
||||
|
||||
Highscores::HighscoreType hst = (race_manager->getRaceMode()==
|
||||
RaceManager::RM_TIME_TRIAL)
|
||||
? Highscores::HST_TIMETRIAL_OVERALL_TIME
|
||||
: Highscores::HST_RACE_OVERALL_TIME;
|
||||
if(m_highscores->addData(hst, k->getName(),
|
||||
k->getPlayer()->getName(),
|
||||
k->getFinishTime())>0 )
|
||||
{
|
||||
highscore_manager->Save();
|
||||
}
|
||||
}
|
||||
delete []index;
|
||||
updateHighscores();
|
||||
pause();
|
||||
menu_manager->pushMenu(MENUID_RACERESULT);
|
||||
}
|
||||
@ -305,7 +276,7 @@ void World::update(float dt)
|
||||
for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i)
|
||||
{
|
||||
if(m_kart[i]->isEliminated()) continue; // ignore eliminated kart
|
||||
if(!m_kart[i]->raceIsFinished()) updateRacePosition((int)i);
|
||||
if(!m_kart[i]->hasFinishedRace()) updateRacePosition((int)i);
|
||||
if(m_kart[i]->isPlayerKart()) m_kart[i]->addMessages(); // add 'wrong direction'
|
||||
}
|
||||
|
||||
@ -322,9 +293,43 @@ void World::update(float dt)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
void World::updateHighscores()
|
||||
{
|
||||
// Add times to highscore list. First compute the order of karts,
|
||||
// so that the timing of the fastest kart is added first (otherwise
|
||||
// someone might get into the highscore list, only to be kicked out
|
||||
// again by a faster kart in the same race), which might be confusing
|
||||
// if we ever decide to display a message (e.g. during a race)
|
||||
unsigned int *index = new unsigned int[m_kart.size()];
|
||||
for (unsigned int i=0; i<m_kart.size(); i++ )
|
||||
{
|
||||
index[m_kart[i]->getPosition()-1] = i;
|
||||
}
|
||||
|
||||
for(unsigned int pos=0; pos<m_kart.size(); pos++)
|
||||
{
|
||||
// Only record times for player karts
|
||||
if(!m_kart[index[pos]]->isPlayerKart()) continue;
|
||||
|
||||
PlayerKart *k = (PlayerKart*)m_kart[index[pos]];
|
||||
|
||||
Highscores::HighscoreType hst = (race_manager->getRaceMode()==
|
||||
RaceManager::RM_TIME_TRIAL)
|
||||
? Highscores::HST_TIMETRIAL_OVERALL_TIME
|
||||
: Highscores::HST_RACE_OVERALL_TIME;
|
||||
if(m_highscores->addData(hst, k->getName(),
|
||||
k->getPlayer()->getName(),
|
||||
k->getFinishTime())>0 )
|
||||
{
|
||||
highscore_manager->Save();
|
||||
}
|
||||
}
|
||||
delete []index;
|
||||
} // updateHighscores
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
//-----------------------------------------------------------------------------
|
||||
bool World::saveReplayHumanReadable( std::string const &filename ) const
|
||||
{
|
||||
std::string path;
|
||||
@ -403,17 +408,23 @@ bool World::loadReplayHumanReadable( std::string const &filename )
|
||||
void World::updateRaceStatus(float dt)
|
||||
{
|
||||
switch (m_phase) {
|
||||
case SETUP_PHASE: m_clock=0.0f; m_phase=READY_PHASE;
|
||||
// Note: setup phase must be a separate phase, since the race_manager
|
||||
// checks the phase when updating the camera: in the very first time
|
||||
// step dt is large (it includes loading time), so the camera might
|
||||
// tilt way too much. A separate setup phase for the first frame
|
||||
// simplifies this handling
|
||||
case SETUP_PHASE: m_clock = 0.0f;
|
||||
m_phase = READY_PHASE;
|
||||
sound_manager->playSfx(SOUND_PRESTART);
|
||||
dt = 0.0f; // solves the problem of adding track loading time
|
||||
break; // loading time, don't play sound yet
|
||||
case READY_PHASE: if(m_clock==0.0) // play sound at beginning of next frame
|
||||
sound_manager->playSfx(SOUND_PRESTART);
|
||||
if(m_clock>1.0)
|
||||
return; // loading time, don't play sound yet
|
||||
case READY_PHASE: if(m_clock>1.0)
|
||||
{
|
||||
m_phase=SET_PHASE;
|
||||
sound_manager->playSfx(SOUND_PRESTART);
|
||||
}
|
||||
break;
|
||||
m_clock += dt;
|
||||
return;
|
||||
case SET_PHASE : if(m_clock>2.0)
|
||||
{
|
||||
m_phase=GO_PHASE;
|
||||
@ -434,167 +445,148 @@ void World::updateRaceStatus(float dt)
|
||||
m_replay_recorder.pushFrame();
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
m_clock += dt;
|
||||
return;
|
||||
case GO_PHASE : if(race_manager->getRaceMode()==RaceManager::RM_FOLLOW_LEADER)
|
||||
{
|
||||
// Switch to race if more than 1 second has past
|
||||
if(m_clock<m_leader_intervals[0]-1.0f)
|
||||
m_phase=RACE_PHASE;
|
||||
m_clock -= dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_clock>1.0) // how long to display the 'go' message
|
||||
m_phase=RACE_PHASE;
|
||||
m_clock += dt;
|
||||
}
|
||||
return;
|
||||
case DELAY_FINISH_PHASE :
|
||||
{
|
||||
m_clock += dt;
|
||||
// Nothing more to do if delay time is not over yet
|
||||
if(m_clock < TIME_DELAY_TILL_FINISH) return;
|
||||
|
||||
m_phase = FINISH_PHASE;
|
||||
estimateFinishTimes();
|
||||
unlock_manager->raceFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
default : break;
|
||||
} // switch
|
||||
|
||||
if(race_manager->getRaceMode()==RaceManager::RM_FOLLOW_LEADER)
|
||||
{
|
||||
// Count 'normal' till race phase has started, then count backwards
|
||||
if(m_phase==RACE_PHASE || m_phase==GO_PHASE)
|
||||
m_clock -=dt;
|
||||
else
|
||||
m_clock +=dt;
|
||||
if(m_clock<0.0f)
|
||||
{
|
||||
if(m_leader_intervals.size()>1)
|
||||
m_leader_intervals.erase(m_leader_intervals.begin());
|
||||
m_clock=m_leader_intervals[0];
|
||||
int kart_number;
|
||||
// If the leader kart is not the first kart, remove the first
|
||||
// kart, otherwise remove the last kart.
|
||||
int position_to_remove = m_kart[0]->getPosition()==1
|
||||
? getCurrentNumKarts() : 1;
|
||||
for (kart_number=0; kart_number<(int)m_kart.size(); kart_number++)
|
||||
{
|
||||
if(m_kart[kart_number]->isEliminated()) continue;
|
||||
if(m_kart[kart_number]->getPosition()==position_to_remove)
|
||||
break;
|
||||
}
|
||||
if(kart_number==m_kart.size())
|
||||
{
|
||||
fprintf(stderr,"Problem with removing leader: position %d not found\n",
|
||||
position_to_remove);
|
||||
for(int i=0; i<(int)m_kart.size(); i++)
|
||||
{
|
||||
fprintf(stderr,"kart %d: eliminated %d position %d\n",
|
||||
i,m_kart[i]->isEliminated(), m_kart[i]->getPosition());
|
||||
} // for i
|
||||
} // kart_number==m_kart.size()
|
||||
else
|
||||
{
|
||||
removeKart(kart_number);
|
||||
}
|
||||
// The follow the leader race is over if there isonly one kart left,
|
||||
// or if all players have gone
|
||||
if(getCurrentNumKarts()==2 ||getCurrentNumPlayers()==0)
|
||||
{
|
||||
// Add the results for the remaining kart
|
||||
for(int i=1; i<(int)race_manager->getNumKarts(); i++)
|
||||
if(!m_kart[i]->isEliminated())
|
||||
race_manager->addKartResult(i, m_kart[i]->getPosition(),
|
||||
m_clock);
|
||||
m_phase=FINISH_PHASE;
|
||||
return;
|
||||
}
|
||||
} // m_clock<0
|
||||
return;
|
||||
} // if is follow leader mode
|
||||
return updateLeaderMode(dt);
|
||||
|
||||
// Now handling of normal race
|
||||
// ===========================
|
||||
m_clock += dt;
|
||||
// The status must now be race mode!
|
||||
// =================================
|
||||
m_clock += dt;
|
||||
|
||||
/*if all players have finished, or if only one kart is not finished when
|
||||
not in time trial mode, the race is over. Players are the last in the
|
||||
vector, so substracting the number of players finds the first player's
|
||||
position.*/
|
||||
int new_finished_karts = 0;
|
||||
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
|
||||
{
|
||||
if(m_kart[i]->isEliminated()) continue;
|
||||
// FIXME: this part should be done as part of Kart::update
|
||||
if ((m_kart[i]->getLap () >= race_manager->getNumLaps()) && !m_kart[i]->raceIsFinished())
|
||||
{
|
||||
m_kart[i]->setFinishingState(m_clock);
|
||||
|
||||
race_manager->addKartResult((int)i, m_kart[i]->getPosition(), m_clock);
|
||||
|
||||
++new_finished_karts;
|
||||
if(m_kart[i]->isPlayerKart())
|
||||
{
|
||||
race_manager->PlayerFinishes();
|
||||
RaceGUI* m=(RaceGUI*)menu_manager->getRaceMenu();
|
||||
if(m)
|
||||
{
|
||||
m->addMessage(m_kart[i]->getPosition()==1
|
||||
? _("You won")
|
||||
: _("You finished") ,
|
||||
m_kart[i], 2.0f, 60);
|
||||
m->addMessage( _("the race!"), m_kart[i], 2.0f, 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
race_manager->addFinishedKarts(new_finished_karts);
|
||||
|
||||
// 1) All karts are finished --> end the race
|
||||
// ==========================================
|
||||
// 2) A player comes in last, go immediately to finish phase
|
||||
// =========================================================
|
||||
if(race_manager->getFinishedKarts() >= race_manager->getNumKarts() )
|
||||
{
|
||||
m_phase = FINISH_PHASE;
|
||||
if(user_config->m_profile<0) // profiling number of laps -> print stats
|
||||
{
|
||||
float min_t=999999.9f, max_t=0.0, av_t=0.0;
|
||||
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
|
||||
{
|
||||
max_t = std::max(max_t, m_kart[i]->getFinishTime());
|
||||
min_t = std::min(min_t, m_kart[i]->getFinishTime());
|
||||
av_t += m_kart[i]->getFinishTime();
|
||||
printf("%s start %d end %d time %f\n",
|
||||
m_kart[i]->getName().c_str(),(int)i,
|
||||
m_kart[i]->getPosition(),
|
||||
m_kart[i]->getFinishTime());
|
||||
}
|
||||
printf("min %f max %f av %f\n",min_t, max_t, av_t/m_kart.size());
|
||||
std::exit(-2);
|
||||
}
|
||||
if(user_config->m_profile<0) printProfileResultAndExit();
|
||||
unlock_manager->raceFinished();
|
||||
} // if all karts are finished
|
||||
|
||||
// 2) All player karts are finished --> wait some
|
||||
// time for AI karts to arrive before finishing
|
||||
// ===============================================
|
||||
else if(race_manager->allPlayerFinished() && m_phase == RACE_PHASE &&
|
||||
!user_config->m_profile)
|
||||
// 3) All player karts are finished, but computer still racing
|
||||
// ===========================================================
|
||||
else if(race_manager->allPlayerFinished())
|
||||
{
|
||||
// Set delay mode to have time for camera animation, and
|
||||
// to give the AI some time to get non-estimated timings
|
||||
m_phase = DELAY_FINISH_PHASE;
|
||||
m_finish_delay_start_time = m_clock;
|
||||
m_clock = 0.0f;
|
||||
}
|
||||
|
||||
// 3) If the 'wait for AI' time is over, estimate arrival times & finish
|
||||
// =====================================================================
|
||||
else if(m_phase==DELAY_FINISH_PHASE &&
|
||||
m_clock-m_finish_delay_start_time>TIME_DELAY_TILL_FINISH &&
|
||||
!user_config->m_profile)
|
||||
{
|
||||
m_phase = FINISH_PHASE;
|
||||
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
|
||||
{
|
||||
if(!m_kart[i]->raceIsFinished())
|
||||
{
|
||||
const float est_finish_time = m_kart[i]->estimateFinishTime();
|
||||
m_kart[i]->setFinishingState(est_finish_time);
|
||||
race_manager->addKartResult((int)i, m_kart[i]->getPosition(),
|
||||
est_finish_time);
|
||||
} // if !raceIsFinished
|
||||
} // for i
|
||||
}
|
||||
|
||||
if(m_phase==FINISH_PHASE) unlock_manager->raceFinished();
|
||||
} // updateRaceStatus
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void World::estimateFinishTimes()
|
||||
{
|
||||
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
|
||||
{
|
||||
if(!m_kart[i]->hasFinishedRace())
|
||||
{
|
||||
const float est_finish_time = m_kart[i]->estimateFinishTime();
|
||||
m_kart[i]->raceFinished(est_finish_time);
|
||||
} // if !hasFinishedRace
|
||||
} // for i
|
||||
} // estimateFinishTimes
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void World::updateLeaderMode(float dt)
|
||||
{
|
||||
// Count 'normal' till race phase has started, then count backwards
|
||||
if(m_phase==RACE_PHASE || m_phase==GO_PHASE)
|
||||
m_clock -=dt;
|
||||
else
|
||||
m_clock +=dt;
|
||||
if(m_clock<0.0f)
|
||||
{
|
||||
if(m_leader_intervals.size()>1)
|
||||
m_leader_intervals.erase(m_leader_intervals.begin());
|
||||
m_clock=m_leader_intervals[0];
|
||||
int kart_number;
|
||||
// If the leader kart is not the first kart, remove the first
|
||||
// kart, otherwise remove the last kart.
|
||||
int position_to_remove = m_kart[0]->getPosition()==1
|
||||
? getCurrentNumKarts() : 1;
|
||||
for (kart_number=0; kart_number<(int)m_kart.size(); kart_number++)
|
||||
{
|
||||
if(m_kart[kart_number]->isEliminated()) continue;
|
||||
if(m_kart[kart_number]->getPosition()==position_to_remove)
|
||||
break;
|
||||
}
|
||||
if(kart_number==m_kart.size())
|
||||
{
|
||||
fprintf(stderr,"Problem with removing leader: position %d not found\n",
|
||||
position_to_remove);
|
||||
for(int i=0; i<(int)m_kart.size(); i++)
|
||||
{
|
||||
fprintf(stderr,"kart %d: eliminated %d position %d\n",
|
||||
i,m_kart[i]->isEliminated(), m_kart[i]->getPosition());
|
||||
} // for i
|
||||
} // kart_number==m_kart.size()
|
||||
else
|
||||
{
|
||||
removeKart(kart_number);
|
||||
}
|
||||
// The follow the leader race is over if there is only one kart left,
|
||||
// or if all players have gone
|
||||
if(getCurrentNumKarts()==2 ||getCurrentNumPlayers()==0)
|
||||
{
|
||||
// Add the results for the remaining kart
|
||||
for(int i=1; i<(int)race_manager->getNumKarts(); i++)
|
||||
if(!m_kart[i]->isEliminated())
|
||||
race_manager->RaceFinished(m_kart[i], m_clock);
|
||||
m_phase=FINISH_PHASE;
|
||||
return;
|
||||
}
|
||||
} // m_clock<0
|
||||
return;
|
||||
|
||||
} // updateLeaderMode
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void World::printProfileResultAndExit()
|
||||
{
|
||||
float min_t=999999.9f, max_t=0.0, av_t=0.0;
|
||||
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
|
||||
{
|
||||
max_t = std::max(max_t, m_kart[i]->getFinishTime());
|
||||
min_t = std::min(min_t, m_kart[i]->getFinishTime());
|
||||
av_t += m_kart[i]->getFinishTime();
|
||||
printf("%s start %d end %d time %f\n",
|
||||
m_kart[i]->getName().c_str(),(int)i,
|
||||
m_kart[i]->getPosition(),
|
||||
m_kart[i]->getFinishTime());
|
||||
}
|
||||
printf("min %f max %f av %f\n",min_t, max_t, av_t/m_kart.size());
|
||||
std::exit(-2);
|
||||
} // printProfileResultAndExit
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called in follow-leader-mode to remove the last kart
|
||||
*/
|
||||
@ -635,7 +627,7 @@ void World::removeKart(int kart_number)
|
||||
// ignored in all loops). Important:world->getCurrentNumKarts() returns
|
||||
// the number of karts still racing. This value can not be used for loops
|
||||
// over all karts, use race_manager->getNumKarts() instead!
|
||||
race_manager->addKartResult(kart_number, kart->getPosition(), m_clock);
|
||||
race_manager->RaceFinished(kart, m_clock);
|
||||
race_manager->eliminate(kart_number);
|
||||
kart->eliminate();
|
||||
m_eliminated_karts++;
|
||||
@ -657,7 +649,7 @@ void World::updateRacePosition ( int k )
|
||||
// Count karts ahead of the current kart, i.e. kart that are already
|
||||
// finished (the current kart k has not yet finished!!), have done more
|
||||
// laps, or the same number of laps, but a greater distance.
|
||||
if (m_kart[j]->raceIsFinished() ||
|
||||
if (m_kart[j]->hasFinishedRace() ||
|
||||
m_kart[j]->getLap() > m_kart[k]->getLap() ||
|
||||
(m_kart[j]->getLap() == m_kart[k]->getLap() &&
|
||||
m_kart[j]->getDistanceDownTrack() > m_kart[k]->getDistanceDownTrack()) )
|
||||
|
@ -111,7 +111,6 @@ public:
|
||||
private:
|
||||
Karts m_kart;
|
||||
std::vector<PlayerKart*> m_player_karts;
|
||||
float m_finish_delay_start_time;
|
||||
Physics* m_physics;
|
||||
float m_fastest_lap;
|
||||
Kart* m_fastest_kart;
|
||||
@ -123,14 +122,18 @@ private:
|
||||
std::vector<float>
|
||||
m_leader_intervals; // time till elimination in follow leader
|
||||
bool m_faster_music_active; // true if faster music was activated
|
||||
void updateRacePosition( int k );
|
||||
void loadTrack();
|
||||
void updateRaceStatus(float dt);
|
||||
void resetAllKarts();
|
||||
void removeKart(int kart_number);
|
||||
Kart* loadRobot(const std::string& kart_name, int position,
|
||||
sgCoord init_pos);
|
||||
|
||||
void updateRacePosition(int k);
|
||||
void updateHighscores ();
|
||||
void loadTrack ();
|
||||
void updateRaceStatus (float dt);
|
||||
void resetAllKarts ();
|
||||
void removeKart (int kart_number);
|
||||
Kart* loadRobot (const std::string& kart_name, int position,
|
||||
sgCoord init_pos);
|
||||
void updateLeaderMode (float dt);
|
||||
void printProfileResultAndExit();
|
||||
void estimateFinishTimes();
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
private:
|
||||
bool saveReplayHumanReadable( std::string const &filename ) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user