soundsource.cpp

Go to the documentation of this file.
00001 /* $Id: soundsource.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2006 - 2012 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 as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "global.hpp"
00017 
00018 
00019 #include "display.hpp"
00020 #include "foreach.hpp"
00021 #include "log.hpp"
00022 #include "serialization/string_utils.hpp"
00023 #include "sound.hpp"
00024 #include "soundsource.hpp"
00025 
00026 namespace soundsource {
00027 
00028 const unsigned DEFAULT_CHANCE           = 100;
00029 const unsigned DEFAULT_DELAY            = 1000;
00030 const unsigned DEFAULT_FULL_RANGE       = 3;
00031 const unsigned DEFAULT_FADE_RANGE       = 14;
00032 
00033 unsigned int positional_source::last_id = 0;
00034 
00035 manager::manager(const display &disp) :
00036     observer(),
00037     savegame_config(),
00038     sources_(),
00039     disp_(disp)
00040 {
00041     disp_.scroll_event().attach_handler(this);
00042     update_positions();
00043 }
00044 
00045 manager::~manager()
00046 {
00047     for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) {
00048         delete (*it).second;
00049     }
00050 
00051     sources_.clear();
00052 }
00053 
00054 void manager::handle_generic_event(const std::string &event_name)
00055 {
00056     if(event_name == "scrolled")
00057         update_positions();
00058 }
00059 
00060 void manager::add(const sourcespec &spec)
00061 {
00062     positional_source_iterator it;
00063 
00064     if((it = sources_.find(spec.id())) == sources_.end()) {
00065         sources_[spec.id()] = new positional_source(spec);
00066     } else {
00067         delete (*it).second;
00068         (*it).second = new positional_source(spec);
00069     }
00070 }
00071 
00072 void manager::remove(const std::string &id)
00073 {
00074     positional_source_iterator it;
00075 
00076     if((it = sources_.find(id)) == sources_.end())
00077         return;
00078     else {
00079         delete (*it).second;
00080         sources_.erase(it);
00081     }
00082 }
00083 
00084 void manager::update()
00085 {
00086     unsigned int time = SDL_GetTicks();
00087 
00088     for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) {
00089         (*it).second->update(time, disp_);
00090     }
00091 }
00092 
00093 void manager::update_positions()
00094 {
00095     unsigned int time = SDL_GetTicks();
00096 
00097     for(positional_source_iterator it = sources_.begin(); it != sources_.end(); ++it) {
00098         (*it).second->update_positions(time, disp_);
00099     }
00100 }
00101 
00102 void manager::write_sourcespecs(config& cfg) const
00103 {
00104     for(positional_source_const_iterator i = sources_.begin(); i != sources_.end(); ++i) {
00105         assert(i->second);
00106 
00107         config& child = cfg.add_child("sound_source");
00108         child["id"] = i->first;
00109         i->second->write_config(child);
00110     }
00111 }
00112 
00113 config manager::to_config() const
00114 {
00115     config cfg;
00116     write_sourcespecs(cfg);
00117     return cfg.child("sound_source");
00118 }
00119 
00120 positional_source::positional_source(const sourcespec &spec) :
00121     last_played_(0),
00122     min_delay_(spec.minimum_delay()),
00123     chance_(spec.chance()),
00124     loops_(spec.loops()),
00125     id_(last_id++),
00126     range_(spec.full_range()),
00127     faderange_(spec.fade_range()),
00128     check_fogged_(spec.check_fogged()),
00129     check_shrouded_(spec.check_shrouded()),
00130     files_(spec.files()),
00131     locations_(spec.get_locations())
00132 {
00133     assert(range_ > 0);
00134     assert(faderange_ > 0);
00135 }
00136 
00137 positional_source::~positional_source()
00138 {
00139     sound::reposition_sound(id_, DISTANCE_SILENT);
00140 }
00141 
00142 bool positional_source::is_global()
00143 {
00144     return locations_.empty();
00145 }
00146 
00147 void positional_source::update(unsigned int time, const display &disp)
00148 {
00149     if (time - last_played_ < unsigned(min_delay_) || sound::is_sound_playing(id_))
00150         return;
00151 
00152     int i = rand() % 100 + 1;
00153 
00154     if(i <= chance_) {
00155         last_played_ = time;
00156 
00157         // If no locations have been specified, treat the source as if
00158         // it was present everywhere on the map
00159         if(locations_.empty()) {
00160             sound::play_sound_positioned(files_, id_, loops_, 0);   // max volume
00161             return;
00162         }
00163 
00164         int distance_volume = DISTANCE_SILENT;
00165         for(std::vector<map_location>::iterator i = locations_.begin(); i != locations_.end(); ++i) {
00166             int v = calculate_volume(*i, disp);
00167             if(v < distance_volume) {
00168                 distance_volume = v;
00169             }
00170         }
00171 
00172         if(distance_volume >= DISTANCE_SILENT)
00173             return;
00174 
00175         sound::play_sound_positioned(files_, id_, loops_, distance_volume);
00176     }
00177 }
00178 
00179 void positional_source::update_positions(unsigned int time, const display &disp)
00180 {
00181     if(is_global()) {
00182         return;
00183     }
00184 
00185     int distance_volume = DISTANCE_SILENT;
00186     for(std::vector<map_location>::iterator i = locations_.begin(); i != locations_.end(); ++i) {
00187         int v = calculate_volume(*i, disp);
00188         if(v < distance_volume) {
00189             distance_volume = v;
00190         }
00191     }
00192 
00193     if(sound::is_sound_playing(id_)) {
00194         sound::reposition_sound(id_, distance_volume);
00195     } else {
00196         update(time, disp);
00197     }
00198 }
00199 
00200 int positional_source::calculate_volume(const map_location &loc, const display &disp)
00201 {
00202     assert(range_ > 0);
00203     assert(faderange_ > 0);
00204 
00205     if((check_shrouded_ && disp.shrouded(loc)) || (check_fogged_ && disp.fogged(loc)))
00206         return DISTANCE_SILENT;
00207 
00208     SDL_Rect area = disp.map_area();
00209     map_location center = disp.hex_clicked_on(area.x + area.w / 2, area.y + area.h / 2);
00210     int distance = distance_between(loc, center);
00211 
00212     if(distance <= range_) {
00213         return 0;
00214     }
00215 
00216     return static_cast<int>((((distance - range_)
00217             / static_cast<double>(faderange_)) * DISTANCE_SILENT));
00218 }
00219 
00220 void positional_source::write_config(config& cfg) const
00221 {
00222     cfg["sounds"] = files_;
00223     cfg["delay"] = min_delay_;
00224     cfg["chance"] = chance_;
00225     cfg["check_fogged"] = check_fogged_;
00226     cfg["check_shrouded"] = check_shrouded_;
00227     cfg["loop"] = loops_;
00228     cfg["full_range"] = range_;
00229     cfg["fade_range"] = faderange_;
00230     write_locations(locations_, cfg);
00231 }
00232 
00233 sourcespec::sourcespec(const config& cfg) :
00234     id_(cfg["id"]),
00235     files_(cfg["sounds"]),
00236     min_delay_(cfg["delay"].to_int(DEFAULT_DELAY)),
00237     chance_(cfg["chance"].to_int(DEFAULT_CHANCE)),
00238     loops_(cfg["loop"]),
00239     range_(cfg["full_range"].to_int(3)),
00240     faderange_(cfg["fade_range"].to_int(14)),
00241     check_fogged_(cfg["check_fogged"].to_bool(true)),
00242     check_shrouded_(cfg["check_shrouded"].to_bool(true)),
00243     locations_()
00244 {
00245     read_locations(cfg, locations_);
00246 }
00247 
00248 } // namespace soundsource
00249 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:10 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs