48
47
#include "physics/btKart.hpp"
49
48
#include "physics/btUprightConstraint.hpp"
50
49
#include "physics/physics.hpp"
50
#include "race/history.hpp"
51
51
#include "tracks/track.hpp"
52
52
#include "utils/constants.hpp"
53
#include "utils/coord.hpp"
54
#include "utils/ssg_help.hpp"
55
#include "audio/sfx_manager.hpp"
57
54
#if defined(WIN32) && !defined(__CYGWIN__)
58
55
// Disable warning for using 'this' in base member initializer list
59
56
# pragma warning(disable:4355)
62
Kart::Kart (const std::string& kart_name, int position,
63
const btTransform& init_transform)
59
/** The kart constructor.
60
* \param ident The identifier for the kart model to use.
61
* \param position The position (or rank) for this kart (between 1 and
62
* number of karts). This is used to determine the start position.
63
* \param init_transform The initial position and rotation for this kart.
65
Kart::Kart (const std::string& ident, int position,
66
const btTransform& init_transform)
65
Moveable(), m_attachment(this), m_powerup(this)
68
Moveable(), EmergencyAnimation(this), MaxSpeed(this), m_powerup(this)
67
70
#if defined(WIN32) && !defined(__CYGWIN__)
68
71
# pragma warning(1:4355)
71
m_kart_properties = kart_properties_manager->getKart(kart_name);
74
m_kart_properties = kart_properties_manager->getKart(ident);
75
assert(m_kart_properties != NULL);
76
// We have to take a copy of the kart model, since otherwise
77
// the animations will be mixed up (i.e. different instances of
78
// the same model will set different animation frames).
79
// Technically the mesh in m_kart_model needs to be grab'ed and
80
// released when the kart is deleted, but since the original
81
// kart_model is stored in the kart_properties all the time,
82
// there is no risk of a mesh being deleted to early.
83
m_kart_model = m_kart_properties->getKartModelCopy();
72
84
m_initial_position = position;
85
m_race_position = position;
73
86
m_collected_energy = 0;
75
87
m_finished_race = false;
76
88
m_finish_time = 0.0f;
77
89
m_shadow_enabled = false;
79
91
m_smoke_system = NULL;
92
m_water_splash_system = NULL;
81
95
m_skidmarks = NULL;
98
m_saved_controller = NULL;
83
101
m_view_blocked_by_plunger = 0;
103
// Initialize custom sound vector (TODO: add back when properly done)
104
// m_custom_sounds.resize(SFXManager::NUM_CUSTOMS);
85
106
// Set position and heading:
86
m_reset_transform = init_transform;
88
// Neglecting the roll resistance (which is small for high speeds compared
89
// to the air resistance), maximum speed is reached when the engine
90
// power equals the air resistance force, resulting in this formula:
91
m_max_speed = m_kart_properties->getMaxSpeed();
92
m_max_speed_reverse_ratio = m_kart_properties->getMaxSpeedReverseRatio();
107
m_reset_transform = init_transform;
95
// Setting rescue to false is important! If rescue is set when reset() is
96
// called, it is assumed that this was triggered by a restart, and that
97
// the vehicle must be added back to the physics world. Since reset() is
98
// also called at the very start, it must be guaranteed that rescue is
101
109
m_wheel_rotation = 0;
103
m_engine_sound = sfx_manager->newSFX(m_kart_properties->getEngineSfxType());
104
m_beep_sound = sfx_manager->newSFX( SFXManager::SOUND_BEEP );
105
m_crash_sound = sfx_manager->newSFX( SFXManager::SOUND_CRASH );
106
m_skid_sound = sfx_manager->newSFX( SFXManager::SOUND_SKID );
107
m_goo_sound = sfx_manager->newSFX( SFXManager::SOUND_GOO );
111
// Create SFXBase for each custom sound (TODO: add back when properly done)
113
for (int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
115
int id = m_kart_properties->getCustomSfxId((SFXManager::CustomSFX)n);
117
// If id == -1 the custom sound was not defined in the .irrkart config file
120
m_custom_sounds[n] = sfx_manager->newSFX(id);
124
m_engine_sound = sfx_manager->createSoundSource(m_kart_properties->getEngineSfxType());
125
m_beep_sound = sfx_manager->createSoundSource( "beep" );
126
m_crash_sound = sfx_manager->createSoundSource( "crash" );
127
m_goo_sound = sfx_manager->createSoundSource( "goo" );
128
m_skid_sound = sfx_manager->createSoundSource( "skid" );
129
m_terrain_sound = NULL;
130
m_previous_terrain_sound = NULL;
109
132
if(!m_engine_sound)
111
134
fprintf(stdout, "Error: Could not allocate a sfx object for the kart. Further errors may ensue!\n");
118
142
// -----------------------------------------------------------------------------
120
btTransform Kart::getKartHeading(const float customPitch)
122
btTransform trans = this->getTrans();
124
// get heading=trans.getBasis*(0,1,0) ... so save the multiplication:
125
btVector3 direction(trans.getBasis()[0][1],
126
trans.getBasis()[1][1],
127
trans.getBasis()[2][1]);
128
float heading=atan2(-direction.getX(), direction.getY());
130
TerrainInfo::update(this->getXYZ());
131
float pitch = (customPitch == -1 ? getTerrainPitch(heading) : customPitch);
143
/** Saves the old controller in m_saved_controller and stores a new
144
* controller. The save controller is needed in case of a reset.
145
* \param controller The new controller to use (atm it's always an
148
void Kart::setController(Controller *controller)
150
assert(m_saved_controller==NULL);
151
m_saved_controller = m_controller;
152
m_controller = controller;
155
// -----------------------------------------------------------------------------
156
/** Returns a transform that will align an object with the kart: the heading
157
* and the pitch will be set appropriately. A custom pitch value can be
158
* specified in order to overwrite the terrain pitch (which would be used
160
* \param customPitch Pitch value to overwrite the terrain pitch.
162
btTransform Kart::getKartTransform(const float customPitch)
164
btTransform trans = getTrans();
166
float pitch = (customPitch == -1 ? getTerrainPitch(getHeading()) : customPitch);
134
m.setEulerZYX(pitch, 0.0f, heading);
169
m.setEulerYPR(-getHeading(), pitch, 0.0f);
135
170
trans.setBasis(m);
173
} // getKartTransform
140
175
// ----------------------------------------------------------------------------
176
/** Creates the physical representation of this kart. Atm it uses the actual
177
* extention of the kart model to determine the size of the collision body.
141
179
void Kart::createPhysics()
143
181
// First: Create the chassis of the kart
144
182
// -------------------------------------
145
const KartModel *km = m_kart_properties->getKartModel();
146
float kart_width = km->getWidth();
147
float kart_length = km->getLength();
148
float kart_height = km->getHeight();
183
float kart_width = getKartWidth();
184
float kart_length = getKartLength();
185
float kart_height = getKartHeight();
150
187
btBoxShape *shape = new btBoxShape(btVector3(0.5f*kart_width,
153
190
btTransform shiftCenterOfGravity;
154
191
shiftCenterOfGravity.setIdentity();
155
// Shift center of gravity downwards, so that the kart
156
// won't topple over too easy.
157
shiftCenterOfGravity.setOrigin(getGravityCenterShift());
192
// Shift center of gravity downwards, so that the kart
193
// won't topple over too easy.
194
shiftCenterOfGravity.setOrigin(m_kart_properties->getGravityCenterShift());
158
195
m_kart_chassis.addChildShape(shiftCenterOfGravity, shape);
160
197
// Set mass and inertia
178
215
// Create the actual vehicle
179
216
// -------------------------
180
m_vehicle_raycaster =
181
new btDefaultVehicleRaycaster(RaceManager::getWorld()->getPhysics()->getPhysicsWorld());
217
m_vehicle_raycaster =
218
new btDefaultVehicleRaycaster(World::getWorld()->getPhysics()->getPhysicsWorld());
182
219
m_tuning = new btKart::btVehicleTuning();
183
m_tuning->m_maxSuspensionTravelCm = m_kart_properties->getSuspensionTravelCM();
220
m_tuning->m_maxSuspensionTravelCm = m_kart_properties->getSuspensionTravelCM();
184
221
m_vehicle = new btKart(*m_tuning, m_body, m_vehicle_raycaster,
185
222
m_kart_properties->getTrackConnectionAccel());
187
224
// never deactivate the vehicle
188
225
m_body->setActivationState(DISABLE_DEACTIVATION);
189
m_vehicle->setCoordinateSystem(/*right: */ 0, /*up: */ 2, /*forward: */ 1);
226
m_vehicle->setCoordinateSystem(/*right: */ 0, /*up: */ 1, /*forward: */ 2);
193
230
float wheel_radius = m_kart_properties->getWheelRadius();
194
231
float suspension_rest = m_kart_properties->getSuspensionRest();
196
btVector3 wheel_direction(0.0f, 0.0f, -1.0f);
197
btVector3 wheel_axle(1.0f,0.0f,0.0f);
233
btVector3 wheel_direction(0.0f, -1.0f, 0.0f);
234
btVector3 wheel_axle(-1.0f, 0.0f, 0.0f);
199
236
for(unsigned int i=0; i<4; i++)
201
238
bool is_front_wheel = i<2;
202
239
btWheelInfo& wheel = m_vehicle->addWheel(
203
m_kart_properties->getKartModel()->getWheelPhysicsPosition(i),
240
m_kart_model->getWheelPhysicsPosition(i),
204
241
wheel_direction, wheel_axle, suspension_rest,
205
242
wheel_radius, *m_tuning, is_front_wheel);
206
243
wheel.m_suspensionStiffness = m_kart_properties->getSuspensionStiffness();
212
249
// Obviously these allocs have to be properly managed/freed
215
m_uprightConstraint=new btUprightConstraint(*m_body, t);
252
m_uprightConstraint=new btUprightConstraint(this, t);
216
253
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
217
254
m_uprightConstraint->setBounce(0.0f);
218
255
m_uprightConstraint->setMaxLimitForce(m_kart_properties->getUprightMaxForce());
219
256
m_uprightConstraint->setErp(1.0f);
220
257
m_uprightConstraint->setLimitSoftness(1.0f);
221
258
m_uprightConstraint->setDamping(0.0f);
222
RaceManager::getWorld()->getPhysics()->addKart(this);
224
//create the engine sound
259
World::getWorld()->getPhysics()->addKart(this);
263
// ----------------------------------------------------------------------------
284
// ----------------------------------------------------------------------------
285
/** Starts the engine sound effect. Called once the track intro phase is over.
287
void Kart::startEngineSFX()
225
289
if(m_engine_sound)
227
291
m_engine_sound->speed(0.6f);
228
m_engine_sound->loop();
292
m_engine_sound->setLoop(true);
229
293
m_engine_sound->play();
233
// -----------------------------------------------------------------------------
297
// ----------------------------------------------------------------------------
298
/** The destructor frees the memory of this kart, but note that the actual kart
299
* model is still stored in the kart_properties (m_kart_model variable), so
300
* it is not reloaded).
236
//stop the engine sound
304
// Delete all custom sounds (TODO: add back when properly done)
306
for (int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
239
m_engine_sound->stop();
308
if (m_custom_sounds[n] != NULL)
309
sfx_manager->deleteSFX(m_custom_sounds[n]);
241
312
sfx_manager->deleteSFX(m_engine_sound );
242
sfx_manager->deleteSFX(m_beep_sound );
243
313
sfx_manager->deleteSFX(m_crash_sound );
244
314
sfx_manager->deleteSFX(m_skid_sound );
245
315
sfx_manager->deleteSFX(m_goo_sound );
247
if(m_smoke_system) ssgDeRefDelete(m_smoke_system);
248
if(m_nitro) ssgDeRefDelete(m_nitro);
316
sfx_manager->deleteSFX(m_beep_sound );
317
if(m_terrain_sound) sfx_manager->deleteSFX(m_terrain_sound);
318
if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound);
319
if(m_smoke_system) delete m_smoke_system;
320
if(m_water_splash_system) delete m_water_splash_system;
321
if(m_nitro) delete m_nitro;
322
if(m_slipstream) delete m_slipstream;
250
ssgDeRefDelete(m_shadow);
252
326
if(m_skidmarks) delete m_skidmarks ;
254
RaceManager::getWorld()->getPhysics()->removeKart(this);
328
World::getWorld()->getPhysics()->removeKart(this);
255
329
delete m_vehicle;
257
331
delete m_vehicle_raycaster;
360
479
TerrainInfo::update(getXYZ());
481
// Reset is also called when the kart is created, at which time
482
// m_controller is not yet defined, so this has to be tested here.
484
m_controller->reset();
363
488
//-----------------------------------------------------------------------------
364
void Kart::raceFinished(float time)
489
/** Sets that this kart has finished the race and finishing time. It also
490
* notifies the race_manager about the race completion for this kart.
491
* \param time The finishing time for this kart. It can either be the
492
* actual time when the kart finished (in which case time() =
493
* world->getTime()), or the estimated time in case that all
494
* player kart have finished the race and all AI karts get
495
* an estimated finish time set.
497
void Kart::finishedRace(float time)
499
// m_finished_race can be true if e.g. an AI kart was set to finish
500
// because the race was over (i.e. estimating the finish time). If
501
// this kart then crosses the finish line (with the end controller)
502
// it would trigger a race end again.
503
if(m_finished_race) return;
366
504
m_finished_race = true;
367
505
m_finish_time = time;
368
race_manager->RaceFinished(this, time);
506
m_controller->finishedRace(time);
507
race_manager->kartFinishedRace(this, time);
509
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_NORMAL_RACE ||
510
race_manager->getMinorMode() == RaceManager::MINOR_MODE_TIME_TRIAL)
512
// in modes that support it, start end animation
513
setController(new EndController(this, m_controller->getPlayer()));
514
if(m_race_position<=0.5f*race_manager->getNumberOfKarts() ||
516
m_kart_model->setAnimation(KartModel::AF_WIN_START);
518
m_kart_model->setAnimation(KartModel::AF_LOSE_START);
520
// Not all karts have a camera
521
if (m_camera) m_camera->setMode(Camera::CM_FINAL);
523
RaceGUIBase* m = World::getWorld()->getRaceGUI();
526
m->addMessage((getPosition() == 1 ? _("You won the race!") : _("You finished the race!")) ,
530
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER)
532
// start end animation
533
setController(new EndController(this, m_controller->getPlayer()));
534
if(m_race_position<=2)
535
m_kart_model->setAnimation(KartModel::AF_WIN_START);
536
else if(m_race_position>=0.7f*race_manager->getNumberOfKarts())
537
m_kart_model->setAnimation(KartModel::AF_LOSE_START);
539
// Not all karts have a camera
540
if (m_camera) m_camera->setMode(Camera::CM_REVERSE);
542
RaceGUIBase* m = World::getWorld()->getRaceGUI();
545
m->addMessage((getPosition() == 2 ? _("You won the race!") : _("You finished the race!")) ,
549
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_3_STRIKES)
551
setController(new EndController(this, m_controller->getPlayer()));
371
556
//-----------------------------------------------------------------------------
372
void Kart::collectedItem(const Item &item, int add_info)
557
/** Called when an item is collected. It will either adjust the collected
558
* energy, or update the attachment or powerup for this kart.
559
* \param item The item that was hit.
560
* \param add_info Additional info, used in networking games to force
561
* a specific item to be used (instead of a random item) to keep
562
* all karts in synch.
564
void Kart::collectedItem(Item *item, int add_info)
374
const ItemType type = item.getType();
566
float old_energy = m_collected_energy;
567
const Item::ItemType type = item->getType();
378
case ITEM_BANANA : m_attachment.hitBanana(item, add_info); break;
379
case ITEM_SILVER_COIN : m_collected_energy++ ; break;
380
case ITEM_GOLD_COIN : m_collected_energy += 3 ; break;
381
case ITEM_BONUS_BOX :
383
// In wheelie style, karts get more items depending on energy,
384
// in nitro mode it's only one item.
386
m_powerup.hitBonusBox(n, item,add_info);
571
case Item::ITEM_BANANA:
572
m_attachment->hitBanana(item, add_info);
574
case Item::ITEM_NITRO_SMALL:
575
m_collected_energy += m_kart_properties->getNitroSmallContainer();
577
case Item::ITEM_NITRO_BIG:
578
m_collected_energy += m_kart_properties->getNitroBigContainer();
580
case Item::ITEM_BONUS_BOX :
582
m_powerup.hitBonusBox(*item, add_info);
585
case Item::ITEM_BUBBLEGUM:
391
587
m_body->setLinearVelocity(m_body->getLinearVelocity()*0.3f);
392
588
m_goo_sound->position(getXYZ());
393
589
m_goo_sound->play();
590
// Play appropriate custom character sound
591
playCustomSFX(SFXManager::CUSTOM_GOO);
399
597
// functions (hit{Red,Green}Item), so only coins need to be
401
599
if(network_manager->getMode()==NetworkManager::NW_SERVER &&
402
(type==ITEM_SILVER_COIN || type==ITEM_GOLD_COIN) )
600
(type==Item::ITEM_NITRO_BIG || type==Item::ITEM_NITRO_SMALL) )
404
race_state->itemCollected(getWorldKartId(), item.getItemId());
602
race_state->itemCollected(getWorldKartId(), item->getItemId());
407
605
if ( m_collected_energy > MAX_ITEMS_COLLECTED )
408
606
m_collected_energy = MAX_ITEMS_COLLECTED;
607
m_controller->collectedItem(*item, add_info, old_energy);
410
609
} // collectedItem
412
611
//-----------------------------------------------------------------------------
612
/** Simulates gears by adjusting the force of the engine. It also takes the
613
* effect of the zipper into account.
414
615
float Kart::getActualWheelForce()
416
float zipperF=(m_zipper_time_left>0.0f) ? stk_config->m_zipper_force : 0.0f;
617
float time_left = MaxSpeed::getSpeedIncreaseTimeLeft(MS_INCREASE_ZIPPER);
618
float zipper_force = time_left>0.0f ? m_kart_properties->getZipperForce(): 0.0f;
417
619
const std::vector<float>& gear_ratio=m_kart_properties->getGearSwitchRatio();
418
620
for(unsigned int i=0; i<gear_ratio.size(); i++)
420
if(m_speed <= getMaxSpeed()*gear_ratio[i])
622
if(m_speed <= m_kart_properties->getMaxSpeed()*gear_ratio[i])
422
m_current_gear_ratio = gear_ratio[i];
423
return getMaxPower()*m_kart_properties->getGearPowerIncrease()[i]+zipperF;
624
return getMaxPower()*m_kart_properties->getGearPowerIncrease()[i]
426
return getMaxPower()+zipperF;
628
return getMaxPower()+zipper_force;
428
630
} // getActualWheelForce
430
632
//-----------------------------------------------------------------------------
431
/** The kart is on ground if all 4 wheels touch the ground
633
/** The kart is on ground if all 4 wheels touch the ground, and if no special
634
* animation (rescue, explosion etc.) is happening).
433
636
bool Kart::isOnGround() const
435
return m_vehicle->getWheelInfo(0).m_raycastInfo.m_isInContact &&
436
m_vehicle->getWheelInfo(1).m_raycastInfo.m_isInContact &&
437
m_vehicle->getWheelInfo(2).m_raycastInfo.m_isInContact &&
438
m_vehicle->getWheelInfo(3).m_raycastInfo.m_isInContact;
638
return (m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels()
639
&& !playingEmergencyAnimation());
440
642
//-----------------------------------------------------------------------------
441
643
/** The kart is near the ground, but not necesarily on it (small jumps). This
442
644
* is used to determine when to switch off the upright constraint, so that
443
* explosions can be more violent, while still
645
* explosions can be more violent, while still
446
647
bool Kart::isNearGround() const
448
649
if(getHoT()==Track::NOHIT)
451
return ((getXYZ().getZ() - getHoT()) < stk_config->m_near_ground);
652
return ((getXYZ().getY() - getHoT()) < stk_config->m_near_ground);
452
653
} // isNearGround
453
//-----------------------------------------------------------------------------
454
void Kart::handleExplosion(const Vec3& pos, bool direct_hit)
458
btVector3 diff((float)(rand()%16/16), (float)(rand()%16/16), 2.0f);
460
diff*=stk_config->m_explosion_impulse/5.0f;
461
m_uprightConstraint->setDisableTime(10.0f);
462
getVehicle()->getRigidBody()->applyCentralImpulse(diff);
463
getVehicle()->getRigidBody()->applyTorqueImpulse(btVector3(float(rand()%32*5),
465
float(rand()%32*5)));
467
else // only affected by a distant explosion
469
btVector3 diff=getXYZ()-pos;
470
//if the z component is negative, the resulting impulse could push the
471
// kart through the floor. So in this case ignore z.
472
if(diff.getZ()<0) diff.setZ(0.0f);
473
float len2=diff.length2();
475
// The correct formhale would be to first normalise diff,
476
// then apply the impulse (which decreases 1/r^2 depending
477
// on the distance r), so:
478
// diff/len(diff) * impulseSize/len(diff)^2
479
// = diff*impulseSize/len(diff)^3
480
// We use diff*impulseSize/len(diff)^2 here, this makes the impulse
481
// somewhat larger, which is actually more fun :)
482
diff *= stk_config->m_explosion_impulse/len2;
483
getVehicle()->getRigidBody()->applyCentralImpulse(diff);
487
//-----------------------------------------------------------------------------
655
//-----------------------------------------------------------------------------
656
/** Updates the kart in each time step. It updates the physics setting,
657
* particle effects, camera position, etc.
658
* \param dt Time step size.
488
660
void Kart::update(float dt)
490
if(m_body->getAngularVelocity().getZ()>1.9f)
662
// Update the position and other data taken from the physics
663
Moveable::update(dt);
665
if(!history->replayHistory())
666
m_controller->update(dt);
668
m_camera->update(dt);
492
669
// if its view is blocked by plunger, decrease remaining time
493
670
if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= dt;
672
m_slipstream->update(dt);
495
674
// Store the actual kart controls at the start of update in the server
496
// state. This makes it easier to reset some fields when they are not used
675
// state. This makes it easier to reset some fields when they are not used
497
676
// anymore (e.g. controls.fire).
498
677
if(network_manager->getMode()==NetworkManager::NW_SERVER)
510
689
m_controls.m_fire = false;
513
// When really on air, free fly, when near ground, try to glide / adjust for landing
515
m_uprightConstraint->setLimit(M_PI);
517
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
520
m_zipper_time_left = m_zipper_time_left>0.0f ? m_zipper_time_left-dt : 0.0f;
694
// When really on air, free fly, when near ground, try to glide / adjust for landing
695
// If zipped, be stable, so ramp+zipper can allow nice jumps without scripting the fly
696
if(!isNearGround() &&
697
MaxSpeed::getSpeedIncreaseTimeLeft(MS_INCREASE_ZIPPER)<=0.0f )
698
m_uprightConstraint->setLimit(M_PI);
700
m_uprightConstraint->setLimit(m_kart_properties->getUprightTolerance());
704
// TODO: hiker said this probably will be moved to btKart or so when updating bullet engine.
705
// Neutralize any yaw change if the kart leaves the ground, so the kart falls more or less
706
// straight after jumping, but still allowing some "boat shake" (roll and pitch).
707
// Otherwise many non perfect jumps end in a total roll over or a serious change of
708
// direction, sometimes 90 or even full U turn (real but less fun for a karting game).
709
// As side effect steering becames a bit less responsive (any wheel on air), but not too bad.
711
btVector3 speed = m_body->getAngularVelocity();
712
speed.setX(speed.getX() * 0.95f);
713
speed.setY(speed.getY() * 0.25f); // or 0.0f for sharp neutralization of yaw
714
speed.setZ(speed.getZ() * 0.95f);
715
m_body->setAngularVelocity(speed);
716
// This one keeps the kart pointing "100% as launched" instead,
717
// like in ski jump sports, too boring but also works.
718
//m_body->setAngularVelocity(btVector3(0,0,0));
522
721
//m_wheel_rotation gives the rotation around the X-axis, and since velocity's
523
722
//timeframe is the delta time, we don't have to multiply it with dt.
524
723
m_wheel_rotation += m_speed*dt / m_kart_properties->getWheelRadius();
525
724
m_wheel_rotation=fmodf(m_wheel_rotation, 2*M_PI);
529
// Let the kart raise 2m in the 2 seconds of the rescue
530
const float rescue_time = 2.0f;
531
const float rescue_height = 2.0f;
532
if(m_attachment.getType() != ATTACH_TINYTUX)
534
m_attachment.set( ATTACH_TINYTUX, rescue_time ) ;
535
m_rescue_pitch = getHPR().getPitch();
536
m_rescue_roll = getHPR().getRoll();
537
RaceManager::getWorld()->getPhysics()->removeKart(this);
538
race_state->itemCollected(getWorldKartId(), -1, -1);
540
btQuaternion q_roll (btVector3(0.f, 1.f, 0.f),
541
-m_rescue_roll*dt/rescue_time*M_PI/180.0f);
542
btQuaternion q_pitch(btVector3(1.f, 0.f, 0.f),
543
-m_rescue_pitch*dt/rescue_time*M_PI/180.0f);
544
setXYZRotation(getXYZ()+Vec3(0, 0, rescue_height*dt/rescue_time),
545
getRotation()*q_roll*q_pitch);
547
m_attachment.update(dt);
726
EmergencyAnimation::update(dt);
728
m_attachment->update(dt);
549
730
//smoke drawing control point
550
if ( user_config->m_graphical_effects )
731
if ( UserConfigParams::m_graphical_effects )
552
733
m_smoke_system->update(dt);
554
} // user_config->m_graphical_effects
734
m_water_splash_system->update(dt);
735
} // UserConfigParams::m_graphical_effects
555
739
updatePhysics(dt);
557
//kart_info.m_last_track_coords = kart_info.m_curr_track_coords;
559
Moveable::update(dt);
741
/* (TODO: add back when properly done)
742
for (int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
744
if (m_custom_sounds[n] != NULL) m_custom_sounds[n]->position ( getXYZ() );
748
m_beep_sound->position ( getXYZ() );
561
749
m_engine_sound->position ( getXYZ() );
562
m_beep_sound->position ( getXYZ() );
563
750
m_crash_sound->position ( getXYZ() );
564
751
m_skid_sound->position ( getXYZ() );
566
753
// Check if a kart is (nearly) upside down and not moving much --> automatic rescue
567
if((fabs(getHPR().getRoll())>60 && fabs(getSpeed())<3.0f) )
754
if((fabs(getRoll())>60*DEGREE_TO_RAD && fabs(getSpeed())<3.0f) )
756
forceRescue(/*is_auto_rescue*/true);
572
759
btTransform trans=getTrans();
573
760
// Add a certain epsilon (0.3) to the height of the kart. This avoids
574
761
// problems of the ray being cast from under the track (which happened
575
762
// e.g. on tux tollway when jumping down from the ramp, when the chassis
576
// partly tunnels through the track). While tunneling should not be
763
// partly tunnels through the track). While tunneling should not be
577
764
// happening (since Z velocity is clamped), the epsilon is left in place
578
765
// just to be on the safe side (it will not hit the chassis itself).
579
Vec3 pos_plus_epsilon = trans.getOrigin()+btVector3(0,0,0.3f);
580
// These values cause the track not to be hit in tuxtrack. I leave
581
// them in as a test case if additional debugging should be needed.
582
// Note: it might be that the kart chassis is actually 'in' the track,
583
// i.e. it's a tunneling problem!
584
//btVector3 pos_plus_epsilon (-54.449902, -139.99402, -3.4524240);
585
// motionstate: -52.449902, -139.99402, -3.6524241
586
// collision object -52.221024, -139.99614, -3.5276926
766
Vec3 pos_plus_epsilon = trans.getOrigin()+btVector3(0,0.3f,0);
588
768
// Make sure that the ray doesn't hit the kart. This is done by
589
769
// resetting the collision filter group, so that this collision
600
780
m_body->getBroadphaseHandle()->m_collisionFilterGroup = old_group;
602
const Material* material=getMaterial();
603
m_power_reduction = 50.0f;
782
const Material* material=TerrainInfo::getMaterial();
604
783
if (getHoT()==Track::NOHIT) // kart falling off the track
606
785
// let kart fall a bit before rescuing
607
if( RaceManager::getTrack()->m_left_driveline.size() > 0 &&
608
fabs( getXYZ().getZ() - RaceManager::getTrack()->m_left_driveline[0].getZ() ) > 17)
786
const Vec3 *min, *max;
787
World::getWorld()->getTrack()->getAABB(&min, &max);
788
if(min->getY() - getXYZ().getY() > 17)
792
// Sometimes the material can be 0. This can happen if a kart is above
793
// another kart (e.g. mass collision, or one kart falling on another
794
// kart). Bullet does not have any triangle information in this case,
795
// and so material can not be set. In this case it is simply ignored
796
// since it can't hurt (material is only used for friction, zipper and
797
// rescue, so those things are not triggered till the kart is on the
611
799
else if(material)
613
// Sometimes the material can be 0. This can happen if a kart is above
614
// another kart (e.g. mass collision, or one kart falling on another
615
// kart). Bullet does not have any triangle information in this case,
616
// and so material can not be set. In this case it is simply ignored
617
// since it can't hurt (material is only used for friction, zipper and
618
// rescue, so those things are not triggered till the kart is on the
801
// If a terrain specific sfx is already being played, when a new
802
// terrain is entered, an old sfx should be finished (once, not
803
// looped anymore of course). The m_terrain_sound is then copied
804
// to a m_previous_terrain_sound, for which looping is disabled.
805
// In case that three sfx needed to be played (i.e. a previous is
806
// playing, a current is playing, and a new terrain with sfx is
807
// entered), the oldest (previous) sfx is stopped and deleted.
808
if(getLastMaterial()!=material)
810
// First stop any previously playing terrain sound
811
// and remove it, sp that m_previous_terrain_sound
812
// can be used again.
813
if(m_previous_terrain_sound)
815
sfx_manager->deleteSFX(m_previous_terrain_sound);
817
m_previous_terrain_sound = m_terrain_sound;
818
if(m_previous_terrain_sound)
819
m_previous_terrain_sound->setLoop(false);
821
const std::string s = material->getSFXName();
824
m_terrain_sound = sfx_manager->createSoundSource(s);
825
m_terrain_sound->play();
826
m_terrain_sound->setLoop(true);
829
m_terrain_sound = NULL;
831
if(m_previous_terrain_sound &&
832
m_previous_terrain_sound->getStatus()==SFXManager::SFX_STOPPED)
834
// We don't modify the position of m_previous_terrain_sound
835
// anymore, so that it keeps on playing at the place where the
836
// kart left the material.
837
sfx_manager->deleteSFX(m_previous_terrain_sound);
838
m_previous_terrain_sound = NULL;
842
m_terrain_sound->position(getXYZ());
843
material->setSFXSpeed(m_terrain_sound, m_speed);
620
846
if (material->isReset() && isOnGround()) forceRescue();
621
else if(material->isZipper() && isOnGround()) handleZipper();
847
else if(material->isZipper() && isOnGround()) handleZipper(material);
624
m_power_reduction = material->getSlowDown();
625
// Normal driving on terrain. Adjust for maximum terrain speed
626
float max_speed_here = material->getMaxSpeedFraction()*getMaxSpeed();
627
// If the speed is too fast, reduce the maximum speed gradually.
628
// The actual capping happens in updatePhysics
629
if(max_speed_here<m_speed)
630
m_max_speed_reduction += dt*material->getSlowDown();
632
m_max_speed_reduction = 0.0f;
850
MaxSpeed::setSlowdown(MaxSpeed::MS_DECREASE_TERRAIN,
851
material->getMaxSpeedFraction(),
852
material->getSlowDownTime() );
854
if(UserConfigParams::m_material_debug)
856
printf("%s\tfraction %f\ttime %f.\n",
857
material->getTexFname().c_str(),
858
material->getMaxSpeedFraction(),
859
material->getSlowDownTime() );
634
863
} // if there is material
636
865
// Check if any item was hit.
637
item_manager->hitItem(this);
866
item_manager->checkItemHit(this);
638
867
if(m_kart_properties->hasSkidmarks())
639
868
m_skidmarks->update(dt);
870
const bool emergency = playingEmergencyAnimation();
874
m_view_blocked_by_plunger = 0.0f;
641
877
// Remove the shadow if the kart is not on the ground (if a kart
642
878
// is rescued isOnGround might still be true, since the kart rigid
643
879
// body was removed from the physics, but still retain the old
644
880
// values for the raycasts).
645
if( (!isOnGround() || m_rescue) && m_shadow_enabled)
881
if( (!isOnGround() || emergency) && m_shadow_enabled)
647
883
m_shadow_enabled = false;
648
m_model_transform->removeKid(m_shadow);
884
m_shadow->disableShadow();
650
if(!m_shadow_enabled && isOnGround() && !m_rescue)
886
if(!m_shadow_enabled && isOnGround() && !emergency)
888
m_shadow->enableShadow();
652
889
m_shadow_enabled = true;
653
m_model_transform->addKid(m_shadow);
657
893
//-----------------------------------------------------------------------------
658
/** Sets zipper time, and apply one time additional speed boost.
894
/** Sets zipper time, and apply one time additional speed boost. It can be
895
* used with a specific material, in which case the zipper parmaters are
896
* taken from this material (parameters that are <0 will be using the
897
* kart-specific values from kart-properties.
898
* \param material If not NULL, will be used to determine the zipper
899
* parameters, otherwise the defaults from kart properties
901
* \param play_sound If true this will cause a sfx to be played even if the
902
* terrain hasn't changed. It is used by the zipper powerup.
660
void Kart::handleZipper()
904
void Kart::handleZipper(const Material *material, bool play_sound)
906
/** The additional speed allowed on top of the kart-specific maximum kart
908
float max_speed_increase;
910
/**Time the zipper stays activated. */
912
/** A one time additional speed gain - the kart will instantly add this
913
* amount of speed to its current speed. */
915
/** Time it takes for the zipper advantage to fade out. */
920
material->getZipperParameter(&max_speed_increase, &duration,
921
&speed_gain, &fade_out_time);
922
if(max_speed_increase<0)
923
max_speed_increase = m_kart_properties->getZipperMaxSpeedIncrease();
925
duration = m_kart_properties->getZipperTime();
927
speed_gain = m_kart_properties->getZipperSpeedGain();
929
fade_out_time = m_kart_properties->getZipperFadeOutTime();
933
max_speed_increase = m_kart_properties->getZipperMaxSpeedIncrease();
934
duration = m_kart_properties->getZipperTime();
935
speed_gain = m_kart_properties->getZipperSpeedGain();
936
fade_out_time = m_kart_properties->getZipperFadeOutTime();
662
938
// Ignore a zipper that's activated while braking
663
if(m_controls.m_brake) return;
664
m_zipper_time_left = stk_config->m_zipper_time;
665
btVector3 v = m_body->getLinearVelocity();
666
float current_speed = v.length();
667
float speed = std::min(current_speed+stk_config->m_zipper_speed_gain,
668
getMaxSpeedOnTerrain());
669
// If the speed is too low, very minor components of the velocity vector
670
// can become too big. E.g. each kart has a z component (to offset gravity
671
// I assume, around 0.16) --> if the karts are (nearly) at standstill,
672
// the z component is exaggerated, resulting in a jump. Even if Z
673
// is set to 0, minor left/right movements are then too strong.
674
// Therefore a zipper only adds the speed if the speed is at least 1
675
// (experimentally found valud). It also avoids NAN problems (if v=0).
676
if(current_speed>1.0f) m_body->setLinearVelocity(v*(speed/current_speed));
939
if(m_controls.m_brake || m_speed<0) return;
941
MaxSpeed::increaseMaxSpeed(MaxSpeed::MS_INCREASE_ZIPPER,
942
max_speed_increase, duration, fade_out_time);
943
// This will result in all max speed settings updated, but no
944
// changes to any slow downs since dt=0
946
float speed = std::min(m_speed + speed_gain,
947
MaxSpeed::getCurrentMaxSpeed() );
949
m_vehicle->activateZipper(speed);
950
// Play custom character sound (weee!)
951
playCustomSFX(SFXManager::CUSTOM_ZIPPER);
952
m_controller->handleZipper(play_sound);
677
953
} // handleZipper
678
//-----------------------------------------------------------------------------
679
#define sgn(x) ((x<0)?-1.0f:((x>0)?1.0f:0.0f))
681
// -----------------------------------------------------------------------------
685
btTransform t=getTrans();
686
t.getOpenGLMatrix(m);
688
btVector3 wire_color(0.5f, 0.5f, 0.5f);
689
//RaceManager::getWorld()->getPhysics()->debugDraw(m, m_body->getCollisionShape(),
691
btCylinderShapeX wheelShape( btVector3(0.1f,
692
m_kart_properties->getWheelRadius(),
693
m_kart_properties->getWheelRadius()));
694
btVector3 wheelColor(1,0,0);
695
for(int i=0; i<m_vehicle->getNumWheels(); i++)
697
m_vehicle->updateWheelTransform(i, true);
699
m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(m);
700
RaceManager::getWorld()->getPhysics()->debugDraw(m, &wheelShape, wheelColor);
704
955
// -----------------------------------------------------------------------------
705
956
/** Returned an additional engine power boost when using nitro.
755
1023
// -----------------------------------------------------------------------------
756
1024
void Kart::beep()
758
m_beep_sound->play();
1026
// If the custom horn can't play (isn't defined) then play the default one
1027
if (!playCustomSFX(SFXManager::CUSTOM_HORN))
1028
m_beep_sound->play();
761
1032
// -----------------------------------------------------------------------------
762
void Kart::updatePhysics (float dt)
1036
This function will play a particular character voice for this kart. It
1037
returns whether or not a character voice sample exists for the particular
1038
event. If there is no voice sample, a default can be played instead.
1040
Use entries from the CustomSFX enumeration as a parameter (see
1041
sfx_manager.hpp). eg. playCustomSFX(SFXManager::CUSTOM_CRASH)
1043
Obviously we don't want a certain character voicing multiple phrases
1044
simultaneously. It just sounds bad. There are two ways of avoiding this:
1046
1. If there is already a voice sample playing for the character
1047
don't play another until it is finished.
1049
2. If there is already a voice sample playing for the character
1050
stop the sample, and play the new one.
1052
Currently we're doing #2.
1058
bool Kart::playCustomSFX(unsigned int type)
1060
// (TODO: add back when properly done)
1066
// Stop all other character voices for this kart before playing a new one
1067
// we don't want overlapping phrases coming from the same kart
1068
for (unsigned int n = 0; n < SFXManager::NUM_CUSTOMS; n++)
1070
if (m_custom_sounds[n] != NULL)
1072
// If the sound we're trying to play is already playing
1073
// don't stop it, we'll just let it finish.
1074
if (type != n) m_custom_sounds[n]->stop();
1078
if (type < SFXManager::NUM_CUSTOMS)
1080
if (m_custom_sounds[type] != NULL)
1083
//printf("Kart SFX: playing %s for %s.\n", sfx_manager->getCustomTagName(type), m_kart_properties->getIdent().c_str());
1084
// If it's already playing, let it finish
1085
if (m_custom_sounds[type]->getStatus() != SFXManager::SFX_PLAYING)
1087
m_custom_sounds[type]->play();
1094
// ----------------------------------------------------------------------------
1095
/** Updates the physics for this kart: computing the driving force, set
1096
* steering, handles skidding, terrain impact on kart, ...
1097
* \param dt Time step size.
1099
void Kart::updatePhysics(float dt)
1101
// Check if accel is pressed for the first time. The actual timing
1102
// is done in getStartupBoost - it returns 0 if the start was actually
1103
// too slow to qualify for a boost.
1104
if(!m_has_started && m_controls.m_accel)
1106
m_has_started = true;
1107
float f = m_kart_properties->getStartupBoost();
1108
m_vehicle->activateZipper(f);
1109
MaxSpeed::increaseMaxSpeed(MS_INCREASE_ZIPPER, +10,
764
1114
m_bounce_back_time-=dt;
765
float engine_power = getActualWheelForce() + handleNitro(dt);
766
if(m_attachment.getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
1115
float engine_power = getActualWheelForce() + handleNitro(dt)
1116
+ m_slipstream->getSlipstreamPower();
1118
if(m_attachment->getType()==ATTACH_PARACHUTE) engine_power*=0.2f;
1122
if (m_controls.m_accel)
1124
float orientation = getHeading();
1125
m_body->applyCentralImpulse(btVector3(60.0f*sin(orientation), 0.0, 60.0f*cos(orientation)));
1127
if (m_controls.m_steer != 0.0f)
1129
m_body->applyTorque(btVector3(0.0, m_controls.m_steer * 3500.0f, 0.0));
1131
if (m_controls.m_brake)
1133
btVector3 velocity = m_body->getLinearVelocity();
1135
const float x = velocity.x();
1136
if (x > 0.2f) velocity.setX(x - 0.2f);
1137
else if (x < -0.2f) velocity.setX(x + 0.2f);
1138
else velocity.setX(0);
1140
const float y = velocity.y();
1141
if (y > 0.2f) velocity.setY(y - 0.2f);
1142
else if (y < -0.2f) velocity.setY(y + 0.2f);
1143
else velocity.setY(0);
1145
const float z = velocity.z();
1146
if (z > 0.2f) velocity.setZ(z - 0.2f);
1147
else if (z < -0.2f) velocity.setZ(z + 0.2f);
1148
else velocity.setZ(0);
1150
m_body->setLinearVelocity(velocity);
1152
//float orientation = getHeading();
1153
//m_body->applyCentralImpulse(btVector3(-60.0f*sin(orientation), 0.0, -60.0f*cos(orientation)));
1156
// dampen any roll while flying, makes the kart hard to control
1157
btVector3 velocity = m_body->getAngularVelocity();
1158
const float z = velocity.z();
1159
if (z > 0.1f) velocity.setZ(z - 0.1f);
1160
else if (z < -0.1f) velocity.setZ(z + 0.1f);
1161
else velocity.setZ(0);
1162
m_body->setAngularVelocity(velocity);
768
1166
if(m_controls.m_accel) // accelerating
769
{ // For a short time after a collision disable the engine,
1168
// For a short time after a collision disable the engine,
770
1169
// so that the karts can bounce back a bit from the obstacle.
771
if(m_bounce_back_time>0.0f)
1170
if(m_bounce_back_time>0.0f)
772
1171
engine_power = 0.0f;
773
1172
// let a player going backwards accelerate quickly (e.g. if a player hits a
774
1173
// wall, he needs to be able to start again quickly after going backwards)
775
1174
else if(m_speed < 0.0f)
776
1175
engine_power *= 5.0f;
777
// Engine slow down due to terrain (see m_power_reduction is set in
778
// update() depending on terrain type.
779
engine_power *= m_power_reduction/stk_config->m_slowdown_factor;
780
m_vehicle->applyEngineForce(engine_power, 2);
781
m_vehicle->applyEngineForce(engine_power, 3);
1177
// Lose some traction when skidding, to balance the adventage
1178
// Up to r5483 AIs were allowed to cheat in medium and high diff levels
1179
if(m_controls.m_drift)
1180
engine_power *= 0.5f;
1182
applyEngineForce(engine_power*m_controls.m_accel);
782
1184
// Either all or no brake is set, so test only one to avoid
783
1185
// resetting all brakes most of the time.
784
if(m_vehicle->getWheelInfo(0).m_brake &&
785
!RaceManager::getWorld()->isStartPhase())
1186
if(m_vehicle->getWheelInfo(0).m_brake &&
1187
!World::getWorld()->isStartPhase())
790
1191
{ // not accelerating
807
1207
// going backward, apply reverse gear ratio (unless he goes too fast backwards)
808
if ( -m_speed < getMaxSpeedOnTerrain()*m_max_speed_reverse_ratio )
1208
if ( -m_speed < MaxSpeed::getCurrentMaxSpeed()
1209
*m_kart_properties->getMaxSpeedReverseRatio() )
810
1211
// The backwards acceleration is artificially increased to
811
1212
// allow players to get "unstuck" quicker if they hit e.g.
812
// a wall. At the same time we have to prevent that driving
813
// backards gives an advantage (see m_max_speed_reverse_ratio),
814
// and that a potential slowdown due to the terrain the
815
// kart is driving on feels right. The speedup factor on
816
// normal terrain (power_reduction/slowdown_factor should
817
// be 2.5 (which was experimentally determined to feel
819
float f = 2.5f - 3.8f*(1-m_power_reduction/stk_config->m_slowdown_factor);
820
// Avoid that a kart gets really stuck:
822
m_vehicle->applyEngineForce(-engine_power*f, 2);
823
m_vehicle->applyEngineForce(-engine_power*f, 3);
1214
applyEngineForce(-engine_power*2.5f);
1216
else // -m_speed >= max speed on this terrain
827
m_vehicle->applyEngineForce(0.f, 2);
828
m_vehicle->applyEngineForce(0.f, 3);
1218
applyEngineForce(0.0f);
835
1225
// lift the foot from throttle, brakes with 10% engine_power
836
m_vehicle->applyEngineForce(-m_controls.m_accel*engine_power*0.1f, 2);
837
m_vehicle->applyEngineForce(-m_controls.m_accel*engine_power*0.1f, 3);
1226
applyEngineForce(-m_controls.m_accel*engine_power*0.1f);
839
if(!RaceManager::getWorld()->isStartPhase())
1228
// If not giving power (forward or reverse gear), and speed is low
1229
// we are "parking" the kart, so in battle mode we can ambush people, eg
1230
if(abs(m_speed) < 5.0f) {
1231
for(int i=0; i<4; i++) m_vehicle->setBrake(20.0f, i);
1234
} // not accelerating
843
1235
#ifdef ENABLE_JUMP
844
1236
if(m_controls.jump && isOnGround())
846
1238
//Vector3 impulse(0.0f, 0.0f, 10.0f);
847
1239
// getVehicle()->getRigidBody()->applyCentralImpulse(impulse);
848
1240
btVector3 velocity = m_body->getLinearVelocity();
881
1273
m_skid_sound->stop();
1276
// dynamically determine friction so that the kart looses its traction
1277
// when trying to drive on too steep surfaces. Below angles of 0.25 rad,
1278
// you have full traction; above 0.5 rad angles you have absolutely none;
1279
// inbetween there is a linear change in friction
1280
float friction = 1.0f;
1281
bool enable_skidding = false;
1283
// If a material has friction of more than 10000 treat this
1284
// as no-skidding possible. This way the current skidding
1285
// handling can be disabled for certain material (e.g. the
1286
// curve in skyline on which otherwise karts could not drive).
1287
// We also had a crash reported here, which was caused by not
1288
// having a material here - no idea how this could have happened,
1289
// but this problem is now avoided by testing if there is a material
1291
(!getMaterial() || getMaterial()->getFriction()<10000.0f))
1293
const btMatrix3x3 &m = m_vehicle->getChassisWorldTransform().getBasis();
1294
// To get the angle between up=(0,1,0), we have to do:
1295
// m*(0,1,0) to get the up vector of the kart, then the
1296
// scalar product between this and (0,1,0) - which is m[1][1]:
1297
float distanceFromUp = m[1][1];
1299
if (distanceFromUp < 0.85f)
1302
enable_skidding = true;
1304
else if (distanceFromUp > 0.9f)
1310
friction = (distanceFromUp - 0.85f) / 0.5f;
1311
enable_skidding = true;
1315
for (unsigned int i=0; i<4; i++)
1317
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
1318
wheel.m_frictionSlip = friction*m_kart_properties->getFrictionSlip();
1321
m_vehicle->enableSliding(enable_skidding);
1326
static float f = 0.0f;
1331
printf("[%s] %f %f --> friction = %f\n", m_kart_properties->getIdent().c_str(), getPitch(), getRoll(), friction);
883
1335
float steering = getMaxSteerAngle() * m_controls.m_steer*m_skidding;
885
1337
m_vehicle->setSteeringValue(steering, 0);
893
1345
// calculate direction of m_speed
894
1346
const btTransform& chassisTrans = getVehicle()->getChassisWorldTransform();
895
1347
btVector3 forwardW (
896
chassisTrans.getBasis()[0][1],
897
chassisTrans.getBasis()[1][1],
898
chassisTrans.getBasis()[2][1]);
1348
chassisTrans.getBasis()[0][2],
1349
chassisTrans.getBasis()[1][2],
1350
chassisTrans.getBasis()[2][2]);
900
1352
if (forwardW.dot(getVehicle()->getRigidBody()->getLinearVelocity()) < btScalar(0.))
901
1353
m_speed *= -1.f;
903
//cap at maximum velocity
904
const float max_speed = getMaxSpeedOnTerrain();
905
if ( m_speed > max_speed )
907
const float velocity_ratio = max_speed/m_speed;
909
btVector3 velocity = m_body->getLinearVelocity();
911
velocity.setY( velocity.getY() * velocity_ratio );
912
velocity.setX( velocity.getX() * velocity_ratio );
914
getVehicle()->getRigidBody()->setLinearVelocity( velocity );
1355
// Cap speed if necessary
1356
MaxSpeed::update(dt);
918
1358
// To avoid tunneling (which can happen on long falls), clamp the
919
// velocity in Z direction. Tunneling can happen if the Z velocity
1359
// velocity in Y direction. Tunneling can happen if the Y velocity
920
1360
// is larger than the maximum suspension travel (per frame), since then
921
1361
// the wheel suspension can not stop/slow down the fall (though I am
922
1362
// not sure if this is enough in all cases!). So the speed is limited
923
1363
// to suspensionTravel / dt with dt = 1/60 (since this is the dt
924
1364
// bullet is using).
1365
// Only apply if near ground instead of purely based on speed avoiding
1366
// the "parachute on top" look.
925
1367
const Vec3 &v = m_body->getLinearVelocity();
926
if(v.getZ() < - m_kart_properties->getSuspensionTravelCM()*0.01f*60)
1368
if(/*isNearGround() &&*/ v.getY() < - m_kart_properties->getSuspensionTravelCM()*0.01f*60)
928
1370
Vec3 v_clamped = v;
929
1371
// clamp the speed to 99% of the maxium falling speed.
930
v_clamped.setZ(-m_kart_properties->getSuspensionTravelCM()*0.01f*60 * 0.99f);
1372
v_clamped.setY(-m_kart_properties->getSuspensionTravelCM()*0.01f*60 * 0.99f);
931
1373
m_body->setLinearVelocity(v_clamped);
954
1417
,m_body->getAngularVelocity().getX()
955
1418
,m_body->getAngularVelocity().getY()
956
1419
,m_body->getAngularVelocity().getZ()
957
,getHPR().getHeading()
960
1424
} // updatePhysics
962
//-----------------------------------------------------------------------------
963
void Kart::forceRescue()
967
//-----------------------------------------------------------------------------
968
/** Drops a kart which was rescued back on the track.
1427
//-----------------------------------------------------------------------------
1428
/** Attaches the right model, creates the physics and loads all special
1429
* effects (particle systems etc.)
970
void Kart::endRescue()
974
m_body->setLinearVelocity (btVector3(0.0f,0.0f,0.0f));
975
m_body->setAngularVelocity(btVector3(0.0f,0.0f,0.0f));
977
// let the mode decide where to put the kart
978
RaceManager::getWorld()->moveKartAfterRescue(this, m_body);
980
RaceManager::getWorld()->getPhysics()->addKart(this);
983
//-----------------------------------------------------------------------------
985
1431
void Kart::loadData()
987
float r [ 2 ] = { -10.0f, 100.0f } ;
990
ssgEntity *obj = m_kart_properties->getKartModel()->getRoot();
1433
m_kart_model->attachModel(&m_node);
1434
// Attachment must be created after attachModel, since only then the
1435
// scene node will exist (to which the attachment is added). But the
1436
// attachment is needed in createPhysics (which gets the mass, which
1437
// is dependent on the attachment).
1438
m_attachment = new Attachment(this);
991
1439
createPhysics();
993
SSGHelp::createDisplayLists(obj); // create all display lists
994
ssgRangeSelector *lod = new ssgRangeSelector ;
996
lod -> addKid ( obj ) ;
997
lod -> setRanges ( r, 2 ) ;
999
getModelTransform() -> addKid ( lod ) ;
1001
1441
// Attach Particle System
1002
m_smoke_system = new Smoke(this);
1003
m_smoke_system->ref();
1004
m_nitro = new Nitro(this);
1442
if ( UserConfigParams::m_graphical_effects )
1444
m_smoke_system = new Smoke(this);
1446
m_water_splash_system = new WaterSplash(this);
1447
m_nitro = new Nitro(this);
1448
m_slipstream = new SlipStream(this);
1007
1450
if(m_kart_properties->hasSkidmarks())
1008
1451
m_skidmarks = new SkidMarks(*this);
1010
m_shadow = createShadow(m_kart_properties->getShadowFile(), -1, 1, -1, 1);
1012
m_model_transform->addKid ( m_shadow );
1013
m_shadow_enabled = true;
1453
m_shadow = new Shadow(m_kart_properties->getShadowTexture(),
1016
1457
//-----------------------------------------------------------------------------
1017
/** Stores the current suspension length. This function is called from world
1458
/** Stores the current suspension length. This function is called from world
1018
1459
* after all karts are in resting position (see World::resetAllKarts), so
1019
1460
* that the default suspension rest length can be stored. This is then used
1020
1461
* later to move the wheels depending on actual suspension, so that when
1021
* a kart is in rest, the wheels are at the position at which they were
1462
* a kart is in rest, the wheels are at the position at which they were
1024
1465
void Kart::setSuspensionLength()
1031
1472
} // setSuspensionLength
1033
1474
//-----------------------------------------------------------------------------
1034
void Kart::updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr)
1036
float wheel_z_axis[4];
1037
KartModel *kart_model = m_kart_properties->getKartModel();
1475
/** Applies engine power to all the wheels that are traction capable,
1476
* so other parts of code do not have to be adjusted to simulate different
1477
* kinds of vehicles in the general case, only if they are trying to
1478
* simulate traction control, diferentials or multiple independent electric
1479
* engines, they will have to tweak the power in a per wheel basis.
1481
void Kart::applyEngineForce(float force)
1483
// Split power to simulate a 4WD 40-60, other values possible
1484
// FWD or RWD is a matter of putting a 0 and 1 in the right place
1485
float frontForce = force*0.4f;
1486
float rearForce = force*0.6f;
1488
for(unsigned int i=0; i<2; i++)
1490
m_vehicle->applyEngineForce (frontForce, i);
1493
for(unsigned int i=2; i<4; i++)
1495
m_vehicle->applyEngineForce (rearForce, i);
1497
} // applyEngineForce
1499
//-----------------------------------------------------------------------------
1500
/** Updates the graphics model. Mainly set the graphical position to be the
1501
* same as the physics position, but uses offsets to position and rotation
1502
* for special gfx effects (e.g. skidding will turn the karts more). These
1503
* variables are actually not used here atm, but are defined here and then
1505
* \param offset_xyz Offset to be added to the position.
1506
* \param rotation Additional rotation.
1508
void Kart::updateGraphics(const Vec3& offset_xyz,
1509
const btQuaternion& rotation)
1511
float wheel_up_axis[4];
1038
1512
for(unsigned int i=0; i<4; i++)
1040
1514
// Set the suspension length
1041
wheel_z_axis[i] = m_default_suspension_length[i]
1042
- m_vehicle->getWheelInfo(i).m_raycastInfo.m_suspensionLength;
1515
wheel_up_axis[i] = m_default_suspension_length[i]
1516
- m_vehicle->getWheelInfo(i).m_raycastInfo.m_suspensionLength;
1044
#define AUTO_SKID_VISUAL 1.7f
1046
if (m_skidding>AUTO_SKID_VISUAL) // Above a limit, start counter rotating the wheels to get drifting look
1047
auto_skid = m_controls.m_steer*30.0f*((AUTO_SKID_VISUAL - m_skidding) / 0.8f); // divisor comes from max_skid - AUTO_SKID_VISUAL
1049
auto_skid = m_controls.m_steer*30.0f;
1050
kart_model->adjustWheels(m_wheel_rotation, auto_skid,
1518
m_kart_model->update(m_wheel_rotation, getSteerPercent(), wheel_up_axis);
1053
Vec3 center_shift = getGravityCenterShift();
1054
float X = m_vehicle->getWheelInfo(0).m_chassisConnectionPointCS.getZ()
1520
Vec3 center_shift = m_kart_properties->getGravityCenterShift();
1521
float y = m_vehicle->getWheelInfo(0).m_chassisConnectionPointCS.getY()
1055
1522
- m_default_suspension_length[0]
1056
1523
- m_vehicle->getWheelInfo(0).m_wheelsRadius
1057
- (kart_model->getWheelGraphicsRadius(0)
1058
-kart_model->getWheelGraphicsPosition(0).getZ() );
1059
center_shift.setZ(X);
1524
- (m_kart_model->getWheelGraphicsRadius(0)
1525
-m_kart_model->getWheelGraphicsPosition(0).getY() );
1526
center_shift.setY(y);
1061
1528
if(m_smoke_system)
1063
float f = fabsf(m_controls.m_steer) > 0.8 ? 50.0f : 0.0f;
1531
if(getMaterial() && getMaterial()->hasSmoke() &&
1532
fabsf(m_controls.m_steer) > 0.8 &&
1064
1535
m_smoke_system->setCreationRate((m_skidding-1)*f);
1537
if(m_water_splash_system)
1539
float f = getMaterial() && getMaterial()->hasWaterSplash() && isOnGround()
1540
? sqrt(getSpeed())*40.0f
1542
m_water_splash_system->setCreationRate(f);
1067
m_nitro->setCreationRate(m_controls.m_nitro && m_collected_energy>0
1068
? getSpeed()*5.0f : 0);
1070
float speed_ratio = getSpeed()/getMaxSpeed();
1545
// fabs(speed) is important, otherwise the negative number will
1546
// become a huge unsigned number in the particle scene node!
1547
m_nitro->setCreationRate(m_controls.m_nitro && isOnGround() && m_collected_energy>0
1548
? (10.0f + fabsf(getSpeed())*20.0f) : 0);
1550
// For testing purposes mis-use the nitro graphical effects to show
1551
// then the slipstream becomes usable.
1552
if(m_slipstream->inUse())
1553
m_nitro->setCreationRate(20.0f);
1555
float speed_ratio = getSpeed()/MaxSpeed::getCurrentMaxSpeed();
1071
1556
float offset_heading = getSteerPercent()*m_kart_properties->getSkidVisual()
1072
1557
* speed_ratio * m_skidding*m_skidding;
1073
Moveable::updateGraphics(center_shift, Vec3(offset_heading, 0, 0));
1558
Moveable::updateGraphics(center_shift,
1559
btQuaternion(offset_heading, 0, 0));
1074
1560
} // updateGraphics