123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // SuperTux
- // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
- // 2023 mrkubax10 <mrkubax10@onet.pl>
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- #include "object/ambient_sound.hpp"
- #include <limits>
- #include "audio/sound_manager.hpp"
- #include "audio/sound_source.hpp"
- #include "editor/editor.hpp"
- #include "object/player.hpp"
- #include "supertux/sector.hpp"
- #include "util/reader_mapping.hpp"
- #include "video/drawing_context.hpp"
- AmbientSound::AmbientSound(const ReaderMapping& mapping) :
- MovingObject(mapping),
- ExposedObject<AmbientSound, scripting::AmbientSound>(this),
- m_sample(),
- m_sound_source(),
- m_radius(),
- m_radius_in_px(),
- m_volume(),
- m_has_played_sound(false)
- {
- m_col.m_group = COLGROUP_DISABLED;
- float w, h;
- mapping.get("x", m_col.m_bbox.get_left(), 0.0f);
- mapping.get("y", m_col.m_bbox.get_top(), 0.0f);
- mapping.get("width" , w, 32.0f);
- mapping.get("height", h, 32.0f);
- m_col.m_bbox.set_size(w, h);
- mapping.get("radius", m_radius, 1.0f);
- mapping.get("sample", m_sample, "");
- mapping.get("volume", m_volume, 1.0f);
- m_radius_in_px = m_radius*32.0f;
- prepare_sound_source();
- }
- AmbientSound::AmbientSound(const Vector& pos, float radius, float vol, const std::string& file) :
- ExposedObject<AmbientSound, scripting::AmbientSound>(this),
- m_sample(file),
- m_sound_source(),
- m_radius(radius),
- m_radius_in_px(m_radius*32.0f),
- m_volume(vol),
- m_has_played_sound(false)
- {
- m_col.m_group = COLGROUP_DISABLED;
- m_col.m_bbox.set_pos(pos);
- m_col.m_bbox.set_size(32, 32);
- prepare_sound_source();
- }
- AmbientSound::~AmbientSound()
- {
- stop_looping_sounds();
- }
- ObjectSettings
- AmbientSound::get_settings()
- {
- ObjectSettings result = MovingObject::get_settings();
- result.add_sound(_("Sound"), &m_sample, "sample");
- result.add_float(_("Radius (in tiles)"), &m_radius, "radius");
- result.add_float(_("Volume"), &m_volume, "volume");
- result.reorder({"sample", "radius", "volume", "region", "name", "x", "y", "width", "height"});
- return result;
- }
- #ifndef SCRIPTING_API
- void
- AmbientSound::set_pos(const Vector& pos)
- {
- MovingObject::set_pos(pos);
- }
- #endif
- void
- AmbientSound::set_pos(float x, float y)
- {
- m_col.m_bbox.set_pos(Vector(x, y));
- }
- float
- AmbientSound::get_pos_x() const
- {
- return m_col.m_bbox.get_left();
- }
- float
- AmbientSound::get_pos_y() const
- {
- return m_col.m_bbox.get_top();
- }
- HitResponse
- AmbientSound::collision(GameObject& other, const CollisionHit& hit_)
- {
- return ABORT_MOVE;
- }
- void
- AmbientSound::draw(DrawingContext& context)
- {
- if (Editor::is_active())
- context.color().draw_filled_rect(m_col.m_bbox, Color(0.0f, 0.0f, 1.0f, 0.6f),
- 0.0f, LAYER_OBJECTS);
- }
- void
- AmbientSound::stop_looping_sounds()
- {
- if (m_sound_source)
- m_sound_source->stop(false);
- }
- void
- AmbientSound::play_looping_sounds()
- {
- if (Editor::is_active())
- return;
- m_sound_source->play();
- }
- void
- AmbientSound::update(float dt_sec)
- {
- const Player* const nearest_player = Sector::get().get_nearest_player(get_bbox().get_middle());
- if (!nearest_player)
- return;
- const Rectf& player_bbox = nearest_player->get_bbox();
- const Vector player_center = player_bbox.get_middle();
- if (get_bbox().overlaps(player_bbox))
- m_sound_source->set_gain(m_volume);
- else
- {
- float player_distance = m_radius+1;
- if (player_center.x >= get_bbox().get_left() && player_center.x <= get_bbox().get_right())
- player_distance = player_center.y < get_bbox().get_top() ? get_bbox().get_top() - player_center.y : player_center.y - get_bbox().get_bottom();
- else if (player_center.y >= get_bbox().get_top() && player_center.y <= get_bbox().get_bottom())
- player_distance = player_center.x < get_bbox().get_left() ? get_bbox().get_left() - player_center.x : player_center.x - get_bbox().get_right();
- else if (player_center.x <= get_bbox().get_left() && player_center.y <= get_bbox().get_top())
- player_distance = glm::distance(player_center, get_bbox().p1());
- else if (player_center.x >= get_bbox().get_right() && player_center.y <= get_bbox().get_top())
- player_distance = glm::distance(player_center, get_bbox().p1() + Vector(get_bbox().get_width(), 0));
- else if (player_center.x <= get_bbox().get_left() && player_center.y >= get_bbox().get_bottom())
- player_distance = glm::distance(player_center, get_bbox().p1() + Vector(0, get_bbox().get_height()));
- else if (player_center.x >= get_bbox().get_right() && player_center.y >= get_bbox().get_bottom())
- player_distance = glm::distance(player_center, get_bbox().p2());
- m_sound_source->set_gain(std::max(m_radius_in_px - player_distance, 0.0f) / m_radius_in_px * m_volume);
- }
- if (!m_has_played_sound)
- {
- m_sound_source->play();
- m_has_played_sound = true;
- }
- }
- void
- AmbientSound::prepare_sound_source()
- {
- if (Editor::is_active())
- return;
- if (m_sample.empty())
- {
- remove_me();
- return;
- }
- try
- {
- m_sound_source = SoundManager::current()->create_sound_source(m_sample);
- if (!m_sound_source)
- throw std::runtime_error("file not found");
- m_sound_source->set_gain(0);
- m_sound_source->set_looping(true);
- m_sound_source->set_relative(true);
- }
- catch(const std::exception& e)
- {
- log_warning << "Couldn't load '" << m_sample << "': " << e.what() << std::endl;
- m_sound_source.reset();
- remove_me();
- }
- }
- /* EOF */
|