void PhysicsContactEffectManager::physicsContact(const PhysicsContact &contact) { // WARNING: unsafe IGamePhysicsObject -> AbstractPhysicsObject casts! AbstractPhysicsObject *o1 = (AbstractPhysicsObject *)contact.obj1; AbstractPhysicsObject *o2 = (AbstractPhysicsObject *)contact.obj2; //assert(o1 != NULL); //assert(o2 != NULL); assert(contact.physicsObject1); assert(contact.physicsObject2); #ifdef PHYSICS_PHYSX int sm1 = contact.physicsObject1->getIntData(); int sm2 = contact.physicsObject2->getIntData(); if(sm1 == SOUNDMATERIALPARSER_NO_SOUND_INDEX || sm2 == SOUNDMATERIALPARSER_NO_SOUND_INDEX) { return; } #else if (o1->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX || o2->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX) { return; } #endif const util::SoundMaterialParser::SoundMaterialList &smlist = impl->soundmp->getSoundMaterials(); for (int i = 0; i < 2; i++) { AbstractPhysicsObject *o = o1; if (i == 1) { o = o2; } #ifdef PHYSICS_PHYSX int smindex = sm1; if (i == 1) { smindex = sm2; } assert(smindex >= 0 && smindex < (int)smlist.size()); #else int smindex = o->getSoundMaterial(); #endif bool makeEffect = false; VC3 effectpos; if(o) { if(contact.contactForceLen >= smlist[smindex].requiredEffectForce) { effectpos = contact.contactPosition; VC3 accel = o->getAcceleration(); VC3 angaccel = o->getAngularAcceleration(); if (accel.GetSquareLength() >= smlist[smindex].requiredEffectAcceleration * smlist[smindex].requiredEffectAcceleration || angaccel.GetSquareLength() >= smlist[smindex].requiredEffectAngularAcceleration * smlist[smindex].requiredEffectAngularAcceleration) { makeEffect = true; } } } else { if(contact.contactForceLen >= smlist[smindex].requiredEffectForce) { makeEffect = true; effectpos = contact.contactPosition; } } if(makeEffect) { if (o) { if (impl->game->gameTimer < o->getLastEffectTick() + (smlist[smindex].effectMaxRate / GAME_TICK_MSEC)) { makeEffect = false; } else { o->setLastEffectTick(impl->game->gameTimer); } } } if(makeEffect) { std::vector<std::string> effectlist = smlist[smindex].effects; if (effectlist.size() > 0) { float effectFactor = 1.0f; if (smlist[smindex].requiredEffectForce > 0.0f) { // 0% - 100% effect factor (100% required force - 200% required force) effectFactor = (contact.contactForceLen / smlist[smindex].requiredEffectForce) - 1.0f; if (effectFactor > 1.0f) effectFactor = 1.0f; assert(effectFactor >= 0.0f); assert(effectFactor <= 1.0f); } int effnum = (int)(effectFactor * (effectlist.size() - 1)); if (effnum < 0) effnum = 0; if (effnum >= (int)effectlist.size()) effnum = (int)effectlist.size() - 1; const char *effname = effectlist[effnum].c_str(); ui::VisualEffectManager *vefman = impl->game->gameUI->getVisualEffectManager(); if (vefman != NULL) { assert(effname != NULL); // TODO: optimize this!!! int visualEffId = vefman->getVisualEffectIdByName(effname); if (visualEffId != -1) { // TODO: proper lifetime int lifetime = GAME_TICKS_PER_SECOND / 2; VisualEffect *vef = vefman->createNewManagedVisualEffect(visualEffId, lifetime, NULL, NULL, effectpos, effectpos, VC3(0,0,0), VC3(0,0,0), impl->game); if (vef == NULL) { Logger::getInstance()->error("PhysicsContactEffectManager::physicsContact - Failed to create visual effect."); Logger::getInstance()->debug(effname); } } else { Logger::getInstance()->error("PhysicsContactEffectManager::physicsContact - Given visual effect name not found."); Logger::getInstance()->debug(effname); } } } } } }
void PhysicsContactSoundManager::physicsContact(const PhysicsContact &contact) { // WARNING: unsafe IGamePhysicsObject -> AbstractPhysicsObject casts! AbstractPhysicsObject *o1 = (AbstractPhysicsObject *)contact.obj1; AbstractPhysicsObject *o2 = (AbstractPhysicsObject *)contact.obj2; //assert(o1 != NULL); //assert(o2 != NULL); assert(contact.physicsObject1); assert(contact.physicsObject2); #ifdef PHYSICS_PHYSX int sm1 = contact.physicsObject1->getIntData(); int sm2 = contact.physicsObject2->getIntData(); // int claw_material = impl->soundmp->getMaterialIndexByName( "claw" ); // int claw_body_material = impl->soundmp->getMaterialIndexByName( "claw_body" ); if(sm1 == SOUNDMATERIALPARSER_NO_SOUND_INDEX || sm2 == SOUNDMATERIALPARSER_NO_SOUND_INDEX) { return; } #else if (o1->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX || o2->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX) { return; } #endif const util::SoundMaterialParser::SoundMaterialList &smlist = impl->soundmp->getSoundMaterials(); for (int i = 0; i < 2; i++) { AbstractPhysicsObject *o = o1; if (i == 1) { o = o2; } #ifdef PHYSICS_PHYSX int smindex = sm1; if (i == 1) { smindex = sm2; } assert(smindex >= 0 && smindex < (int)smlist.size()); #else int smindex = o->getSoundMaterial(); #endif bool makeSound = false; VC3 soundpos; if(o) { /* // debug logging if( contact.contactForceLen > 1.0f && smlist[smindex].sounds.empty() == false ) { VC3 accel = o->getAcceleration(); VC3 angaccel = o->getAngularAcceleration(); std::stringstream ss; ss << contact.contactForceLen << ", " << accel.GetLength() << ", " << angaccel.GetLength() << std::endl; Logger::getInstance()->error( ss.str().c_str() ); } */ if(contact.contactForceLen >= smlist[smindex].requiredForce) { // TODO: use contact position instead of object's position. soundpos = o->getPosition(); VC3 accel = o->getAcceleration(); VC3 angaccel = o->getAngularAcceleration(); if (accel.GetSquareLength() >= smlist[smindex].requiredAcceleration * smlist[smindex].requiredAcceleration || angaccel.GetSquareLength() >= smlist[smindex].requiredAngularAcceleration * smlist[smindex].requiredAngularAcceleration) { makeSound = true; /* std::vector<std::string> soundlist = smlist[smindex].sounds; if (soundlist.size() > 0) { // TODO: some better pseudo-random logic here maybe... int sndnum = rand() % soundlist.size(); const char *soundfile = soundlist[sndnum].c_str(); float volumeFactor = 1.0f; if (smlist[smindex].requiredForce > 0.0f) { // 40% - 100% volume factor (100% required force - 200% required force) volumeFactor = (contact.contactForceLen / smlist[smindex].requiredForce) - 1.0f; volumeFactor *= 0.6f; volumeFactor += 0.4f; if (volumeFactor > 1.0f) volumeFactor = 1.0f; assert(volumeFactor >= 0.4f); assert(volumeFactor <= 1.0f); } impl->gameUI->playSoundEffect(soundfile, soundpos.x, soundpos.y, soundpos.z, false, (int)(DEFAULT_SOUND_EFFECT_VOLUME * volumeFactor), DEFAULT_SOUND_RANGE, DEFAULT_SOUND_PRIORITY_NORMAL); } */ } } // not to repeat the effect too frequently if( o != NULL && makeSound && ( impl->gameUI->game->gameTimer - o->getLastEffectSoundTick() ) > ( 200 / GAME_TICK_MSEC ) ) { o->setLastEffectSoundTick( impl->gameUI->game->gameTimer ); } else { makeSound = false; } } else { if(contact.contactForceLen >= smlist[smindex].requiredForce) { makeSound = true; #ifdef PHYSICS_PHYSX if(i == 0) contact.physicsObject1->getPosition(soundpos); else contact.physicsObject2->getPosition(soundpos); #endif } } if(makeSound) { std::vector<std::string> soundlist = smlist[smindex].sounds; if (soundlist.size() > 0) { // TODO: some better pseudo-random logic here maybe... int sndnum = rand() % soundlist.size(); // const char *soundfile = soundlist[sndnum].c_str(); float volumeFactor = 1.0f; std::string soundfile = soundlist[sndnum]; if (smlist[smindex].requiredForce > 0.0f) { // 100% required force - 500% required force float contactFactor = contact.contactForceLen / ( smlist[smindex].requiredForce * 5.0f ); if( contactFactor > 1.0f ) contactFactor = 1.0f; int sndnum = (int)((float)( soundlist.size() - 1 ) * contactFactor + 0.5f); sndnum += ( rand() % 3 ) - 1; if( sndnum < 0 ) sndnum = 0; if( sndnum > (signed)( soundlist.size() - 1 ) ) sndnum = (signed)( soundlist.size() - 1 ); soundfile = soundlist[sndnum]; /* // 40% - 100% volume factor (100% required force - 200% required force) volumeFactor = (contact.contactForceLen / smlist[smindex].requiredForce) - 1.0f; volumeFactor *= 0.6f; volumeFactor += 0.4f; if (volumeFactor > 1.0f) volumeFactor = 1.0f; assert(volumeFactor >= 0.4f); assert(volumeFactor <= 1.0f); */ } impl->gameUI->playSoundEffect(soundfile.c_str(), soundpos.x, soundpos.y, soundpos.z, false, (int)(DEFAULT_SOUND_EFFECT_VOLUME * volumeFactor), DEFAULT_SOUND_RANGE, DEFAULT_SOUND_PRIORITY_NORMAL); } } } }