Use "named parameters" to specify sound source properties + some small tweaks.

This commit is contained in:
Karol Nowak 2008-03-13 19:57:33 +00:00
parent 7f9d7a2542
commit 45a126be5a
3 changed files with 120 additions and 63 deletions

View file

@ -1435,18 +1435,28 @@ void event_handler::handle_event_command(const queued_event& event_info,
if(!sounds.empty() && !delay.empty() && !chance.empty()) {
const std::vector<std::string>& vx = utils::split(x);
const std::vector<std::string>& vy = utils::split(y);
const int loops = lexical_cast_default<int>(loop, 0);
if(play_fogged.empty())
soundsources->add(id, sounds, lexical_cast<int>(delay), lexical_cast<int>(chance), loops);
else
soundsources->add(id, sounds, lexical_cast<int>(delay),
lexical_cast<int>(chance), loops, utils::string_bool(play_fogged));
if(vx.size() != vy.size()) {
lg::wml_error << "invalid number of sound source location coordinates";
return;
}
soundsource::sourcespec spec(id, sounds, lexical_cast_default<int>(delay, 1000), lexical_cast_default<int>(chance, 100));
spec.loop(lexical_cast_default<int>(loop, 0));
if(play_fogged.empty()) {
spec.check_fog(true);
} else {
spec.check_fog(utils::string_bool(play_fogged));
}
for(unsigned int i = 0; i < minimum(vx.size(), vy.size()); ++i) {
gamemap::location loc(lexical_cast<int>(vx[i]), lexical_cast<int>(vy[i]));
soundsources->add_location(id, loc);
spec.location(loc);
}
soundsources->add(spec);
}
}

View file

