2007-05-27 16:01:53 +00:00
|
|
|
// $Id$
|
|
|
|
//
|
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
|
|
|
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
|
|
|
|
// Copyright (C) 2006 SuperTuxKart-Team, Joerg Henrichs, Steve Baker
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 2
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
2008-01-25 01:29:12 +00:00
|
|
|
#include <math.h>
|
2007-05-27 16:01:53 +00:00
|
|
|
#include <iostream>
|
|
|
|
#include <plib/ssg.h>
|
2008-04-15 13:57:18 +00:00
|
|
|
#include "bullet/Demos/OpenGL/GL_ShapeDrawer.h"
|
2007-05-27 16:01:53 +00:00
|
|
|
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
#include "loader.hpp"
|
2007-05-27 16:01:53 +00:00
|
|
|
#include "herring_manager.hpp"
|
|
|
|
#include "sound_manager.hpp"
|
2008-03-01 03:18:53 +00:00
|
|
|
#include "file_manager.hpp"
|
2007-05-27 16:01:53 +00:00
|
|
|
#include "skid_mark.hpp"
|
|
|
|
#include "user_config.hpp"
|
|
|
|
#include "constants.hpp"
|
|
|
|
#include "shadow.hpp"
|
|
|
|
#include "track.hpp"
|
|
|
|
#include "world.hpp"
|
|
|
|
#include "kart.hpp"
|
|
|
|
#include "ssg_help.hpp"
|
|
|
|
#include "physics.hpp"
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
#include "kart_properties_manager.hpp"
|
2007-05-27 16:01:53 +00:00
|
|
|
#include "gui/menu_manager.hpp"
|
|
|
|
#include "gui/race_gui.hpp"
|
|
|
|
#include "translation.hpp"
|
2008-04-15 13:57:18 +00:00
|
|
|
#include "smoke.hpp"
|
2007-05-27 16:01:53 +00:00
|
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
|
|
|
# define snprintf _snprintf
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
Kart::Kart (const std::string& kart_name, int position_ ,
|
2007-12-17 13:16:09 +00:00
|
|
|
sgCoord init_pos)
|
|
|
|
: TerrainInfo(1),
|
2007-12-11 02:48:10 +00:00
|
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
|
|
|
// Disable warning for using 'this' in base member initializer list
|
|
|
|
# pragma warning(disable:4355)
|
|
|
|
#endif
|
2007-12-17 13:16:09 +00:00
|
|
|
Moveable(true), m_attachment(this), m_collectable(this)
|
2007-12-11 02:48:10 +00:00
|
|
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
|
|
|
# pragma warning(1:4355)
|
|
|
|
#endif
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
m_kart_properties = kart_properties_manager->getKart(kart_name);
|
2008-04-17 00:20:06 +00:00
|
|
|
m_grid_position = position_;
|
|
|
|
m_initial_position = position_;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_num_herrings_gobbled = 0;
|
2008-04-15 13:57:18 +00:00
|
|
|
m_eliminated = false;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_finished_race = false;
|
|
|
|
m_finish_time = 0.0f;
|
|
|
|
m_wheelie_angle = 0.0f;
|
|
|
|
m_smokepuff = NULL;
|
|
|
|
m_smoke_system = NULL;
|
|
|
|
m_exhaust_pipe = NULL;
|
|
|
|
m_skidmark_left = NULL;
|
|
|
|
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:
|
2007-08-17 17:07:12 +00:00
|
|
|
m_max_speed = m_kart_properties->getMaximumSpeed();
|
|
|
|
m_max_speed_reverse_ratio = m_kart_properties->getMaxSpeedReverseRatio();
|
|
|
|
m_speed = 0.0f;
|
2007-05-27 16:01:53 +00:00
|
|
|
|
2008-02-12 00:10:05 +00:00
|
|
|
// Setting rescue to false is important! If rescue is set when reset() is
|
|
|
|
// called, it is assumed that this was triggered by a restart, and that
|
|
|
|
// the vehicle must be added back to the physics world. Since reset() is
|
|
|
|
// also called at the very start, it must be guaranteed that rescue is
|
|
|
|
// not set.
|
|
|
|
m_rescue = false;
|
|
|
|
m_wheel_rotation = 0;
|
|
|
|
|
|
|
|
m_wheel_front_l = NULL;
|
|
|
|
m_wheel_front_r = NULL;
|
|
|
|
m_wheel_rear_l = NULL;
|
|
|
|
m_wheel_rear_r = NULL;
|
|
|
|
m_lap_start_time = -1.0f;
|
2007-05-27 16:01:53 +00:00
|
|
|
loadData();
|
|
|
|
} // Kart
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------v
|
|
|
|
void Kart::createPhysics(ssgEntity *obj)
|
|
|
|
{
|
|
|
|
// First: Create the chassis of the kart
|
|
|
|
// -------------------------------------
|
|
|
|
// The size for bullet must be specified in half extends!
|
|
|
|
// ssgEntity *model = getModel();
|
|
|
|
float x_min, x_max, y_min, y_max, z_min, z_max;
|
|
|
|
MinMax(obj, &x_min, &x_max, &y_min, &y_max, &z_min, &z_max);
|
2008-02-17 12:29:14 +00:00
|
|
|
if(getName()=="Hexley" || getName()=="Wilber")
|
|
|
|
{
|
|
|
|
// These kart models are too small, so we get problems with stability.
|
|
|
|
// Till we find either better (bigger) models or improve their physics
|
|
|
|
// parameters to become playable, we just adjust the size of their
|
|
|
|
// physical models to be the same as the tuxkart model
|
2008-02-18 02:25:54 +00:00
|
|
|
x_min=-0.473799f;
|
|
|
|
x_max= 0.486361f;
|
|
|
|
y_min=-0.772244f;
|
|
|
|
y_max= 0.739075f;
|
|
|
|
z_min= 0.002806f;
|
|
|
|
z_max= 0.701095f;
|
2008-02-17 12:29:14 +00:00
|
|
|
}
|
2007-05-27 16:01:53 +00:00
|
|
|
float kart_width = x_max-x_min;
|
2007-11-03 13:13:26 +00:00
|
|
|
m_kart_length = y_max-y_min;
|
|
|
|
if(m_kart_length<1.2) m_kart_length=1.5f;
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
// The kart height is needed later to reset the physics to the correct
|
|
|
|
// position.
|
|
|
|
m_kart_height = z_max-z_min;
|
|
|
|
|
2007-11-03 13:13:26 +00:00
|
|
|
btBoxShape *shape = new btBoxShape(btVector3(0.5f*kart_width,
|
2007-11-08 22:40:15 +00:00
|
|
|
0.5f*m_kart_length,
|
|
|
|
0.5f*m_kart_height));
|
2007-05-27 16:01:53 +00:00
|
|
|
btTransform shiftCenterOfGravity;
|
|
|
|
shiftCenterOfGravity.setIdentity();
|
|
|
|
// Shift center of gravity downwards, so that the kart
|
|
|
|
// won't topple over too easy. This must be between 0 and 0.5
|
|
|
|
// (it's in units of kart_height)
|
|
|
|
const float CENTER_SHIFT = getGravityCenterShift();
|
|
|
|
shiftCenterOfGravity.setOrigin(btVector3(0.0f,0.0f,CENTER_SHIFT*m_kart_height));
|
2007-09-30 14:17:28 +00:00
|
|
|
|
2007-11-08 22:40:15 +00:00
|
|
|
m_kart_chassis.addChildShape(shiftCenterOfGravity, shape);
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
// Set mass and inertia
|
|
|
|
// --------------------
|
|
|
|
float mass=getMass();
|
|
|
|
|
|
|
|
// Position the chassis
|
|
|
|
// --------------------
|
|
|
|
btTransform trans;
|
|
|
|
trans.setIdentity();
|
2008-01-30 05:30:10 +00:00
|
|
|
createBody(mass, trans, &m_kart_chassis);
|
2008-02-05 11:56:21 +00:00
|
|
|
m_user_pointer.set(this);
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setDamping(m_kart_properties->getChassisLinearDamping(),
|
|
|
|
m_kart_properties->getChassisAngularDamping() );
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
// Reset velocities
|
|
|
|
// ----------------
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setLinearVelocity (btVector3(0.0f,0.0f,0.0f));
|
|
|
|
m_body->setAngularVelocity(btVector3(0.0f,0.0f,0.0f));
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
// Create the actual vehicle
|
|
|
|
// -------------------------
|
|
|
|
m_vehicle_raycaster =
|
|
|
|
new btDefaultVehicleRaycaster(world->getPhysics()->getPhysicsWorld());
|
2007-11-08 22:40:15 +00:00
|
|
|
m_tuning = new btRaycastVehicle::btVehicleTuning();
|
2007-09-30 14:17:28 +00:00
|
|
|
m_vehicle = new btRaycastVehicle(*m_tuning, m_body, m_vehicle_raycaster);
|
2007-11-03 13:13:26 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
// never deactivate the vehicle
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setActivationState(DISABLE_DEACTIVATION);
|
2007-05-27 16:01:53 +00:00
|
|
|
m_vehicle->setCoordinateSystem(/*right: */ 0, /*up: */ 2, /*forward: */ 1);
|
|
|
|
|
|
|
|
// Add wheels
|
|
|
|
// ----------
|
|
|
|
float wheel_width = m_kart_properties->getWheelWidth();
|
|
|
|
float wheel_radius = m_kart_properties->getWheelRadius();
|
2007-08-16 07:09:26 +00:00
|
|
|
float suspension_rest = m_kart_properties->getSuspensionRest();
|
2007-11-03 13:13:26 +00:00
|
|
|
float connection_height = -(0.5f-CENTER_SHIFT)*m_kart_height;
|
2007-05-27 16:01:53 +00:00
|
|
|
btVector3 wheel_direction(0.0f, 0.0f, -1.0f);
|
|
|
|
btVector3 wheel_axle(1.0f,0.0f,0.0f);
|
|
|
|
|
|
|
|
// right front wheel
|
|
|
|
btVector3 wheel_coord(0.5f*kart_width-0.3f*wheel_width,
|
2007-11-03 13:13:26 +00:00
|
|
|
0.5f*m_kart_length-wheel_radius,
|
2007-05-27 16:01:53 +00:00
|
|
|
connection_height);
|
|
|
|
m_vehicle->addWheel(wheel_coord, wheel_direction, wheel_axle,
|
|
|
|
suspension_rest, wheel_radius, *m_tuning,
|
|
|
|
/* isFrontWheel: */ true);
|
|
|
|
|
|
|
|
// left front wheel
|
|
|
|
wheel_coord = btVector3(-0.5f*kart_width+0.3f*wheel_width,
|
2007-11-03 13:13:26 +00:00
|
|
|
0.5f*m_kart_length-wheel_radius,
|
2007-05-27 16:01:53 +00:00
|
|
|
connection_height);
|
|
|
|
m_vehicle->addWheel(wheel_coord, wheel_direction, wheel_axle,
|
|
|
|
suspension_rest, wheel_radius, *m_tuning,
|
|
|
|
/* isFrontWheel: */ true);
|
|
|
|
|
|
|
|
// right rear wheel
|
2007-11-03 13:13:26 +00:00
|
|
|
wheel_coord = btVector3(0.5f*kart_width-0.3f*wheel_width,
|
|
|
|
-0.5f*m_kart_length+wheel_radius,
|
2007-05-27 16:01:53 +00:00
|
|
|
connection_height);
|
|
|
|
m_vehicle->addWheel(wheel_coord, wheel_direction, wheel_axle,
|
|
|
|
suspension_rest, wheel_radius, *m_tuning,
|
|
|
|
/* isFrontWheel: */ false);
|
|
|
|
|
|
|
|
// right rear wheel
|
2007-11-03 13:13:26 +00:00
|
|
|
wheel_coord = btVector3(-0.5f*kart_width+0.3f*wheel_width,
|
|
|
|
-0.5f*m_kart_length+wheel_radius,
|
2007-05-27 16:01:53 +00:00
|
|
|
connection_height);
|
|
|
|
m_vehicle->addWheel(wheel_coord, wheel_direction, wheel_axle,
|
|
|
|
suspension_rest, wheel_radius, *m_tuning,
|
|
|
|
/* isFrontWheel: */ false);
|
|
|
|
|
|
|
|
for(int i=0; i<m_vehicle->getNumWheels(); i++)
|
|
|
|
{
|
2007-11-08 22:40:15 +00:00
|
|
|
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
|
2007-05-27 16:01:53 +00:00
|
|
|
wheel.m_suspensionStiffness = m_kart_properties->getSuspensionStiffness();
|
|
|
|
wheel.m_wheelsDampingRelaxation = m_kart_properties->getWheelDampingRelaxation();
|
|
|
|
wheel.m_wheelsDampingCompression = m_kart_properties->getWheelDampingCompression();
|
|
|
|
wheel.m_frictionSlip = m_kart_properties->getFrictionSlip();
|
|
|
|
wheel.m_rollInfluence = m_kart_properties->getRollInfluence();
|
|
|
|
}
|
|
|
|
world->getPhysics()->addKart(this, m_vehicle);
|
|
|
|
|
|
|
|
} // createPhysics
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
Kart::~Kart()
|
|
|
|
{
|
2007-11-08 22:40:15 +00:00
|
|
|
if(m_smokepuff) delete m_smokepuff;
|
2008-02-21 13:08:21 +00:00
|
|
|
if(m_smoke_system != NULL) delete m_smoke_system;
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
sgMat4 wheel_steer;
|
|
|
|
sgMakeIdentMat4(wheel_steer);
|
|
|
|
if (m_wheel_front_l) m_wheel_front_l->setTransform(wheel_steer);
|
|
|
|
if (m_wheel_front_r) m_wheel_front_r->setTransform(wheel_steer);
|
|
|
|
|
|
|
|
|
|
|
|
ssgDeRefDelete(m_shadow);
|
|
|
|
ssgDeRefDelete(m_wheel_front_l);
|
|
|
|
ssgDeRefDelete(m_wheel_front_r);
|
|
|
|
ssgDeRefDelete(m_wheel_rear_l);
|
|
|
|
ssgDeRefDelete(m_wheel_rear_r);
|
|
|
|
|
|
|
|
if(m_skidmark_left ) delete m_skidmark_left ;
|
|
|
|
if(m_skidmark_right) delete m_skidmark_right;
|
|
|
|
|
2007-11-08 22:40:15 +00:00
|
|
|
delete m_vehicle;
|
2007-05-27 16:01:53 +00:00
|
|
|
delete m_tuning;
|
|
|
|
delete m_vehicle_raycaster;
|
2007-11-03 13:13:26 +00:00
|
|
|
world->getPhysics()->removeKart(this);
|
2007-11-08 22:40:15 +00:00
|
|
|
for(int i=0; i<m_kart_chassis.getNumChildShapes(); i++)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2007-11-08 22:40:15 +00:00
|
|
|
delete m_kart_chassis.getChildShape(i);
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
} // ~Kart
|
|
|
|
|
2008-04-15 13:57:18 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::eliminate()
|
|
|
|
{
|
|
|
|
m_eliminated = true;
|
|
|
|
world->getPhysics()->removeKart(this);
|
|
|
|
|
|
|
|
// make the kart invisible by placing it way under the track
|
|
|
|
sgVec3 hell; hell[0]=0.0f; hell[1]=0.0f; hell[2] = -10000.0f;
|
|
|
|
getModelTransform()->setTransform(hell);
|
|
|
|
} // eliminate
|
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Returns true if the kart is 'resting'
|
|
|
|
*
|
|
|
|
* Returns true if the kart is 'resting', i.e. (nearly) not moving.
|
|
|
|
*/
|
2008-01-16 00:09:05 +00:00
|
|
|
bool Kart::isInRest() const
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2007-09-30 14:17:28 +00:00
|
|
|
return fabs(m_body->getLinearVelocity ().z())<0.2;
|
2007-05-27 16:01:53 +00:00
|
|
|
} // isInRest
|
2007-12-17 13:16:09 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Modifies the physics parameter to simulate an attached anvil.
|
|
|
|
* The velocity is multiplicated by f, and the mass of the kart is increased.
|
|
|
|
*/
|
|
|
|
void Kart::adjustSpeedWeight(float f)
|
|
|
|
{
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setLinearVelocity(m_body->getLinearVelocity()*f);
|
2007-05-27 16:01:53 +00:00
|
|
|
// getMass returns the mass increased by the attachment
|
|
|
|
btVector3 inertia;
|
|
|
|
float m=getMass();
|
2007-11-08 22:40:15 +00:00
|
|
|
m_kart_chassis.calculateLocalInertia(m, inertia);
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setMassProps(m, inertia);
|
2007-05-27 16:01:53 +00:00
|
|
|
} // adjustSpeedWeight
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::reset()
|
|
|
|
{
|
2008-04-15 13:57:18 +00:00
|
|
|
if(m_eliminated)
|
|
|
|
{
|
|
|
|
world->getPhysics()->addKart(this, m_vehicle);
|
|
|
|
}
|
2007-05-27 16:01:53 +00:00
|
|
|
Moveable::reset();
|
|
|
|
|
|
|
|
m_attachment.clear();
|
|
|
|
m_collectable.clear();
|
|
|
|
|
|
|
|
m_race_lap = -1;
|
|
|
|
m_lap_start_time = -1.0f;
|
2007-12-08 13:04:56 +00:00
|
|
|
m_time_at_last_lap = 99999.9f;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_shortcut_sector = Track::UNKNOWN_SECTOR;
|
|
|
|
m_race_position = 9;
|
|
|
|
m_finished_race = false;
|
2008-04-15 13:57:18 +00:00
|
|
|
m_eliminated = false;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_finish_time = 0.0f;
|
|
|
|
m_zipper_time_left = 0.0f;
|
|
|
|
m_num_herrings_gobbled = 0;
|
2008-01-25 01:29:12 +00:00
|
|
|
m_wheel_rotation = 0;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_wheelie_angle = 0.0f;
|
|
|
|
|
|
|
|
m_controls.lr = 0.0f;
|
|
|
|
m_controls.accel = 0.0f;
|
|
|
|
m_controls.brake = false;
|
|
|
|
m_controls.wheelie = false;
|
|
|
|
m_controls.jump = false;
|
|
|
|
m_controls.fire = false;
|
|
|
|
|
2008-02-11 02:20:51 +00:00
|
|
|
// Set the brakes so that karts don't slide downhill
|
|
|
|
for(int i=0; i<4; i++) m_vehicle->setBrake(5.0f, i);
|
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
world->m_track->findRoadSector(m_curr_pos.xyz, &m_track_sector);
|
|
|
|
|
|
|
|
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
|
|
|
|
//the road, so we have to use another function to find the sector.
|
|
|
|
if (m_track_sector == Track::UNKNOWN_SECTOR )
|
|
|
|
{
|
|
|
|
m_on_road = false;
|
|
|
|
m_track_sector = world->m_track->findOutOfRoadSector(
|
|
|
|
m_curr_pos.xyz, Track::RS_DONT_KNOW, Track::UNKNOWN_SECTOR );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_on_road = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
world->m_track->spatialToTrack( m_curr_track_coords, m_curr_pos.xyz,
|
|
|
|
m_track_sector );
|
|
|
|
|
2008-01-15 11:38:54 +00:00
|
|
|
m_vehicle->applyEngineForce (0.0f, 2);
|
|
|
|
m_vehicle->applyEngineForce (0.0f, 3);
|
2007-09-26 03:43:02 +00:00
|
|
|
// Set heading:
|
2007-12-20 04:37:35 +00:00
|
|
|
m_transform.setRotation(btQuaternion(btVector3(0.0f, 0.0f, 1.0f),
|
|
|
|
DEGREE_TO_RAD(m_reset_pos.hpr[0])) );
|
2007-09-26 03:43:02 +00:00
|
|
|
// Set position
|
2007-12-20 04:37:35 +00:00
|
|
|
m_transform.setOrigin(btVector3(m_reset_pos.xyz[0],
|
|
|
|
m_reset_pos.xyz[1],
|
|
|
|
m_reset_pos.xyz[2]+0.5f*m_kart_height));
|
|
|
|
m_body->setCenterOfMassTransform(m_transform);
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setLinearVelocity (btVector3(0.0f,0.0f,0.0f));
|
|
|
|
m_body->setAngularVelocity(btVector3(0.0f,0.0f,0.0f));
|
2008-02-12 00:01:27 +00:00
|
|
|
m_motion_state->setWorldTransform(m_transform);
|
2007-05-27 16:01:53 +00:00
|
|
|
for(int j=0; j<m_vehicle->getNumWheels(); j++)
|
|
|
|
{
|
|
|
|
m_vehicle->updateWheelTransform(j, true);
|
|
|
|
}
|
|
|
|
|
2008-02-12 00:10:05 +00:00
|
|
|
// if the kart was being rescued when a restart is called,
|
|
|
|
// add the vehicle back into the physical world!
|
|
|
|
if(m_rescue)
|
|
|
|
{
|
|
|
|
world->getPhysics()->addKart(this, m_vehicle);
|
|
|
|
}
|
|
|
|
m_rescue = false;
|
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
placeModel();
|
2008-02-12 00:01:27 +00:00
|
|
|
TerrainInfo::update(m_transform.getOrigin());
|
2007-05-27 16:01:53 +00:00
|
|
|
} // reset
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::doLapCounting ()
|
|
|
|
{
|
|
|
|
bool newLap = m_last_track_coords[1] > 300.0f && m_curr_track_coords[1] < 20.0f;
|
2008-02-21 03:40:40 +00:00
|
|
|
if ( newLap )
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
|
|
|
// Only increase the lap counter and set the new time if the
|
|
|
|
// kart hasn't already finished the race (otherwise the race_gui
|
|
|
|
// will begin another countdown).
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
if(m_race_lap+1<=race_manager->getNumLaps())
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2008-02-08 04:43:35 +00:00
|
|
|
setTimeAtLap(world->getTime());
|
2007-05-27 16:01:53 +00:00
|
|
|
m_race_lap++ ;
|
|
|
|
}
|
2008-03-17 05:18:26 +00:00
|
|
|
// Sound manager makes sure that only the first call switches the music
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
if(m_race_lap==race_manager->getNumLaps()-1) // last lap started
|
2008-03-17 05:18:26 +00:00
|
|
|
{
|
|
|
|
sound_manager->switchToFastMusic();
|
|
|
|
}
|
2007-05-27 16:01:53 +00:00
|
|
|
// Only do timings if original time was set properly. Driving backwards
|
2008-02-08 04:43:35 +00:00
|
|
|
// over the start line will cause the lap start time to be set to -1.
|
2007-05-27 16:01:53 +00:00
|
|
|
if(m_lap_start_time>=0.0)
|
|
|
|
{
|
2007-12-12 22:35:27 +00:00
|
|
|
float time_per_lap;
|
|
|
|
if (m_race_lap == 1) // just completed first lap
|
|
|
|
{
|
2008-02-08 04:43:35 +00:00
|
|
|
time_per_lap=world->getTime();
|
2007-12-12 22:35:27 +00:00
|
|
|
}
|
|
|
|
else //completing subsequent laps
|
|
|
|
{
|
2008-02-08 04:43:35 +00:00
|
|
|
time_per_lap=world->getTime()-m_lap_start_time;
|
2007-12-12 22:35:27 +00:00
|
|
|
}
|
|
|
|
|
2008-04-15 13:57:18 +00:00
|
|
|
if(time_per_lap < world->getFastestLapTime() &&
|
|
|
|
race_manager->raceHasLaps())
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
|
|
|
world->setFastestLap(this, time_per_lap);
|
|
|
|
RaceGUI* m=(RaceGUI*)menu_manager->getRaceMenu();
|
|
|
|
if(m)
|
|
|
|
{
|
|
|
|
m->addMessage(_("New fastest lap"), NULL,
|
|
|
|
2.0f, 40, 100, 210, 100);
|
|
|
|
char s[20];
|
|
|
|
m->TimeToString(time_per_lap, s);
|
|
|
|
snprintf(m_fastest_lap_message, sizeof(m_fastest_lap_message),
|
|
|
|
"%s: %s",s, getName().c_str());
|
|
|
|
m->addMessage(m_fastest_lap_message, NULL,
|
|
|
|
2.0f, 40, 100, 210, 100);
|
|
|
|
} // if m
|
|
|
|
} // if time_per_lap < world->getFasterstLapTime()
|
|
|
|
if(isPlayerKart())
|
|
|
|
{
|
|
|
|
// Put in in the highscore list???
|
|
|
|
//printf("Time per lap: %s %f\n", getName().c_str(), time_per_lap);
|
|
|
|
}
|
|
|
|
}
|
2008-02-08 04:43:35 +00:00
|
|
|
m_lap_start_time = world->getTime();
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
else if ( m_curr_track_coords[1] > 300.0f && m_last_track_coords[1] < 20.0f)
|
|
|
|
{
|
|
|
|
m_race_lap-- ;
|
|
|
|
// Prevent cheating by setting time to a negative number, indicating
|
|
|
|
// that the line wasn't crossed properly.
|
|
|
|
m_lap_start_time = -1.0f;
|
2008-04-15 13:57:18 +00:00
|
|
|
} else
|
|
|
|
{ // Switch to fast music in case of follow the leader when only 3 karts are left
|
|
|
|
if(race_manager->getRaceMode()==RaceManager::RM_FOLLOW_LEADER &&
|
|
|
|
world->getCurrentNumKarts()==3)
|
|
|
|
{
|
|
|
|
sound_manager->switchToFastMusic();
|
|
|
|
}
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
} // doLapCounting
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::collectedHerring(Herring* herring)
|
|
|
|
{
|
|
|
|
const herringType TYPE = herring->getType();
|
|
|
|
const int OLD_HERRING_GOBBLED = m_num_herrings_gobbled;
|
|
|
|
|
|
|
|
switch (TYPE)
|
|
|
|
{
|
|
|
|
case HE_GREEN : m_attachment.hitGreenHerring(); break;
|
|
|
|
case HE_SILVER : m_num_herrings_gobbled++ ; break;
|
|
|
|
case HE_GOLD : m_num_herrings_gobbled += 3 ; break;
|
|
|
|
case HE_RED : int n=1 + 4*getNumHerring() / MAX_HERRING_EATEN;
|
|
|
|
m_collectable.hitRedHerring(n); break;
|
|
|
|
} // switch TYPE
|
|
|
|
|
|
|
|
if ( m_num_herrings_gobbled > MAX_HERRING_EATEN )
|
|
|
|
m_num_herrings_gobbled = MAX_HERRING_EATEN;
|
|
|
|
|
|
|
|
if(OLD_HERRING_GOBBLED < m_num_herrings_gobbled &&
|
|
|
|
m_num_herrings_gobbled == MAX_HERRING_EATEN)
|
|
|
|
sound_manager->playSfx(SOUND_FULL);
|
|
|
|
} // hitHerring
|
|
|
|
|
2007-08-18 14:26:11 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2007-12-20 04:37:35 +00:00
|
|
|
// Simulates gears
|
2007-08-18 14:26:11 +00:00
|
|
|
float Kart::getActualWheelForce()
|
|
|
|
{
|
2008-01-01 14:30:39 +00:00
|
|
|
float zipperF=(m_zipper_time_left>0.0f) ? stk_config->m_zipper_force : 0.0f;
|
2007-08-21 14:50:45 +00:00
|
|
|
const std::vector<float>& gear_ratio=m_kart_properties->getGearSwitchRatio();
|
|
|
|
for(unsigned int i=0; i<gear_ratio.size(); i++)
|
2007-08-18 14:26:11 +00:00
|
|
|
{
|
2007-08-21 14:50:45 +00:00
|
|
|
if(m_speed <= m_max_speed*gear_ratio[i])
|
2008-01-01 14:30:39 +00:00
|
|
|
return getMaxPower()*m_kart_properties->getGearPowerIncrease()[i]+zipperF;
|
2007-08-18 14:26:11 +00:00
|
|
|
}
|
2008-01-01 14:30:39 +00:00
|
|
|
return getMaxPower()+zipperF;
|
2007-08-21 14:50:45 +00:00
|
|
|
|
|
|
|
} // getActualWheelForce
|
2007-08-18 14:26:11 +00:00
|
|
|
|
2007-11-08 12:31:54 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2008-02-11 02:20:51 +00:00
|
|
|
/** The kart is on ground if all 4 wheels touch the ground
|
|
|
|
*/
|
|
|
|
bool Kart::isOnGround() const
|
2007-11-08 12:31:54 +00:00
|
|
|
{
|
|
|
|
return m_vehicle->getWheelInfo(0).m_raycastInfo.m_isInContact &&
|
|
|
|
m_vehicle->getWheelInfo(1).m_raycastInfo.m_isInContact &&
|
|
|
|
m_vehicle->getWheelInfo(2).m_raycastInfo.m_isInContact &&
|
|
|
|
m_vehicle->getWheelInfo(3).m_raycastInfo.m_isInContact;
|
|
|
|
} // isOnGround
|
2007-05-27 16:01:53 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2007-08-21 14:50:45 +00:00
|
|
|
void Kart::handleExplosion(const sgVec3& pos, bool direct_hit)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2007-08-21 14:50:45 +00:00
|
|
|
if(direct_hit) {
|
2007-09-30 14:17:28 +00:00
|
|
|
btVector3 velocity = m_body->getLinearVelocity();
|
2007-08-21 14:50:45 +00:00
|
|
|
|
|
|
|
velocity.setX( 0.0f );
|
|
|
|
velocity.setY( 0.0f );
|
|
|
|
velocity.setZ( 3.5f );
|
2007-08-17 17:07:12 +00:00
|
|
|
|
2007-08-21 14:50:45 +00:00
|
|
|
getVehicle()->getRigidBody()->setLinearVelocity( velocity );
|
|
|
|
}
|
2007-12-17 13:16:09 +00:00
|
|
|
else // only affected by a distant explosion
|
2007-08-21 14:50:45 +00:00
|
|
|
{
|
|
|
|
sgVec3 diff;
|
|
|
|
sgSubVec3(diff, getCoord()->xyz, pos);
|
|
|
|
float len2=sgLengthSquaredVec3(diff);
|
|
|
|
|
2007-12-17 13:16:09 +00:00
|
|
|
// The correct formhale would be to first normalise diff,
|
2007-08-21 14:50:45 +00:00
|
|
|
// then apply the impulse (which decreases 1/r^2 depending
|
|
|
|
// on the distance r), so:
|
|
|
|
// diff/len(diff) * impulseSize/len(diff)^2
|
|
|
|
// = diff*impulseSize/len(diff)^3
|
|
|
|
// We use diff*impulseSize/len(diff)^2 here, this makes the impulse
|
|
|
|
// somewhat larger, which is actually more fun :)
|
|
|
|
sgScaleVec3(diff,stk_config->m_explosion_impulse/len2);
|
|
|
|
btVector3 impulse(diff[0],diff[1], diff[2]);
|
|
|
|
getVehicle()->getRigidBody()->applyCentralImpulse(impulse);
|
|
|
|
}
|
|
|
|
} // handleExplosion
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-04-16 09:57:50 +00:00
|
|
|
void Kart::update(float dt)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2008-01-01 14:30:39 +00:00
|
|
|
m_zipper_time_left = m_zipper_time_left>0.0f ? m_zipper_time_left-dt : 0.0f;
|
|
|
|
|
2008-01-25 01:29:12 +00:00
|
|
|
//m_wheel_rotation gives the rotation around the X-axis, and since velocity's
|
2007-05-27 16:01:53 +00:00
|
|
|
//timeframe is the delta time, we don't have to multiply it with dt.
|
2008-01-25 01:29:12 +00:00
|
|
|
m_wheel_rotation += m_speed*dt / m_kart_properties->getWheelRadius();
|
|
|
|
m_wheel_rotation=fmodf(m_wheel_rotation, 2*M_PI);
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
if ( m_rescue )
|
|
|
|
{
|
|
|
|
// Let the kart raise 2m in the 2 seconds of the rescue
|
|
|
|
const float rescue_time = 2.0f;
|
|
|
|
const float rescue_height = 2.0f;
|
|
|
|
if(m_attachment.getType() != ATTACH_TINYTUX)
|
|
|
|
{
|
|
|
|
if(isPlayerKart()) sound_manager -> playSfx ( SOUND_BZZT );
|
|
|
|
m_attachment.set( ATTACH_TINYTUX, rescue_time ) ;
|
|
|
|
m_rescue_pitch = m_curr_pos.hpr[1];
|
|
|
|
m_rescue_roll = m_curr_pos.hpr[2];
|
2007-11-03 13:13:26 +00:00
|
|
|
world->getPhysics()->removeKart(this);
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
m_curr_pos.xyz[2] += rescue_height*dt/rescue_time;
|
|
|
|
|
2008-01-15 11:38:54 +00:00
|
|
|
m_transform.setOrigin(btVector3(m_curr_pos.xyz[0],m_curr_pos.xyz[1],
|
|
|
|
m_curr_pos.xyz[2]));
|
2007-11-03 13:13:26 +00:00
|
|
|
btQuaternion q_roll (btVector3(0.f, 1.f, 0.f),
|
|
|
|
-m_rescue_roll*dt/rescue_time*M_PI/180.0f);
|
|
|
|
btQuaternion q_pitch(btVector3(1.f, 0.f, 0.f),
|
|
|
|
-m_rescue_pitch*dt/rescue_time*M_PI/180.0f);
|
2007-12-20 04:37:35 +00:00
|
|
|
m_transform.setRotation(m_transform.getRotation()*q_roll*q_pitch);
|
|
|
|
m_body->setCenterOfMassTransform(m_transform);
|
|
|
|
|
2007-12-12 14:07:26 +00:00
|
|
|
//printf("Set %f %f %f\n",pos.getOrigin().x(),pos.getOrigin().y(),pos.getOrigin().z());
|
2007-05-27 16:01:53 +00:00
|
|
|
} // if m_rescue
|
2008-01-01 14:30:39 +00:00
|
|
|
m_attachment.update(dt);
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
/*smoke drawing control point*/
|
|
|
|
if ( user_config->m_smoke )
|
|
|
|
{
|
|
|
|
if (m_smoke_system != NULL)
|
|
|
|
m_smoke_system->update (dt);
|
|
|
|
} // user_config->smoke
|
|
|
|
updatePhysics(dt);
|
|
|
|
|
|
|
|
sgCopyVec2 ( m_last_track_coords, m_curr_track_coords );
|
2007-12-17 13:42:19 +00:00
|
|
|
|
2007-12-17 13:16:09 +00:00
|
|
|
Moveable::update(dt);
|
2008-01-16 00:09:05 +00:00
|
|
|
|
|
|
|
// Check if a kart is (nearly) upside down and not moving much --> automatic rescue
|
2008-03-02 12:43:23 +00:00
|
|
|
if((fabs(m_curr_pos.hpr[2])>60 && fabs(getSpeed())<3.0f) )
|
2008-01-16 00:09:05 +00:00
|
|
|
{
|
|
|
|
forceRescue();
|
|
|
|
}
|
|
|
|
|
2008-01-01 14:30:39 +00:00
|
|
|
btTransform trans=getTrans();
|
2008-03-04 03:37:42 +00:00
|
|
|
// Add a certain epsilon (0.1) to the height of the kart. This avoids
|
|
|
|
// problems of the ray being cast from under the track (which happened
|
|
|
|
// e.g. on tux tollway when jumping down from the ramp).
|
|
|
|
btVector3 pos_plus_epsilon = trans.getOrigin()+btVector3(0,0,0.1f);
|
|
|
|
TerrainInfo::update(pos_plus_epsilon);
|
2007-12-17 13:16:09 +00:00
|
|
|
if (getHoT()==Track::NOHIT ||
|
|
|
|
(getMaterial()->isReset() && isOnGround()) )
|
|
|
|
{
|
|
|
|
forceRescue();
|
|
|
|
}
|
2008-01-01 14:30:39 +00:00
|
|
|
else if(getMaterial()->isZipper())
|
|
|
|
{
|
|
|
|
handleZipper();
|
|
|
|
}
|
2007-12-17 13:16:09 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
for(int i=0; i<m_vehicle->getNumWheels(); i++)
|
|
|
|
{
|
|
|
|
// terrain dependent friction
|
2007-12-17 13:42:19 +00:00
|
|
|
m_vehicle->getWheelInfo(i).m_frictionSlip = getFrictionSlip() *
|
|
|
|
getMaterial()->getFriction();
|
2007-12-17 13:16:09 +00:00
|
|
|
} // for i<getNumWheels
|
2007-12-17 13:42:19 +00:00
|
|
|
|
2007-12-17 13:16:09 +00:00
|
|
|
} // if there is terrain and it's not a reset material
|
2007-05-27 16:01:53 +00:00
|
|
|
|
2007-12-20 04:37:35 +00:00
|
|
|
// Check if any herring was hit.
|
|
|
|
herring_manager->hitHerring(this);
|
|
|
|
|
2007-06-15 01:59:33 +00:00
|
|
|
// Save the last valid sector for forced rescue on shortcuts
|
|
|
|
if(m_track_sector != Track::UNKNOWN_SECTOR &&
|
|
|
|
!m_rescue )
|
|
|
|
{
|
|
|
|
m_shortcut_sector = m_track_sector;
|
|
|
|
}
|
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
int prev_sector = m_track_sector;
|
2007-06-15 01:59:33 +00:00
|
|
|
if(!m_rescue)
|
|
|
|
world->m_track->findRoadSector(m_curr_pos.xyz, &m_track_sector);
|
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
// Check if the kart is taking a shortcut (if it's not already doing one):
|
2008-03-03 11:51:01 +00:00
|
|
|
if(!m_rescue && world->m_track->isShortcut(prev_sector, m_track_sector))
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2008-03-03 11:51:01 +00:00
|
|
|
if(isPlayerKart())
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2008-03-03 11:51:01 +00:00
|
|
|
forceRescue(/*is rescue*/ true); // bring karts back to where they left the track.
|
|
|
|
RaceGUI* m=(RaceGUI*)menu_manager->getRaceMenu();
|
|
|
|
// Can happen if the option menu is called
|
|
|
|
if(m)
|
|
|
|
m->addMessage(_("Invalid short-cut!!"), this, 2.0f, 60);
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-15 01:59:33 +00:00
|
|
|
if (m_track_sector == Track::UNKNOWN_SECTOR && !m_rescue)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
|
|
|
m_on_road = false;
|
|
|
|
if( m_curr_track_coords[0] > 0.0 )
|
|
|
|
m_track_sector = world->m_track->findOutOfRoadSector(
|
|
|
|
m_curr_pos.xyz, Track::RS_RIGHT, prev_sector );
|
|
|
|
else
|
|
|
|
m_track_sector = world->m_track->findOutOfRoadSector(
|
|
|
|
m_curr_pos.xyz, Track::RS_LEFT, prev_sector );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_on_road = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sector = world->m_track->spatialToTrack( m_curr_track_coords,
|
|
|
|
m_curr_pos.xyz,
|
|
|
|
m_track_sector );
|
2008-02-21 03:40:40 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
doLapCounting () ;
|
|
|
|
processSkidMarks();
|
|
|
|
} // update
|
|
|
|
|
2008-01-01 14:30:39 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2008-03-05 13:22:00 +00:00
|
|
|
// Set zipper time, and apply one time additional speed boost
|
2008-01-01 14:30:39 +00:00
|
|
|
void Kart::handleZipper()
|
|
|
|
{
|
2008-03-05 13:22:00 +00:00
|
|
|
m_zipper_time_left = stk_config->m_zipper_time;
|
|
|
|
const btVector3& v = m_body->getLinearVelocity();
|
|
|
|
float current_speed = v.length();
|
|
|
|
float speed = std::min(current_speed+stk_config->m_zipper_speed_gain,
|
|
|
|
getMaxSpeed());
|
|
|
|
|
|
|
|
m_body->setLinearVelocity(v/current_speed*speed);
|
2008-01-01 14:30:39 +00:00
|
|
|
} // handleZipper
|
2007-05-27 16:01:53 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define sgn(x) ((x<0)?-1.0f:((x>0)?1.0f:0.0f))
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void Kart::draw()
|
|
|
|
{
|
|
|
|
float m[16];
|
2008-01-01 14:30:39 +00:00
|
|
|
btTransform t=getTrans();
|
2007-05-27 16:01:53 +00:00
|
|
|
t.getOpenGLMatrix(m);
|
|
|
|
|
|
|
|
btVector3 wire_color(0.5f, 0.5f, 0.5f);
|
2007-09-30 14:17:28 +00:00
|
|
|
world->getPhysics()->debugDraw(m, m_body->getCollisionShape(),
|
2007-05-27 16:01:53 +00:00
|
|
|
wire_color);
|
2007-11-08 22:40:15 +00:00
|
|
|
btCylinderShapeX wheelShape( btVector3(0.3f,
|
2007-05-27 16:01:53 +00:00
|
|
|
m_kart_properties->getWheelRadius(),
|
2007-11-08 22:40:15 +00:00
|
|
|
m_kart_properties->getWheelRadius()));
|
2007-05-27 16:01:53 +00:00
|
|
|
btVector3 wheelColor(1,0,0);
|
|
|
|
for(int i=0; i<m_vehicle->getNumWheels(); i++)
|
|
|
|
{
|
|
|
|
m_vehicle->updateWheelTransform(i, true);
|
|
|
|
float m[16];
|
|
|
|
m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(m);
|
2007-11-08 22:40:15 +00:00
|
|
|
world->getPhysics()->debugDraw(m, &wheelShape, wheelColor);
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
} // draw
|
2007-12-17 13:16:09 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/** Returned an additional engine power boost when doing a wheele.
|
|
|
|
***/
|
2007-12-17 13:16:09 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
float Kart::handleWheelie(float dt)
|
|
|
|
{
|
|
|
|
// Handle wheelies
|
|
|
|
// ===============
|
|
|
|
if ( m_controls.wheelie &&
|
|
|
|
m_speed >= getMaxSpeed()*getWheelieMaxSpeedRatio())
|
|
|
|
{
|
|
|
|
if ( m_wheelie_angle < getWheelieMaxPitch() )
|
|
|
|
m_wheelie_angle += getWheeliePitchRate() * dt;
|
|
|
|
else
|
|
|
|
m_wheelie_angle = getWheelieMaxPitch();
|
|
|
|
}
|
|
|
|
else if ( m_wheelie_angle > 0.0f )
|
|
|
|
{
|
|
|
|
m_wheelie_angle -= getWheelieRestoreRate() * dt;
|
|
|
|
if ( m_wheelie_angle <= 0.0f ) m_wheelie_angle = 0.0f ;
|
|
|
|
}
|
|
|
|
if(m_wheelie_angle <=0.0f) return 0.0f;
|
|
|
|
|
2007-12-20 04:37:35 +00:00
|
|
|
const btTransform& chassisTrans = getTrans();
|
2007-05-27 16:01:53 +00:00
|
|
|
btVector3 targetUp(0.0f, 0.0f, 1.0f);
|
|
|
|
btVector3 forwardW (chassisTrans.getBasis()[0][1],
|
|
|
|
chassisTrans.getBasis()[1][1],
|
|
|
|
chassisTrans.getBasis()[2][1]);
|
|
|
|
btVector3 crossProd = targetUp.cross(forwardW);
|
|
|
|
crossProd.normalize();
|
|
|
|
|
|
|
|
const float gLeanRecovery = m_kart_properties->getWheelieLeanRecovery();
|
|
|
|
const float step = m_kart_properties->getWheelieStep();
|
|
|
|
const float balance_recovery= m_kart_properties->getWheelieBalanceRecovery();
|
|
|
|
float alpha = (targetUp.dot(forwardW));
|
|
|
|
float deltaalpha = m_wheelie_angle*M_PI/180.0f - alpha;
|
2007-09-30 14:17:28 +00:00
|
|
|
btVector3 angvel = m_body->getAngularVelocity();
|
2007-05-27 16:01:53 +00:00
|
|
|
float projvel = angvel.dot(crossProd);
|
|
|
|
float deltavel = -projvel * gLeanRecovery / step
|
|
|
|
-deltaalpha * balance_recovery / step;
|
|
|
|
btVector3 deltaangvel = deltavel * crossProd;
|
|
|
|
|
|
|
|
angvel += deltaangvel;
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setAngularVelocity(angvel);
|
2007-12-20 04:37:35 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
return m_kart_properties->getWheeliePowerBoost() * getMaxPower()
|
|
|
|
* m_wheelie_angle/getWheelieMaxPitch();
|
|
|
|
} // handleWheelie
|
|
|
|
|
2008-02-11 02:20:51 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/** This function is called when the race starts. Up to then all brakes are
|
|
|
|
braking (to avoid the kart from rolling downhill), but they need to be set
|
|
|
|
to zero (otherwise the brakes will be braking whenever no engine force
|
|
|
|
is set, i.e. the kart is not accelerating).
|
|
|
|
*/
|
|
|
|
void Kart::resetBrakes()
|
|
|
|
{
|
|
|
|
for(int i=0; i<4; i++) m_vehicle->setBrake(0.0f, i);
|
|
|
|
} // resetBrakes
|
2007-05-27 16:01:53 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void Kart::updatePhysics (float dt)
|
|
|
|
{
|
2007-08-18 14:26:11 +00:00
|
|
|
float engine_power = getActualWheelForce() + handleWheelie(dt);
|
2007-11-03 13:13:26 +00:00
|
|
|
if(m_attachment.getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
|
2007-05-27 16:01:53 +00:00
|
|
|
|
2007-08-17 17:07:12 +00:00
|
|
|
if(m_controls.accel)
|
|
|
|
{ // accelerating
|
|
|
|
m_vehicle->applyEngineForce(engine_power, 2);
|
|
|
|
m_vehicle->applyEngineForce(engine_power, 3);
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
else
|
2007-08-17 17:07:12 +00:00
|
|
|
{ // not accelerating
|
|
|
|
if(m_controls.brake)
|
|
|
|
{ // braking or moving backwards
|
|
|
|
if(m_speed > 0.f)
|
|
|
|
{ // going forward, apply brake force
|
2007-12-20 04:37:35 +00:00
|
|
|
m_vehicle->applyEngineForce(-getBrakeFactor()*engine_power, 2);
|
|
|
|
m_vehicle->applyEngineForce(-getBrakeFactor()*engine_power, 3);
|
2007-08-17 17:07:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // going backward, apply reverse gear ratio
|
|
|
|
if ( fabs(m_speed) < m_max_speed*m_max_speed_reverse_ratio )
|
|
|
|
{
|
2007-11-08 12:31:54 +00:00
|
|
|
m_vehicle->applyEngineForce(-engine_power*m_controls.brake, 2);
|
|
|
|
m_vehicle->applyEngineForce(-engine_power*m_controls.brake, 3);
|
2007-08-17 17:07:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_vehicle->applyEngineForce(0.f, 2);
|
|
|
|
m_vehicle->applyEngineForce(0.f, 3);
|
|
|
|
}
|
|
|
|
}
|
2007-06-15 02:06:26 +00:00
|
|
|
}
|
|
|
|
else
|
2007-08-17 17:07:12 +00:00
|
|
|
{ // lift the foot from throttle, brakes with 10% engine_power
|
|
|
|
m_vehicle->applyEngineForce(-m_controls.accel*engine_power*0.1f, 2);
|
|
|
|
m_vehicle->applyEngineForce(-m_controls.accel*engine_power*0.1f, 3);
|
2007-06-15 02:06:26 +00:00
|
|
|
}
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
2007-09-23 14:52:39 +00:00
|
|
|
|
2007-11-08 12:31:54 +00:00
|
|
|
if(isOnGround() && m_controls.jump)
|
2007-09-23 14:52:39 +00:00
|
|
|
{
|
|
|
|
//Vector3 impulse(0.0f, 0.0f, 10.0f);
|
|
|
|
// getVehicle()->getRigidBody()->applyCentralImpulse(impulse);
|
2007-09-30 14:17:28 +00:00
|
|
|
btVector3 velocity = m_body->getLinearVelocity();
|
2007-11-18 13:44:53 +00:00
|
|
|
velocity.setZ( m_kart_properties->getJumpVelocity() );
|
2007-09-23 14:52:39 +00:00
|
|
|
|
2007-11-03 13:13:26 +00:00
|
|
|
getBody()->setLinearVelocity( velocity );
|
2007-09-23 14:52:39 +00:00
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
2008-03-06 13:32:51 +00:00
|
|
|
const float steering = DEGREE_TO_RAD(getMaxSteerAngle()) * m_controls.lr;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_vehicle->setSteeringValue(steering, 0);
|
|
|
|
m_vehicle->setSteeringValue(steering, 1);
|
|
|
|
|
|
|
|
//store current velocity
|
|
|
|
m_speed = getVehicle()->getRigidBody()->getLinearVelocity().length();
|
|
|
|
|
2007-08-17 17:07:12 +00:00
|
|
|
// calculate direction of m_speed
|
|
|
|
const btTransform& chassisTrans = getVehicle()->getChassisWorldTransform();
|
|
|
|
btVector3 forwardW (
|
|
|
|
chassisTrans.getBasis()[0][1],
|
|
|
|
chassisTrans.getBasis()[1][1],
|
|
|
|
chassisTrans.getBasis()[2][1]);
|
|
|
|
|
|
|
|
if (forwardW.dot(getVehicle()->getRigidBody()->getLinearVelocity()) < btScalar(0.))
|
|
|
|
m_speed *= -1.f;
|
|
|
|
|
2007-05-27 16:01:53 +00:00
|
|
|
//cap at maximum velocity
|
|
|
|
const float max_speed = m_kart_properties->getMaximumSpeed();
|
|
|
|
if ( m_speed > max_speed )
|
|
|
|
{
|
|
|
|
const float velocity_ratio = max_speed/m_speed;
|
|
|
|
m_speed = max_speed;
|
2007-09-30 14:17:28 +00:00
|
|
|
btVector3 velocity = m_body->getLinearVelocity();
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
velocity.setY( velocity.getY() * velocity_ratio );
|
|
|
|
velocity.setX( velocity.getX() * velocity_ratio );
|
|
|
|
|
|
|
|
getVehicle()->getRigidBody()->setLinearVelocity( velocity );
|
|
|
|
|
|
|
|
}
|
|
|
|
//at low velocity, forces on kart push it back and forth so we ignore this
|
2007-08-18 14:26:11 +00:00
|
|
|
if(fabsf(m_speed) < 0.2f) // quick'n'dirty workaround for bug 1776883
|
2007-05-27 16:01:53 +00:00
|
|
|
m_speed = 0;
|
|
|
|
} // updatePhysics
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-02-21 03:40:40 +00:00
|
|
|
void Kart::forceRescue(bool is_shortcut)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
|
|
|
m_rescue=true;
|
|
|
|
// If rescue is triggered while doing a shortcut, reset the kart to the
|
|
|
|
// segment where the shortcut started!! And then reset the shortcut
|
|
|
|
// flag, so that this shortcut is not counted!
|
2008-02-21 03:40:40 +00:00
|
|
|
if(is_shortcut)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
|
|
|
m_track_sector = m_shortcut_sector;
|
|
|
|
}
|
|
|
|
} // forceRescue
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Drops a kart which was rescued back on the track.
|
|
|
|
*/
|
|
|
|
void Kart::endRescue()
|
|
|
|
{
|
|
|
|
if ( m_track_sector > 0 ) m_track_sector-- ;
|
|
|
|
world ->m_track -> trackToSpatial ( m_curr_pos.xyz, m_track_sector ) ;
|
|
|
|
m_curr_pos.hpr[0] = world->m_track->m_angle[m_track_sector] ;
|
|
|
|
m_rescue = false ;
|
2007-12-12 14:07:26 +00:00
|
|
|
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setLinearVelocity (btVector3(0.0f,0.0f,0.0f));
|
|
|
|
m_body->setAngularVelocity(btVector3(0.0f,0.0f,0.0f));
|
2007-05-27 16:01:53 +00:00
|
|
|
// FIXME: This code positions the kart correctly back on the track
|
|
|
|
// (nearest waypoint) - but if the kart is simply upside down,
|
|
|
|
// it feels better if the kart is left where it was. Perhaps
|
|
|
|
// this code should only be used if a rescue was not triggered
|
|
|
|
// by the kart being upside down??
|
2008-01-15 11:38:54 +00:00
|
|
|
btTransform pos;
|
|
|
|
// A certain epsilon is added here to the Z coordinate (0.1), in case
|
|
|
|
// that the drivelines are somewhat under the track. Otherwise, the
|
|
|
|
// kart will be placed a little bit under the track, triggering
|
|
|
|
// a rescue, ...
|
2007-05-27 16:01:53 +00:00
|
|
|
pos.setOrigin(btVector3(m_curr_pos.xyz[0],m_curr_pos.xyz[1],
|
2008-01-15 11:38:54 +00:00
|
|
|
m_curr_pos.xyz[2]+0.5f*m_kart_height+0.1f));
|
2007-12-12 14:07:26 +00:00
|
|
|
pos.setRotation(btQuaternion(btVector3(0.0f, 0.0f, 1.0f),
|
|
|
|
DEGREE_TO_RAD(world->m_track->m_angle[m_track_sector])));
|
2007-09-30 14:17:28 +00:00
|
|
|
m_body->setCenterOfMassTransform(pos);
|
2008-01-15 11:38:54 +00:00
|
|
|
world->getPhysics()->addKart(this, m_vehicle);
|
2007-11-03 13:13:26 +00:00
|
|
|
setTrans(pos);
|
2007-05-27 16:01:53 +00:00
|
|
|
} // endRescue
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::processSkidMarks()
|
|
|
|
{
|
|
|
|
assert(m_skidmark_left);
|
|
|
|
assert(m_skidmark_right);
|
2008-04-16 09:57:50 +00:00
|
|
|
const float threshold=0.3f;
|
|
|
|
bool skid_front = m_vehicle->getWheelInfo(0).m_skidInfo < threshold ||
|
|
|
|
m_vehicle->getWheelInfo(1).m_skidInfo < threshold;
|
|
|
|
bool skid_rear = m_vehicle->getWheelInfo(2).m_skidInfo < threshold ||
|
|
|
|
m_vehicle->getWheelInfo(3).m_skidInfo < threshold;
|
|
|
|
if(skid_rear || skid_front)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2007-11-08 12:31:54 +00:00
|
|
|
if(isOnGround())
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
|
|
|
const float LENGTH = 0.57f;
|
|
|
|
if(m_skidmark_left)
|
|
|
|
{
|
|
|
|
const float ANGLE = -43.0f;
|
|
|
|
|
|
|
|
sgCoord wheelpos;
|
|
|
|
sgCopyCoord(&wheelpos, getCoord());
|
|
|
|
|
|
|
|
wheelpos.xyz[0] += LENGTH * sgSin(wheelpos.hpr[0] + ANGLE);
|
|
|
|
wheelpos.xyz[1] += LENGTH * -sgCos(wheelpos.hpr[0] + ANGLE);
|
|
|
|
|
|
|
|
if(m_skidmark_left->wasSkidMarking())
|
|
|
|
m_skidmark_left->add(&wheelpos);
|
|
|
|
else
|
|
|
|
m_skidmark_left->addBreak(&wheelpos);
|
|
|
|
} // if m_skidmark_left
|
|
|
|
|
|
|
|
if(m_skidmark_right)
|
|
|
|
{
|
|
|
|
const float ANGLE = 43.0f;
|
|
|
|
|
|
|
|
sgCoord wheelpos;
|
|
|
|
sgCopyCoord(&wheelpos, getCoord());
|
|
|
|
|
|
|
|
wheelpos.xyz[0] += LENGTH * sgSin(wheelpos.hpr[0] + ANGLE);
|
|
|
|
wheelpos.xyz[1] += LENGTH * -sgCos(wheelpos.hpr[0] + ANGLE);
|
|
|
|
|
|
|
|
if(m_skidmark_right->wasSkidMarking())
|
|
|
|
m_skidmark_right->add(&wheelpos);
|
|
|
|
else
|
|
|
|
m_skidmark_right->addBreak(&wheelpos);
|
|
|
|
} // if m_skidmark_right
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // not on ground
|
|
|
|
if(m_skidmark_left)
|
|
|
|
{
|
|
|
|
const float LENGTH = 0.57f;
|
|
|
|
const float ANGLE = -43.0f;
|
|
|
|
|
|
|
|
sgCoord wheelpos;
|
|
|
|
sgCopyCoord(&wheelpos, getCoord());
|
|
|
|
|
|
|
|
wheelpos.xyz[0] += LENGTH * sgSin(wheelpos.hpr[0] + ANGLE);
|
|
|
|
wheelpos.xyz[1] += LENGTH * -sgCos(wheelpos.hpr[0] + ANGLE);
|
|
|
|
|
|
|
|
m_skidmark_left->addBreak(&wheelpos);
|
|
|
|
} // if m_skidmark_left
|
|
|
|
|
|
|
|
if(m_skidmark_right)
|
|
|
|
{
|
|
|
|
const float LENGTH = 0.57f;
|
|
|
|
const float ANGLE = 43.0f;
|
|
|
|
|
|
|
|
sgCoord wheelpos;
|
|
|
|
sgCopyCoord(&wheelpos, getCoord());
|
|
|
|
|
|
|
|
wheelpos.xyz[0] += LENGTH * sgSin(wheelpos.hpr[0] + ANGLE);
|
|
|
|
wheelpos.xyz[1] += LENGTH * -sgCos(wheelpos.hpr[0] + ANGLE);
|
|
|
|
|
|
|
|
m_skidmark_right->addBreak(&wheelpos);
|
|
|
|
} // if m_skidmark_right
|
|
|
|
} // on ground
|
|
|
|
}
|
|
|
|
else
|
2008-04-16 09:57:50 +00:00
|
|
|
{ // !skid_rear && _skid_front
|
2007-05-27 16:01:53 +00:00
|
|
|
if(m_skidmark_left)
|
|
|
|
if(m_skidmark_left->wasSkidMarking())
|
|
|
|
{
|
|
|
|
const float ANGLE = -43.0f;
|
|
|
|
const float LENGTH = 0.57f;
|
|
|
|
|
|
|
|
sgCoord wheelpos;
|
|
|
|
sgCopyCoord(&wheelpos, getCoord());
|
|
|
|
|
|
|
|
wheelpos.xyz[0] += LENGTH * sgSin(wheelpos.hpr[0] + ANGLE);
|
|
|
|
wheelpos.xyz[1] += LENGTH * -sgCos(wheelpos.hpr[0] + ANGLE);
|
|
|
|
|
|
|
|
m_skidmark_left->addBreak(&wheelpos);
|
|
|
|
} // m_skidmark_left->wasSkidMarking
|
|
|
|
|
|
|
|
if(m_skidmark_right)
|
|
|
|
if(m_skidmark_right->wasSkidMarking())
|
|
|
|
{
|
|
|
|
const float ANGLE = 43.0f;
|
|
|
|
const float LENGTH = 0.57f;
|
|
|
|
|
|
|
|
sgCoord wheelpos;
|
|
|
|
sgCopyCoord(&wheelpos, getCoord());
|
|
|
|
|
|
|
|
wheelpos.xyz[0] += LENGTH * sgSin(wheelpos.hpr[0] + ANGLE);
|
|
|
|
wheelpos.xyz[1] += LENGTH * -sgCos(wheelpos.hpr[0] + ANGLE);
|
|
|
|
|
|
|
|
m_skidmark_right->addBreak(&wheelpos);
|
|
|
|
} // m_skidmark_right->wasSkidMarking
|
|
|
|
} // m_velocity < 20
|
|
|
|
} // processSkidMarks
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::load_wheels(ssgBranch* branch)
|
|
|
|
{
|
|
|
|
if (!branch) return;
|
|
|
|
|
|
|
|
for(ssgEntity* i = branch->getKid(0); i != NULL; i = branch->getNextKid())
|
|
|
|
{
|
|
|
|
if (i->getName())
|
|
|
|
{ // We found something that might be a wheel
|
|
|
|
if (strcmp(i->getName(), "WheelFront.L") == 0)
|
|
|
|
{
|
|
|
|
m_wheel_front_l = add_transform(dynamic_cast<ssgTransform*>(i));
|
|
|
|
}
|
|
|
|
else if (strcmp(i->getName(), "WheelFront.R") == 0)
|
|
|
|
{
|
|
|
|
m_wheel_front_r = add_transform(dynamic_cast<ssgTransform*>(i));
|
|
|
|
}
|
|
|
|
else if (strcmp(i->getName(), "WheelRear.L") == 0)
|
|
|
|
{
|
|
|
|
m_wheel_rear_l = add_transform(dynamic_cast<ssgTransform*>(i));
|
|
|
|
}
|
|
|
|
else if (strcmp(i->getName(), "WheelRear.R") == 0)
|
|
|
|
{
|
|
|
|
m_wheel_rear_r = add_transform(dynamic_cast<ssgTransform*>(i));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Wasn't a wheel, continue searching
|
|
|
|
load_wheels(dynamic_cast<ssgBranch*>(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Can't be a wheel,continue searching
|
|
|
|
load_wheels(dynamic_cast<ssgBranch*>(i));
|
|
|
|
}
|
|
|
|
} // for i
|
|
|
|
} // load_wheels
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::loadData()
|
|
|
|
{
|
|
|
|
float r [ 2 ] = { -10.0f, 100.0f } ;
|
|
|
|
|
|
|
|
m_smokepuff = new ssgSimpleState ();
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
m_smokepuff -> setTexture (loader->createTexture("smoke.rgb", true, true, true)) ;
|
2007-05-27 16:01:53 +00:00
|
|
|
m_smokepuff -> setTranslucent () ;
|
|
|
|
m_smokepuff -> enable ( GL_TEXTURE_2D ) ;
|
|
|
|
m_smokepuff -> setShadeModel ( GL_SMOOTH ) ;
|
|
|
|
m_smokepuff -> enable ( GL_CULL_FACE ) ;
|
|
|
|
m_smokepuff -> enable ( GL_BLEND ) ;
|
|
|
|
m_smokepuff -> enable ( GL_LIGHTING ) ;
|
|
|
|
m_smokepuff -> setColourMaterial ( GL_EMISSION ) ;
|
|
|
|
m_smokepuff -> setMaterial ( GL_AMBIENT, 0, 0, 0, 1 ) ;
|
|
|
|
m_smokepuff -> setMaterial ( GL_DIFFUSE, 0, 0, 0, 1 ) ;
|
|
|
|
m_smokepuff -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ;
|
|
|
|
m_smokepuff -> setShininess ( 0 ) ;
|
|
|
|
|
|
|
|
ssgEntity *obj = m_kart_properties->getModel();
|
|
|
|
createPhysics(obj);
|
|
|
|
|
|
|
|
load_wheels(dynamic_cast<ssgBranch*>(obj));
|
|
|
|
|
|
|
|
// Optimize the model, this can't be done while loading the model
|
|
|
|
// because it seems that it removes the name of the wheels or something
|
|
|
|
// else needed to load the wheels as a separate object.
|
|
|
|
ssgFlatten(obj);
|
|
|
|
|
|
|
|
createDisplayLists(obj); // create all display lists
|
|
|
|
ssgRangeSelector *lod = new ssgRangeSelector ;
|
|
|
|
|
|
|
|
lod -> addKid ( obj ) ;
|
|
|
|
lod -> setRanges ( r, 2 ) ;
|
|
|
|
|
2007-12-08 13:04:56 +00:00
|
|
|
this-> getModelTransform() -> addKid ( lod ) ;
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
// Attach Particle System
|
|
|
|
//JH sgCoord pipe_pos = {{0, 0, .3}, {0, 0, 0}} ;
|
2008-04-15 13:57:18 +00:00
|
|
|
m_smoke_system = new Smoke(this, 50, 100.0f, true, 0.35f, 1000);
|
2007-05-27 16:01:53 +00:00
|
|
|
m_smoke_system -> init(5);
|
|
|
|
//JH m_smoke_system -> setState (getMaterial ("smoke.png")-> getState() );
|
|
|
|
//m_smoke_system -> setState ( m_smokepuff ) ;
|
|
|
|
// m_exhaust_pipe = new ssgTransform (&pipe_pos);
|
|
|
|
// m_exhaust_pipe -> addKid (m_smoke_system) ;
|
|
|
|
// comp_model-> addKid (m_exhaust_pipe) ;
|
|
|
|
|
|
|
|
m_skidmark_left = new SkidMark();
|
|
|
|
m_skidmark_right = new SkidMark();
|
|
|
|
|
|
|
|
m_shadow = createShadow(m_kart_properties->getShadowFile(), -1, 1, -1, 1);
|
|
|
|
m_shadow->ref();
|
2007-12-08 13:04:56 +00:00
|
|
|
m_model_transform->addKid ( m_shadow );
|
2007-05-27 16:01:53 +00:00
|
|
|
} // loadData
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::placeModel ()
|
|
|
|
{
|
|
|
|
sgMat4 wheel_front;
|
|
|
|
sgMat4 wheel_steer;
|
|
|
|
sgMat4 wheel_rot;
|
|
|
|
|
2008-01-25 01:29:12 +00:00
|
|
|
sgMakeRotMat4( wheel_rot, 0, RAD_TO_DEGREE(-m_wheel_rotation), 0);
|
2008-03-06 13:32:51 +00:00
|
|
|
sgMakeRotMat4( wheel_steer, m_controls.lr * 30.0f , 0, 0);
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
sgMultMat4(wheel_front, wheel_steer, wheel_rot);
|
|
|
|
|
|
|
|
if (m_wheel_front_l) m_wheel_front_l->setTransform(wheel_front);
|
|
|
|
if (m_wheel_front_r) m_wheel_front_r->setTransform(wheel_front);
|
|
|
|
|
|
|
|
if (m_wheel_rear_l) m_wheel_rear_l->setTransform(wheel_rot);
|
|
|
|
if (m_wheel_rear_r) m_wheel_rear_r->setTransform(wheel_rot);
|
|
|
|
// We don't have to call Moveable::placeModel, since it does only setTransform
|
|
|
|
|
2007-09-10 00:36:50 +00:00
|
|
|
// Only transfer the bullet data to the plib tree if no history is being
|
|
|
|
// replayed.
|
|
|
|
if(!user_config->m_replay_history)
|
2007-05-27 16:01:53 +00:00
|
|
|
{
|
2007-09-10 00:36:50 +00:00
|
|
|
float m[4][4];
|
2007-12-20 04:37:35 +00:00
|
|
|
getTrans().getOpenGLMatrix((float*)&m);
|
2007-09-10 00:36:50 +00:00
|
|
|
|
|
|
|
//printf(" is %f %f %f\n",t.getOrigin().x(),t.getOrigin().y(),t.getOrigin().z());
|
|
|
|
// Transfer the new position and hpr to m_curr_pos
|
|
|
|
sgSetCoord(&m_curr_pos, m);
|
2007-05-27 16:01:53 +00:00
|
|
|
}
|
|
|
|
sgCoord c ;
|
|
|
|
sgCopyCoord ( &c, &m_curr_pos ) ;
|
|
|
|
// c.hpr[1] += m_wheelie_angle ;
|
|
|
|
// c.xyz[2] += 0.3f*fabs(sin(m_wheelie_angle*SG_DEGREES_TO_RADIANS));
|
2007-08-03 08:17:56 +00:00
|
|
|
const float CENTER_SHIFT = getGravityCenterShift();
|
2007-11-03 13:13:26 +00:00
|
|
|
c.xyz[2] -= (0.5f-CENTER_SHIFT)*m_kart_height; // adjust for center of gravity
|
2007-12-08 13:04:56 +00:00
|
|
|
m_model_transform->setTransform(&c);
|
2007-12-20 04:37:35 +00:00
|
|
|
Moveable::placeModel();
|
2007-05-27 16:01:53 +00:00
|
|
|
|
|
|
|
} // placeModel
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Kart::setFinishingState(float time)
|
|
|
|
{
|
|
|
|
m_finished_race = true;
|
|
|
|
m_finish_time = time;
|
2008-02-08 04:43:35 +00:00
|
|
|
} // setFinishingState
|
2007-05-27 16:01:53 +00:00
|
|
|
|
2008-02-08 04:43:35 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float Kart::estimateFinishTime ()
|
|
|
|
{
|
|
|
|
// Estimate the arrival time of any karts that haven't arrived
|
|
|
|
// yet by using their average speed up to now and the distance
|
|
|
|
// still to race. This approach guarantees that the order of
|
|
|
|
// the karts won't change anymore (karts ahead will have a
|
|
|
|
// higher average speed and therefore finish the race earlier
|
|
|
|
// than karts further behind), so the position doesn't have to
|
|
|
|
// be updated to get the correct scoring.
|
|
|
|
float distance_covered = getLap()*world->m_track->getTrackLength()
|
|
|
|
+ getDistanceDownTrack();
|
|
|
|
// In case that a kart is rescued behind start line, or ...
|
|
|
|
if(distance_covered<0) distance_covered =1.0f;
|
|
|
|
|
|
|
|
float average_speed = distance_covered/world->getTime();
|
|
|
|
|
|
|
|
// Finish time is the time needed for the whole race with
|
|
|
|
// the average speed computed above.
|
1) Removed race_setup and race_mode data structures. All this
information is now only managed by the race_manager, no
more in-between objects to transfer information along.
2) The scores for grand prix are now defined in the stk_config.dat
file (10, 8, 6, 5, 4, .., 1, 0, 0) points
3) Bugfix: unlock information wasn't saved anymore. Added specific
saving after unlocking, plus re-inserted the 'generic' save
at the end of STK again.
4) bugfix/work around: Visual Studio complains about incompatible
iterators in sdldrv - apparently caused by using erase, and
then keep on using the iterator.
5) Fixed bug when running a race in a GP again (scores/times
were added each time).
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1681 178a84e3-b1eb-0310-8ba1-8eac791a3b58
2008-04-09 13:52:48 +00:00
|
|
|
return race_manager->getNumLaps()*world->getTrack()->getTrackLength()
|
2008-02-08 04:43:35 +00:00
|
|
|
/ average_speed;
|
|
|
|
|
|
|
|
} // estimateFinishTime
|
2007-05-27 16:01:53 +00:00
|
|
|
/* EOF */
|