diff --git a/CHANGELOG.md b/CHANGELOG.md index 63bc7e02b..64b9c875a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * New smoother camera by Auria * New grand prix win scene * Gamepad configuration bugfixes +* 3 Strikes Battles : added spare tire karts * Various improvements (wall driving fixes, parachutes, GP points, cannon fixes, colorization shader) ## SuperTuxKart 0.9.2 diff --git a/data/shaders/flipparticle.vert b/data/shaders/flipparticle.vert index 4c81d8082..dc2e8f5dd 100644 --- a/data/shaders/flipparticle.vert +++ b/data/shaders/flipparticle.vert @@ -22,7 +22,7 @@ float anglespeed; out float lf; out vec2 tc; -out vec3 pc; +out vec4 pc; void main(void) { @@ -68,5 +68,5 @@ void main(void) vec4 viewpos = ViewMatrix * vec4(newposition + newquadcorner, 1.0); gl_Position = ProjectionMatrix * viewpos; - pc = vec3(1.); + pc = vec4(1.); } diff --git a/data/shaders/particle.frag b/data/shaders/particle.frag index 3a2dd232a..25eec19e2 100644 --- a/data/shaders/particle.frag +++ b/data/shaders/particle.frag @@ -4,7 +4,7 @@ uniform mat4 invproj; in float lf; in vec2 tc; -in vec3 pc; +in vec4 pc; out vec4 FragColor; #stk_include "utils/getPosFromUVDepth.frag" @@ -17,6 +17,5 @@ void main(void) float EnvZ = texture(dtex, xy).x; vec4 EnvPos = getPosFromUVDepth(vec3(xy, EnvZ), InverseProjectionMatrix); float alpha = clamp((EnvPos.z - FragmentPos.z) * 0.3, 0., 1.); - vec4 color = texture(tex, tc) * vec4(pc, 1.0); - FragColor = color * alpha * smoothstep(1., 0.8, lf); + FragColor = texture(tex, tc) * pc * alpha; } diff --git a/data/shaders/particle.vert b/data/shaders/particle.vert index d9a7d8659..600e247a2 100644 --- a/data/shaders/particle.vert +++ b/data/shaders/particle.vert @@ -19,13 +19,16 @@ in vec2 quadcorner; out float lf; out vec2 tc; -out vec3 pc; +out vec4 pc; void main(void) { tc = Texcoord; lf = lifetime; - pc = color_from + (color_to - color_from) * lifetime; + pc = vec4(vec3(color_from + (color_to - color_from) * lf), 1.0) * smoothstep(1., 0.8, lf); +#if defined(GL_ES) && !defined(Advanced_Lighting_Enabled) + pc.rgb = pow(pc.rgb, vec3(1. / 2.2)); +#endif vec3 newposition = Position; vec4 viewpos = ViewMatrix * vec4(newposition, 1.0); diff --git a/src/audio/dummy_sfx.hpp b/src/audio/dummy_sfx.hpp index 63f9893e9..32eb1116d 100644 --- a/src/audio/dummy_sfx.hpp +++ b/src/audio/dummy_sfx.hpp @@ -47,9 +47,9 @@ public: virtual void reallySetSpeedPosition(float f, const Vec3 &p) {} virtual void play() {} - virtual void reallyPlayNow() {} - virtual void play(const Vec3 &xyz) {} - virtual void reallyPlayNow(const Vec3 &xyz) {} + virtual void reallyPlayNow(SFXBuffer* buffer = NULL) {} + virtual void play(const Vec3 &xyz, SFXBuffer* buffer = NULL) {} + virtual void reallyPlayNow(const Vec3 &xyz, SFXBuffer* buffer = NULL) {} virtual void stop() {} virtual void reallyStopNow() {} virtual void pause() {} diff --git a/src/audio/sfx_base.hpp b/src/audio/sfx_base.hpp index f01479346..da601bbf1 100644 --- a/src/audio/sfx_base.hpp +++ b/src/audio/sfx_base.hpp @@ -64,9 +64,9 @@ public: virtual void setLoop(bool status) = 0; virtual void reallySetLoop(bool status) = 0; virtual void play() = 0; - virtual void reallyPlayNow() = 0; - virtual void play(const Vec3 &xyz) = 0; - virtual void reallyPlayNow(const Vec3 &xyz) = 0; + virtual void reallyPlayNow(SFXBuffer* buffer = NULL) = 0; + virtual void play(const Vec3 &xyz, SFXBuffer* buffer = NULL) = 0; + virtual void reallyPlayNow(const Vec3 &xyz, SFXBuffer* buffer = NULL) = 0; virtual void stop() = 0; virtual void reallyStopNow() = 0; virtual void pause() = 0; diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp index 4761e2c47..9cecda9dc 100644 --- a/src/audio/sfx_manager.cpp +++ b/src/audio/sfx_manager.cpp @@ -217,6 +217,15 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p) queueCommand(sfx_command); } // queue (Vec3) +//---------------------------------------------------------------------------- + +void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer) +{ + SFXCommand *sfx_command = new SFXCommand(command, sfx, p); + sfx_command->m_buffer = buffer; + queueCommand(sfx_command); +} // queue (Vec3) + //---------------------------------------------------------------------------- /** Adds a sound effect command with a float and a Vec3 parameter to the queue * of the sfx manager. Openal commands can sometimes cause a 5ms delay, so it @@ -340,7 +349,7 @@ void* SFXManager::mainLoop(void *obj) { case SFX_PLAY: current->m_sfx->reallyPlayNow(); break; case SFX_PLAY_POSITION: - current->m_sfx->reallyPlayNow(current->m_parameter); break; + current->m_sfx->reallyPlayNow(current->m_parameter, current->m_buffer); break; case SFX_STOP: current->m_sfx->reallyStopNow(); break; case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break; case SFX_RESUME: current->m_sfx->reallyResumeNow(); break; @@ -675,6 +684,22 @@ SFXBase* SFXManager::createSoundSource(const std::string &name, return createSoundSource( i->second, add_to_SFXList ); } // createSoundSource +//---------------------------------------------------------------------------- + +SFXBuffer* SFXManager::getBuffer(const std::string &name) +{ + std::map::iterator i = m_all_sfx_types.find(name); + if (i == m_all_sfx_types.end()) + { + Log::error("SFXManager", + "SFXManager::getBuffer could not find the " + "requested sound effect : '%s'.", name.c_str()); + return NULL; + } + + return i->second; +} + //---------------------------------------------------------------------------- /** Returns true if a sfx with the given name exists. * \param name The internal name of the sfx (not the name of the ogg file) diff --git a/src/audio/sfx_manager.hpp b/src/audio/sfx_manager.hpp index d9bfbf515..beb476395 100644 --- a/src/audio/sfx_manager.hpp +++ b/src/audio/sfx_manager.hpp @@ -122,6 +122,9 @@ private: /** The sound effect for which the command should be executed. */ SFXBase *m_sfx; + /** The sound buffer to play (null = no change) */ + SFXBuffer *m_buffer = NULL; + /** Stores music information for music commands. */ MusicInformation *m_music_information; @@ -232,12 +235,14 @@ private: public: static void create(); static void destroy(); - void queue(SFXCommands command, SFXBase *sfx=NULL); - void queue(SFXCommands command, SFXBase *sfx, float f); - void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p); - void queue(SFXCommands command, SFXBase *sfx, float f, const Vec3 &p); - void queue(SFXCommands command, MusicInformation *mi); - void queue(SFXCommands command, MusicInformation *mi, float f); + void queue(SFXCommands command, SFXBase *sfx=NULL); + void queue(SFXCommands command, SFXBase *sfx, float f); + void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p); + void queue(SFXCommands command, SFXBase *sfx, float f, const Vec3 &p); + void queue(SFXCommands command, MusicInformation *mi); + void queue(SFXCommands command, MusicInformation *mi, float f); + void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p, SFXBuffer* buffer); + // ------------------------------------------------------------------------ /** Static function to get the singleton sfx manager. */ static SFXManager *get() @@ -296,6 +301,9 @@ public: /** Returns the current position of the listener. */ Vec3 getListenerPos() const { return m_listener_position.getData(); } + // ------------------------------------------------------------------------ + + SFXBuffer* getBuffer(const std::string &name); }; #endif // HEADER_SFX_MANAGER_HPP diff --git a/src/audio/sfx_openal.cpp b/src/audio/sfx_openal.cpp index 652fd56c6..21368e1b5 100644 --- a/src/audio/sfx_openal.cpp +++ b/src/audio/sfx_openal.cpp @@ -365,7 +365,7 @@ void SFXOpenAL::play() //----------------------------------------------------------------------------- /** Plays this sound effect. */ -void SFXOpenAL::reallyPlayNow() +void SFXOpenAL::reallyPlayNow(SFXBuffer* buffer) { if (!SFXManager::get()->sfxAllowed()) return; if (m_status==SFX_NOT_INITIALISED) @@ -377,6 +377,18 @@ void SFXOpenAL::reallyPlayNow() if (m_status==SFX_UNKNOWN) return; } + if (buffer != NULL) + { + if (m_status == SFX_PLAYING || m_status == SFX_PAUSED) + reallyStopNow(); + + m_sound_buffer = buffer; + alSourcei(m_sound_source, AL_BUFFER, m_sound_buffer->getBufferID()); + + if (!SFXManager::checkError("attaching the buffer to the source")) + return; + } + alSourcePlay(m_sound_source); SFXManager::checkError("playing"); // Esp. with terrain sounds it can (very likely) happen that the status @@ -392,8 +404,11 @@ void SFXOpenAL::reallyPlayNow() /** This actually queues up the sfx in the sfx manager. It will be started * from a separate thread later (in this frame). */ -void SFXOpenAL::play(const Vec3 &position) +void SFXOpenAL::play(const Vec3 &position, SFXBuffer* buffer) { + if (m_owns_buffer && buffer != NULL) + assert(false); // sources that own a buffer cannot play any other buffer + if (m_status == SFX_UNKNOWN || !SFXManager::get()->sfxAllowed()) return; if(m_status==SFX_STOPPED || m_status==SFX_NOT_INITIALISED) @@ -405,16 +420,15 @@ void SFXOpenAL::play(const Vec3 &position) // - which can happen if the sfx thread had no time to actually start // it yet. m_status = SFX_PLAYING; - SFXManager::get()->queue(SFXManager::SFX_PLAY_POSITION, this, position); + SFXManager::get()->queue(SFXManager::SFX_PLAY_POSITION, this, position, buffer); } // play(Vec3) - //----------------------------------------------------------------------------- /** Plays this sound effect. */ -void SFXOpenAL::reallyPlayNow(const Vec3 &position) +void SFXOpenAL::reallyPlayNow(const Vec3 &position, SFXBuffer* buffer) { reallySetPosition(position); - reallyPlayNow(); + reallyPlayNow(buffer); } // reallyPlayNow(Vec3) //----------------------------------------------------------------------------- @@ -528,4 +542,6 @@ void SFXOpenAL::setRolloff(float rolloff) alSourcef (m_sound_source, AL_ROLLOFF_FACTOR, rolloff); } +//----------------------------------------------------------------------------- + #endif //if HAVE_OGGVORBIS diff --git a/src/audio/sfx_openal.hpp b/src/audio/sfx_openal.hpp index 10b1c0717..0d491b097 100644 --- a/src/audio/sfx_openal.hpp +++ b/src/audio/sfx_openal.hpp @@ -29,6 +29,7 @@ #endif #include "audio/sfx_base.hpp" #include "utils/leak_check.hpp" +#include "utils/cpp2011.hpp" /** * \brief OpenAL implementation of the abstract SFXBase interface @@ -81,11 +82,11 @@ public: virtual ~SFXOpenAL(); virtual void updatePlayingSFX(float dt); - virtual bool init(); - virtual void play(); - virtual void reallyPlayNow(); - virtual void play(const Vec3 &xyz); - virtual void reallyPlayNow(const Vec3 &xyz); + virtual bool init() OVERRIDE; + virtual void play() OVERRIDE; + virtual void reallyPlayNow(SFXBuffer* buffer = NULL) OVERRIDE; + virtual void play(const Vec3 &xyz, SFXBuffer* buffer = NULL) OVERRIDE; + virtual void reallyPlayNow(const Vec3 &xyz, SFXBuffer* buffer = NULL) OVERRIDE; virtual void setLoop(bool status); virtual void reallySetLoop(bool status); virtual void stop(); diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index d59706ab3..bf059c058 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -435,6 +435,11 @@ namespace UserConfigParams &m_multitouch_group, "A parameter in range [0, 0.5] that determines the zone that is " "considered as max value in steering button.")); + + PARAM_PREFIX FloatUserConfigParam m_multitouch_tilt_factor + PARAM_DEFAULT( FloatUserConfigParam(4.0f, "multitouch_tilt_factor", + &m_multitouch_group, + "A parameter that determines general accelerometer sensitivity.")); PARAM_PREFIX FloatUserConfigParam m_multitouch_scale PARAM_DEFAULT( FloatUserConfigParam(1.1f, "multitouch_scale", diff --git a/src/graphics/stk_tex_manager.cpp b/src/graphics/stk_tex_manager.cpp index 4ea5ccd94..e1b7ede45 100644 --- a/src/graphics/stk_tex_manager.cpp +++ b/src/graphics/stk_tex_manager.cpp @@ -147,6 +147,12 @@ video::ITexture* STKTexManager::getTexture(const std::string& path, TexConfig* tc, bool no_upload, bool create_if_unfound) { + if (path.empty()) + { + Log::error("STKTexManager", "Texture name is empty."); + return NULL; + } + auto ret = m_all_textures.find(path); if (!no_upload && ret != m_all_textures.end()) return ret->second; diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index e604e6b82..9057b888e 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -1191,15 +1191,18 @@ EventPropagation InputManager::input(const SEvent& event) if (button->type != BUTTON_STEERING) continue; + + float factor = UserConfigParams::m_multitouch_tilt_factor; + factor = std::max(factor, 0.1f); if (UserConfigParams::m_multitouch_accelerometer == 1) { - button->axis_x = (float)-event.AccelerometerEvent.X / 5.0f; + button->axis_x = (float)-event.AccelerometerEvent.X / factor; device->handleControls(button); } else if (UserConfigParams::m_multitouch_accelerometer == 2) { - button->axis_x = (float)event.AccelerometerEvent.Y / 5.0f; + button->axis_x = (float)event.AccelerometerEvent.Y / factor; device->handleControls(button); } } diff --git a/src/karts/abstract_kart.hpp b/src/karts/abstract_kart.hpp index 71582aa4b..5bab9703c 100644 --- a/src/karts/abstract_kart.hpp +++ b/src/karts/abstract_kart.hpp @@ -45,6 +45,7 @@ class KartModel; class KartProperties; class Material; class Powerup; +class SFXBuffer; class Skidding; class SlipStream; class TerrainInfo; @@ -472,7 +473,8 @@ public: // ------------------------------------------------------------------------ /** Returns whether this kart is jumping. */ virtual bool isJumping() const = 0; - + // ------------------------------------------------------------------------ + virtual void playSound(SFXBuffer* buffer) = 0; }; // AbstractKart diff --git a/src/karts/controller/local_player_controller.cpp b/src/karts/controller/local_player_controller.cpp index 01eb0879f..2c8b96b47 100644 --- a/src/karts/controller/local_player_controller.cpp +++ b/src/karts/controller/local_player_controller.cpp @@ -65,11 +65,11 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart, // the right camera once per frame later. Camera *camera = Camera::createCamera(kart); m_camera_index = camera->getIndex(); - m_bzzt_sound = SFXManager::get()->createSoundSource("bzzt"); m_wee_sound = SFXManager::get()->createSoundSource("wee"); - m_ugh_sound = SFXManager::get()->createSoundSource("ugh"); - m_grab_sound = SFXManager::get()->createSoundSource("grab_collectable"); - m_full_sound = SFXManager::get()->createSoundSource("energy_bar_full"); + m_bzzt_sound = SFXManager::get()->getBuffer("bzzt"); + m_ugh_sound = SFXManager::get()->getBuffer("ugh"); + m_grab_sound = SFXManager::get()->getBuffer("grab_collectable"); + m_full_sound = SFXManager::get()->getBuffer("energy_bar_full"); // Attach Particle System Track *track = Track::getCurrentTrack(); @@ -97,11 +97,8 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart, */ LocalPlayerController::~LocalPlayerController() { - m_bzzt_sound->deleteSFX(); - m_wee_sound ->deleteSFX(); - m_ugh_sound ->deleteSFX(); - m_grab_sound->deleteSFX(); - m_full_sound->deleteSFX(); + m_wee_sound->deleteSFX(); + if (m_sky_particles_emitter) delete m_sky_particles_emitter; } // ~LocalPlayerController @@ -228,7 +225,7 @@ void LocalPlayerController::update(float dt) else if (!m_kart->getKartAnimation() && m_sound_schedule == true) { m_sound_schedule = false; - m_bzzt_sound->play(); + m_kart->playSound(m_bzzt_sound); } } // update @@ -246,7 +243,7 @@ void LocalPlayerController::displayPenaltyWarning() m->addMessage(_("Don't accelerate before go"), m_kart, 2.0f, GUIEngine::getSkin()->getColor("font::normal")); } - m_bzzt_sound->play(); + m_kart->playSound(m_bzzt_sound); } // displayPenaltyWarning //----------------------------------------------------------------------------- @@ -326,31 +323,31 @@ void LocalPlayerController::collectedItem(const Item &item, int add_info, if (old_energy < m_kart->getKartProperties()->getNitroMax() && m_kart->getEnergy() == m_kart->getKartProperties()->getNitroMax()) { - m_full_sound->play(); + m_kart->playSound(m_full_sound); } else if (race_manager->getCoinTarget() > 0 && old_energy < race_manager->getCoinTarget() && m_kart->getEnergy() == race_manager->getCoinTarget()) { - m_full_sound->play(); + m_kart->playSound(m_full_sound); } else { switch(item.getType()) { case Item::ITEM_BANANA: - m_ugh_sound->play(); + m_kart->playSound(m_ugh_sound); break; case Item::ITEM_BUBBLEGUM: //More sounds are played by the kart class //See Kart::collectedItem() - m_ugh_sound->play(); + m_kart->playSound(m_ugh_sound); break; case Item::ITEM_TRIGGER: // no default sound for triggers break; default: - m_grab_sound->play(); + m_kart->playSound(m_grab_sound); break; } } diff --git a/src/karts/controller/local_player_controller.hpp b/src/karts/controller/local_player_controller.hpp index 5493e1b2d..fbe327030 100644 --- a/src/karts/controller/local_player_controller.hpp +++ b/src/karts/controller/local_player_controller.hpp @@ -26,6 +26,7 @@ class AbstractKart; class ParticleEmitter; class SFXBase; +class SFXBuffer; /** PlayerKart manages control events from the player and moves * them to the Kart @@ -47,11 +48,11 @@ private: * camera object is managed in the Camera class, so no need to free it. */ int m_camera_index; - SFXBase *m_bzzt_sound; - SFXBase *m_wee_sound; - SFXBase *m_ugh_sound; - SFXBase *m_grab_sound; - SFXBase *m_full_sound; + SFXBase *m_wee_sound; + SFXBuffer *m_bzzt_sound; + SFXBuffer *m_ugh_sound; + SFXBuffer *m_grab_sound; + SFXBuffer *m_full_sound; virtual void steer(float, int) OVERRIDE; virtual void displayPenaltyWarning() OVERRIDE; diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index b14d0d0af..7c20cbce5 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -170,13 +170,18 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, } }*/ + m_horn_sound = SFXManager::get()->getBuffer("horn"); + m_crash_sounds[0] = SFXManager::get()->getBuffer("crash"); + m_crash_sounds[1] = SFXManager::get()->getBuffer("crash2"); + m_crash_sounds[2] = SFXManager::get()->getBuffer("crash3"); + m_goo_sound = SFXManager::get()->getBuffer("goo"); + m_boing_sound = SFXManager::get()->getBuffer("boing"); + m_engine_sound = SFXManager::get()->createSoundSource(m_kart_properties->getEngineSfxType()); - m_beep_sound = SFXManager::get()->createSoundSource( "horn" ); - m_crash_sound = SFXManager::get()->createSoundSource( "crash" ); - m_crash_sound2 = SFXManager::get()->createSoundSource( "crash2"); - m_crash_sound3 = SFXManager::get()->createSoundSource( "crash3"); - m_boing_sound = SFXManager::get()->createSoundSource( "boing" ); - m_goo_sound = SFXManager::get()->createSoundSource( "goo" ); + + for (int i = 0; i < EMITTER_COUNT; i++) + m_emitters[i] = SFXManager::get()->createSoundSource("crash"); + m_skid_sound = SFXManager::get()->createSoundSource( "skid" ); m_nitro_sound = SFXManager::get()->createSoundSource( "nitro" ); m_terrain_sound = NULL; @@ -201,13 +206,10 @@ void Kart::init(RaceManager::KartType type) if (type == RaceManager::KT_PLAYER) factor = std::min(1.0f, race_manager->getNumLocalPlayers()/2.0f); - m_goo_sound->setVolume(factor); + for (int i = 0; i < EMITTER_COUNT; i++) + m_emitters[i]->setVolume(factor); + m_skid_sound->setVolume(factor); - m_crash_sound->setVolume(factor); - m_crash_sound2->setVolume(factor); - m_crash_sound3->setVolume(factor); - m_boing_sound->setVolume(factor); - m_beep_sound->setVolume(factor); m_nitro_sound->setVolume(factor); } // if getNumLocalPlayers > 1 @@ -257,13 +259,11 @@ Kart::~Kart() }*/ m_engine_sound->deleteSFX(); - m_crash_sound ->deleteSFX(); - m_crash_sound2->deleteSFX(); - m_crash_sound3->deleteSFX(); m_skid_sound ->deleteSFX(); - m_goo_sound ->deleteSFX(); - m_beep_sound ->deleteSFX(); - m_boing_sound ->deleteSFX(); + + for (int i = 0; i < EMITTER_COUNT; i++) + m_emitters[i]->deleteSFX(); + m_nitro_sound ->deleteSFX(); delete m_kart_gfx; if(m_terrain_sound) m_terrain_sound->deleteSFX(); @@ -1028,8 +1028,8 @@ void Kart::collectedItem(Item *item, int add_info) m_kart_properties->getBubblegumSpeedFraction() , m_kart_properties->getBubblegumFadeInTime(), m_bubblegum_time); - m_goo_sound->setPosition(getXYZ()); - m_goo_sound->play(); + getNextEmitter()->play(getXYZ(), m_goo_sound); + // Play appropriate custom character sound playCustomSFX(SFXManager::CUSTOM_GOO); break; @@ -1360,12 +1360,10 @@ void Kart::update(float dt) } */ - m_beep_sound->setPosition ( getXYZ() ); - m_crash_sound->setPosition ( getXYZ() ); - m_crash_sound2->setPosition ( getXYZ() ); - m_crash_sound3->setPosition ( getXYZ() ); + for (int i = 0; i < EMITTER_COUNT; i++) + m_emitters[i]->setPosition(getXYZ()); + m_skid_sound->setPosition ( getXYZ() ); - m_boing_sound->setPosition ( getXYZ() ); m_nitro_sound->setPosition ( getXYZ() ); // Check if a kart is (nearly) upside down and not moving much --> @@ -2165,23 +2163,13 @@ void Kart::playCrashSFX(const Material* m, AbstractKart *k) // it's not already playing. if (isShielded() || (k != NULL && k->isShielded())) { - if (m_boing_sound->getStatus() != SFXBase::SFX_PLAYING) - m_boing_sound->play(getXYZ()); + getNextEmitter()->play(getXYZ(), m_boing_sound); } else { - if (m_crash_sound->getStatus() != SFXBase::SFX_PLAYING - && m_crash_sound2->getStatus() != SFXBase::SFX_PLAYING - && m_crash_sound3->getStatus() != SFXBase::SFX_PLAYING) - { - int idx = rand() % 3; - if (idx == 0) - m_crash_sound->play(getXYZ()); - else if (idx == 1) - m_crash_sound2->play(getXYZ()); - else - m_crash_sound3->play(getXYZ()); - } + int idx = rand() % CRASH_SOUND_COUNT; + SFXBuffer* buffer = m_crash_sounds[idx]; + getNextEmitter()->play(getXYZ(), buffer); } } // if lin_vel > 0.555 } // if m_bounce_back_time <= 0 @@ -2195,7 +2183,7 @@ void Kart::beep() // If the custom horn can't play (isn't defined) then play the default one if (!playCustomSFX(SFXManager::CUSTOM_HORN)) { - m_beep_sound->play(getXYZ()); + getNextEmitter()->play(getXYZ(), m_horn_sound); } } // beep @@ -2689,6 +2677,14 @@ void Kart::kartIsInRestNow() m_kart_model->setDefaultSuspension(); } // kartIsInRestNow +//----------------------------------------------------------------------------- + +SFXBase* Kart::getNextEmitter() +{ + m_emitter_id = (m_emitter_id + 1) % 3; + return m_emitters[m_emitter_id]; +} + //----------------------------------------------------------------------------- /** Updates the graphics model. It is responsible for positioning the graphical * chasses at an 'appropriate' position: typically, the physical model has @@ -2983,4 +2979,11 @@ const Vec3& Kart::getNormal() const return m_terrain_info->getNormal(); } // getNormal +// ------------------------------------------------------------------------ + +void Kart::playSound(SFXBuffer* buffer) +{ + getNextEmitter()->play(getXYZ(), buffer); +} + /* EOF */ diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 9440130f1..6353f2022 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -206,19 +206,21 @@ protected: float m_last_factor_engine_sound; std::vector m_custom_sounds; - SFXBase *m_beep_sound; + int m_emitter_id = 0; + static const int EMITTER_COUNT = 3; + SFXBase *m_emitters[EMITTER_COUNT]; SFXBase *m_engine_sound; - SFXBase *m_crash_sound; - SFXBase *m_crash_sound2; - SFXBase *m_crash_sound3; SFXBase *m_terrain_sound; SFXBase *m_nitro_sound; /** A pointer to the previous terrain sound needs to be saved so that an * 'older' sfx can be finished and an abrupt end of the sfx is avoided. */ SFXBase *m_previous_terrain_sound; SFXBase *m_skid_sound; - SFXBase *m_goo_sound; - SFXBase *m_boing_sound; + SFXBuffer *m_horn_sound; + static const int CRASH_SOUND_COUNT = 3; + SFXBuffer *m_crash_sounds[CRASH_SOUND_COUNT]; + SFXBuffer *m_goo_sound; + SFXBuffer *m_boing_sound; float m_time_last_crash; RaceManager::KartType m_type; @@ -473,7 +475,10 @@ public: // ------------------------------------------------------------------------ /** Returns whether this kart is jumping. */ virtual bool isJumping() const { return m_is_jumping; }; - + // ------------------------------------------------------------------------ + SFXBase* getNextEmitter(); + // ------------------------------------------------------------------------ + virtual void playSound(SFXBuffer* buffer); }; // Kart diff --git a/src/tracks/arena_graph.cpp b/src/tracks/arena_graph.cpp index d888e4c47..6fa3e6ac1 100644 --- a/src/tracks/arena_graph.cpp +++ b/src/tracks/arena_graph.cpp @@ -158,6 +158,18 @@ void ArenaGraph::loadNavmesh(const std::string &navmesh) } } } + const XMLNode* ht = xml->getNode("height-testing"); + if (ht) + { + float min = Graph::MIN_HEIGHT_TESTING; + float max = Graph::MAX_HEIGHT_TESTING; + ht->get("min", &min); + ht->get("max", &max); + for (unsigned i = 0; i < m_all_nodes.size(); i++) + { + m_all_nodes[i]->setHeightTesting(min, max); + } + } delete xml; } // loadNavmesh diff --git a/src/tracks/drive_graph.cpp b/src/tracks/drive_graph.cpp index e73b730fb..8155b2ab0 100644 --- a/src/tracks/drive_graph.cpp +++ b/src/tracks/drive_graph.cpp @@ -97,16 +97,24 @@ void DriveGraph::load(const std::string &quad_file_name, return; } + float min_height_testing = Graph::MIN_HEIGHT_TESTING; + float max_height_testing = Graph::MAX_HEIGHT_TESTING; // Each quad is part of the graph exactly once now. for (unsigned int i = 0; i < quad->getNumNodes(); i++) { const XMLNode *xml_node = quad->getNode(i); - if (xml_node->getName() != "quad") + if (!(xml_node->getName() == "quad" || xml_node->getName() == "height-testing")) { Log::warn("DriveGraph: Unsupported node type '%s' found in '%s' - ignored.", xml_node->getName().c_str(), filename.c_str()); continue; } + if (xml_node->getName() == "height-testing") + { + xml_node->get("min", &min_height_testing); + xml_node->get("max", &max_height_testing); + continue; + } // Note that it's not easy to do the reading of the parameters here // in quad, since the specification in the xml can contain references @@ -141,6 +149,11 @@ void DriveGraph::load(const std::string &quad_file_name, createQuad(p0, p1, p2, p3, m_all_nodes.size(), invisible, ai_ignore, false/*is_arena*/, ignored); } + for (unsigned i = 0; i < m_all_nodes.size(); i++) + { + m_all_nodes[i]->setHeightTesting(min_height_testing, + max_height_testing); + } delete quad; const XMLNode *xml = file_manager->createXMLTree(filename); diff --git a/src/tracks/graph.cpp b/src/tracks/graph.cpp index 117da8e72..704e78c0b 100644 --- a/src/tracks/graph.cpp +++ b/src/tracks/graph.cpp @@ -31,6 +31,8 @@ #include "utils/log.hpp" const int Graph::UNKNOWN_SECTOR = -1; +const float Graph::MIN_HEIGHT_TESTING = -1.0f; +const float Graph::MAX_HEIGHT_TESTING = 5.0f; Graph *Graph::m_graph = NULL; // ----------------------------------------------------------------------------- Graph::Graph() diff --git a/src/tracks/graph.hpp b/src/tracks/graph.hpp index 31ab048fb..54de20be0 100644 --- a/src/tracks/graph.hpp +++ b/src/tracks/graph.hpp @@ -103,6 +103,9 @@ private: public: static const int UNKNOWN_SECTOR; + // For 2d Quad + static const float MIN_HEIGHT_TESTING; + static const float MAX_HEIGHT_TESTING; // ------------------------------------------------------------------------ /** Returns the one instance of this object. It is possible that there * is no instance created (e.g. arena without navmesh) so we don't assert diff --git a/src/tracks/quad.cpp b/src/tracks/quad.cpp index 48b66035f..a8c4c9f30 100644 --- a/src/tracks/quad.cpp +++ b/src/tracks/quad.cpp @@ -17,6 +17,7 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "tracks/quad.hpp" +#include "tracks/graph.hpp" #include "utils/log.hpp" #include @@ -36,6 +37,8 @@ Quad::Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3, std::min(p2.getY(), p3.getY()) ); m_max_height = std::max ( std::max(p0.getY(), p1.getY()), std::max(p2.getY(), p3.getY()) ); + m_min_height_testing = Graph::MIN_HEIGHT_TESTING; + m_max_height_testing = Graph::MAX_HEIGHT_TESTING; } // Quad // ---------------------------------------------------------------------------- @@ -77,8 +80,8 @@ bool Quad::pointInside(const Vec3& p, bool ignore_vertical) const // with the minimum height of the quad (and not with the actual // height of the quad at the point where the kart is). if(!ignore_vertical && - (p.getY() - m_max_height > 5.0f || - p.getY() - m_min_height < -1.0f )) + (p.getY() - m_max_height > m_max_height_testing || + p.getY() - m_min_height < m_min_height_testing )) return false; // If a point is exactly on the line of two quads (e.g. between points diff --git a/src/tracks/quad.hpp b/src/tracks/quad.hpp index 2f046d3b3..396f618cf 100644 --- a/src/tracks/quad.hpp +++ b/src/tracks/quad.hpp @@ -58,11 +58,11 @@ private: /** The minimum height of the quad, used in case that several quads * are on top of each other when determining the sector a kart is on. */ - float m_min_height; + float m_min_height, m_min_height_testing; /** The maximum height of the quad, used together with m_min_height * to distinguish between quads which are on top of each other. */ - float m_max_height; + float m_max_height, m_max_height_testing; public: LEAK_CHECK() @@ -81,6 +81,12 @@ public: /** Returns the center of a quad. */ const Vec3& getCenter () const { return m_center; } // ------------------------------------------------------------------------ + void setHeightTesting(float min, float max) + { + m_min_height_testing = min; + m_max_height_testing = max; + } + // ------------------------------------------------------------------------ /** Returns the minimum height of a quad. */ float getMinHeight() const { return m_min_height; } // ------------------------------------------------------------------------ diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index b6b9fad50..1b2b5f51d 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -573,7 +573,10 @@ void Track::loadTrackInfo() if(xml_node) loadCurves(*xml_node); // Set the correct paths - m_screenshot = m_root+m_screenshot; + if (m_screenshot.length() > 0) + { + m_screenshot = m_root+m_screenshot; + } delete root; std::string dir = StringUtils::getPath(m_filename);