@ -35,7 +35,7 @@ static int calculate_volume(int x, int y, const display &disp)
namespace soundsource {
unsigned int manager::positional_source::last_id = 0;
unsigned int positional_source::last_id = 0;
manager::manager(const display &disp) : _disp(disp)
{
@ -58,16 +58,16 @@ void manager::handle_generic_event(const std::string &event_name)
update_positions();
}
void manager::add(const std::string &id, const std::string &files, int min_delay, int chance, int loop, bool play_fogged)
void manager::add(const sourcespec &spec)
{
positional_source_iterator it;
if((it = _sources.find(id)) == _sources.end()) {
_sources[id] = new positional_source(files, min_delay, chance, loop, play_fogged);
if((it = _sources.find(spec.id)) == _sources.end()) {
_sources[spec.id] = new positional_source(spec);
}
else {
delete (*it).second;
(*it).second = new positional_source(files, min_delay, chance, loop, play_fogged);
(*it).second = new positional_source(spec);
}
}
@ -110,14 +110,14 @@ void manager::add_location(const std::string &id, const gamemap::location &loc)
}
manager::positional_source::positional_source(const std::string &files, int min_delay, int chance, int loop, bool play_fogged)
: _last_played(0), _min_delay(min_delay), _chance(chance), _loop(loop),
_id(last_id++), _play_fogged(play_fogged), _visible(false),
_files(files)
positional_source::positional_source(const sourcespec &spec)
: _last_played(0), _min_delay(spec.min_delay), _chance(spec.chance), _loops(spec.loops),
_id(last_id++), _check_fogged(spec.check_fogged), _visible(false), _files(spec.files),
_locations(spec.locations)
{
}
void manager::positional_source::update(unsigned int time, const display &disp)
void positional_source::update(unsigned int time, const display &disp)
{
if(time - _last_played < _min_delay || !_visible)
return;
@ -130,14 +130,14 @@ void manager::positional_source::update(unsigned int time, const display &disp)
// If no locations have been specified, treat the source as if
// it was present everywhere on the map
if(_locations.size() == 0) {
sound::play_sound_positioned(_files, last_id, _loop, 0); // max volume
sound::play_sound_positioned(_files, last_id, _loops, 0); // max volume
return;
}
// SDL_Rect area = disp.map_outside_area();
int distance_volume = 256;
for(std::list<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
for(std::vector<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
int locx = disp.get_location_x(*i);
int locy = disp.get_location_y(*i);
/*
@ -153,24 +153,24 @@ void manager::positional_source::update(unsigned int time, const display &disp)
}
if(!sound::is_sound_playing(last_id)) {
sound::play_sound_positioned(_files, last_id, _loop, distance_volume);
sound::play_sound_positioned(_files, last_id, _loops, distance_volume);
}
}
}
void manager::positional_source::update_positions(unsigned int time, const display &disp)
void positional_source::update_positions(unsigned int time, const display &disp)
{
const bool was_visible = _visible;
SDL_Rect area = disp.map_outside_area();
_visible = false;
for(std::list<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
for(std::vector<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
int locx = disp.get_location_x(*i);
int locy = disp.get_location_y(*i);
if(disp.outside_area(area, locx, locy) || disp.shrouded(*i)
|| (!_play_fogged && disp.fogged(*i)))
|| (_check_fogged && disp.fogged(*i)))
continue;
else {
_visible = true;
@ -190,7 +190,7 @@ void manager::positional_source::update_positions(unsigned int time, const displ
sound::stop_sound(last_id);
}
void manager::positional_source::add_location(const gamemap::location &loc)
void positional_source::add_location(const gamemap::location &loc)
{
_locations.push_back(loc);
}

View file

@ -14,7 +14,6 @@
#ifndef SOUNDSOURCE_HPP_INCLUDED
#define SOUNDSOURCE_HPP_INCLUDED
#include <list>
#include <map>
#include <string>
#include <vector>
@ -26,43 +25,48 @@ class display;
namespace soundsource {
class sourcespec;
class manager;
/*
* Sound source is an object on a map (a location) which has one or more
* sounds effects associated with it, which are played randomly and with
* appropriate delays, when sound emiting object is visible on screen.
*/
class positional_source {
friend class manager;
unsigned int _last_played;
unsigned int _min_delay;
unsigned int _chance;
unsigned int _loops;
unsigned int _id;
bool _check_fogged;
bool _visible;
std::string _files;
std::vector<gamemap::location> _locations;
// Last assigned id; this can, of course, overflow, but I'd
// never expect to see 4 billions sound sources being created...
static unsigned int last_id;
// min_delay is a minimum time in seconds, which must pass before
// this sound source can be played again if it remains visible
//
// chance is a chance ;-) (in %) that the sound source will emit
// sound every second after the delay has passed or once the source
// becomes visible
positional_source(const sourcespec &spec);
void update(unsigned int time, const display &disp);
void update_positions(unsigned int time, const display &disp);
void add_location(const gamemap::location &loc);
void remove_location(const gamemap::location &loc);
void replace_location(const gamemap::location &oldloc, const gamemap::location &newloc);
};
class manager : public events::observer {
/*
* Sound source is an object on a map (a location) which has one or more
* sounds effects associated with it, which are played randomly and with
* appropriate delays, when sound emiting object is visible on screen.
*/
class positional_source {
unsigned int _last_played;
unsigned int _min_delay;
unsigned int _chance;
unsigned int _loop;
unsigned int _id;
bool _play_fogged;
bool _visible;
std::string _files;
std::list<gamemap::location> _locations;
// Last assigned id; this can, of course, overflow, but I'd
// never expect to see 4 billions sound sources being created...
static unsigned int last_id;
public:
// min_delay is a minimum time in seconds, which must pass before
// this sound source can be played again if it remains visible
//
// chance is a chance ;-) (in %) that the sound source will emit
// sound every second after the delay has passed or once the source
// becomes visible
positional_source(const std::string &files, int min_delay, int chance, int loop, bool play_fogged = false);
void update(unsigned int time, const display &disp);
void update_positions(unsigned int time, const display &disp);
void add_location(const gamemap::location &loc);
void remove_location(const gamemap::location &loc);
void replace_location(const gamemap::location &oldloc, const gamemap::location &newloc);
};
typedef std::map<std::string, positional_source *> positional_source_map;
typedef positional_source_map::iterator positional_source_iterator;
@ -81,13 +85,56 @@ public:
void handle_generic_event(const std::string &event_name);
// add or replace a soundsource
void add(const std::string &id, const std::string &files, int min_delay, int chance, int loop, bool play_fogged = false);
void add(const sourcespec &source);
void remove(const std::string &id);
void update();
void add_location(const std::string &id, const gamemap::location &loc);
};
} // namespace soundsource
/*
* A class encapsulating parameters, so that they're easier to pass around/extend/read.
*/
class sourcespec {
const std::string &id;
const std::string &files;
int min_delay;
int chance;
int loops;
int check_fogged;
std::vector<gamemap::location> locations;
public:
sourcespec(const std::string &id_, const std::string &files_, int min_delay_, int chance_)
: id(id), files(files_), min_delay(min_delay_), chance(chance_)
{
loops = 0;
check_fogged = false;
}
sourcespec& loop(int loops_) {
loops = loops_;
return *this;
}
sourcespec& check_fog(bool fogged) {
check_fogged = fogged;
return *this;
}
sourcespec& location(const gamemap::location &loc) {
locations.push_back(loc);
return *this;
}
friend class manager;
friend class positional_source;
};
} // namespace soundsourcespec
#endif