soundsource.cpp

Go to the documentation of this file.
00001 /* $Id: soundsource.cpp 25631 2008-04-06 15:47:16Z ilor $ */
00002 /*
00003    Copyright (C) 2006 - 2008 by Karol Nowak <grzywacz@sul.uni.lodz.pl>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License version 2
00008    or at your option any later version.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 #include "global.hpp"
00016 
00017 #include <cassert>
00018 #include <cstdlib>
00019 
00020 #include "display.hpp"
00021 #include "pathutils.hpp"
00022 #include "sound.hpp"
00023 #include "soundsource.hpp"
00024 
00025 
00026 namespace soundsource {
00027 
00028 unsigned int positional_source::last_id = 0;
00029 
00030 manager::manager(const display &disp) : _disp(disp) 
00031 {
00032     _disp.scroll_event().attach_handler(this);
00033     update_positions();
00034 }
00035 
00036 manager::~manager()
00037 {
00038     for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) {
00039         delete (*it).second;
00040     }
00041 
00042     _sources.clear();
00043 }
00044 
00045 void manager::handle_generic_event(const std::string &event_name)
00046 {
00047     if(event_name == "scrolled")
00048         update_positions();
00049 }
00050 
00051 void manager::add(const sourcespec &spec)
00052 {
00053     positional_source_iterator it;
00054 
00055     if((it = _sources.find(spec.id)) == _sources.end()) {
00056         _sources[spec.id] = new positional_source(spec);
00057     } else {
00058         delete (*it).second;
00059         (*it).second = new positional_source(spec);
00060     }
00061 }
00062 
00063 void manager::remove(const std::string &id)
00064 {
00065     positional_source_iterator it;
00066 
00067     if((it = _sources.find(id)) == _sources.end())
00068         return;
00069     else {
00070         delete (*it).second;
00071         _sources.erase(it);
00072     }
00073 }
00074 
00075 void manager::update()
00076 {
00077     unsigned int time = SDL_GetTicks();
00078 
00079     for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) {
00080         (*it).second->update(time, _disp);
00081     }
00082 }
00083 
00084 void manager::update_positions()
00085 {
00086     unsigned int time = SDL_GetTicks();
00087 
00088     for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) {
00089         (*it).second->update_positions(time, _disp);
00090     }
00091 }
00092 
00093 void manager::add_location(const std::string &id, const gamemap::location &loc)
00094 {
00095     positional_source_iterator it = _sources.find(id);
00096 
00097     if(it == _sources.end())
00098         return;
00099     else
00100         (*it).second->add_location(loc);
00101 }
00102 
00103 
00104 positional_source::positional_source(const sourcespec &spec) 
00105                 : _last_played(0), _min_delay(spec.min_delay), _chance(spec.chance), _loops(spec.loops),
00106                     _id(last_id++), _range(spec.range), _faderange(spec.faderange), 
00107                     _check_fogged(spec.check_fogged), _files(spec.files), _locations(spec.locations)
00108 {
00109     assert(_range > 0);
00110     assert(_faderange > 0);
00111 }
00112 
00113 positional_source::~positional_source()
00114 {
00115     sound::reposition_sound(_id, DISTANCE_SILENT);
00116 }
00117 
00118 void positional_source::update(unsigned int time, const display &disp)
00119 {
00120     if(time - _last_played < _min_delay || sound::is_sound_playing(_id))
00121         return;
00122 
00123     unsigned int i = rand() % 100 + 1;
00124 
00125     if(i <= _chance) {
00126         _last_played = time;
00127 
00128         // If no locations have been specified, treat the source as if
00129         // it was present everywhere on the map
00130         if(_locations.size() == 0) {
00131             sound::play_sound_positioned(_files, _id, _loops, 0);   // max volume
00132             return;
00133         }
00134 
00135         int distance_volume = DISTANCE_SILENT;
00136         for(std::vector<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
00137             int v = calculate_volume(*i, disp);
00138             if(v < distance_volume) {
00139                 distance_volume = v;
00140             }
00141         }
00142 
00143         if(distance_volume >= DISTANCE_SILENT)
00144             return;
00145 
00146         sound::play_sound_positioned(_files, _id, _loops, distance_volume);
00147     }
00148 }
00149 
00150 void positional_source::update_positions(unsigned int time, const display &disp)
00151 {
00152     int distance_volume = DISTANCE_SILENT;
00153     for(std::vector<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
00154         if(disp.shrouded(*i) || (_check_fogged && disp.fogged(*i)))
00155             continue;
00156 
00157         int v = calculate_volume(*i, disp);
00158         if(v < distance_volume) {
00159             distance_volume = v;
00160         }
00161     }
00162 
00163     if(sound::is_sound_playing(_id)) {
00164         sound::reposition_sound(_id, distance_volume);
00165     } else {
00166         update(time, disp);
00167     }
00168 }
00169 
00170 int positional_source::calculate_volume(const gamemap::location &loc, const display &disp)
00171 {
00172     assert(_range > 0);
00173     assert(_faderange > 0);
00174 
00175     SDL_Rect area = disp.map_area();
00176     gamemap::location center = disp.hex_clicked_on(area.x + area.w / 2, area.y + area.h / 2);
00177     size_t distance = distance_between(loc, center);
00178 
00179     if(distance <= _range) {
00180         return 0;
00181     }
00182 
00183     return static_cast<int>(( ( (distance - _range) / (double) _faderange) * DISTANCE_SILENT));
00184 }
00185 
00186 void positional_source::add_location(const gamemap::location &loc)
00187 {
00188     _locations.push_back(loc);
00189 }
00190 
00191 } // namespace soundsource
00192 

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs