Changed logic responsible for determining volume of sound sources.
It's now based on hex distance.
This commit is contained in:
parent
3e0594928c
commit
3b9705905b
3 changed files with 64 additions and 70 deletions
|
@ -1604,6 +1604,7 @@ void event_handler::handle_event_command(const queued_event& event_info,
|
|||
std::string x = cfg["x"];
|
||||
std::string y = cfg["y"];
|
||||
std::string loop = cfg["loop"];
|
||||
std::string full_range = cfg["full_range"];
|
||||
|
||||
assert(state_of_game != NULL);
|
||||
|
||||
|
@ -1619,6 +1620,7 @@ void event_handler::handle_event_command(const queued_event& event_info,
|
|||
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));
|
||||
spec.full_range(lexical_cast_default<int>(full_range, 1));
|
||||
|
||||
if(play_fogged.empty()) {
|
||||
spec.check_fog(true);
|
||||
|
|
|
@ -14,25 +14,15 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "display.hpp"
|
||||
#include "pathutils.hpp"
|
||||
#include "sound.hpp"
|
||||
#include "soundsource.hpp"
|
||||
|
||||
|
||||
static int calculate_volume(int x, int y, const display &disp)
|
||||
{
|
||||
SDL_Rect area = disp.map_outside_area();
|
||||
|
||||
int dx = area.w / 2 - x; dx *= dx;
|
||||
int dy = area.h / 2 - y; dy *= dy;
|
||||
|
||||
// An obscure formula to calculate SDL_Mixer's "distance" based on the source's
|
||||
// distance from screen's center
|
||||
return maximum<int>(0, 128 * static_cast<int>(std::sqrt((double) (dx + dy)) / (std::sqrt((double) (area.w*area.w + area.h * area.h)))));
|
||||
}
|
||||
|
||||
namespace soundsource {
|
||||
|
||||
unsigned int positional_source::last_id = 0;
|
||||
|
@ -64,8 +54,7 @@ void manager::add(const sourcespec &spec)
|
|||
|
||||
if((it = _sources.find(spec.id)) == _sources.end()) {
|
||||
_sources[spec.id] = new positional_source(spec);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
delete (*it).second;
|
||||
(*it).second = new positional_source(spec);
|
||||
}
|
||||
|
@ -87,16 +76,18 @@ void manager::update()
|
|||
{
|
||||
unsigned int time = SDL_GetTicks();
|
||||
|
||||
for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it)
|
||||
for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) {
|
||||
(*it).second->update(time, _disp);
|
||||
}
|
||||
}
|
||||
|
||||
void manager::update_positions()
|
||||
{
|
||||
unsigned int time = SDL_GetTicks();
|
||||
|
||||
for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it)
|
||||
for(positional_source_iterator it = _sources.begin(); it != _sources.end(); ++it) {
|
||||
(*it).second->update_positions(time, _disp);
|
||||
}
|
||||
}
|
||||
|
||||
void manager::add_location(const std::string &id, const gamemap::location &loc)
|
||||
|
@ -111,83 +102,79 @@ void manager::add_location(const std::string &id, const gamemap::location &loc)
|
|||
|
||||
|
||||
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),
|
||||
: _last_played(0), _min_delay(spec.min_delay), _chance(spec.chance), _loops(spec.loops),
|
||||
_id(last_id++), _range(spec.range), _check_fogged(spec.check_fogged), _files(spec.files),
|
||||
_locations(spec.locations)
|
||||
{
|
||||
assert(_range > 0);
|
||||
}
|
||||
|
||||
void positional_source::update(unsigned int time, const display &disp)
|
||||
{
|
||||
if(time - _last_played < _min_delay || !_visible)
|
||||
if(time - _last_played < _min_delay || sound::is_sound_playing(_id))
|
||||
return;
|
||||
|
||||
_last_played = time;
|
||||
unsigned int i = rand() % 100 + 1;
|
||||
|
||||
|
||||
if(i <= _chance) {
|
||||
_last_played = time;
|
||||
|
||||
// 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, _loops, 0); // max volume
|
||||
sound::play_sound_positioned(_files, _id, _loops, 0); // max volume
|
||||
return;
|
||||
}
|
||||
|
||||
// SDL_Rect area = disp.map_outside_area();
|
||||
|
||||
int distance_volume = 256;
|
||||
int distance_volume = DISTANCE_SILENT;
|
||||
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).x, (*i).y)
|
||||
|| (!_play_fogged && disp.fogged((*i).x, (*i).y)))
|
||||
continue;
|
||||
else {*/
|
||||
// Finds the location with the lowest distance == highest volume
|
||||
int v = calculate_volume(locx, locy, disp);
|
||||
if(v < distance_volume)
|
||||
distance_volume = v;
|
||||
/* }*/
|
||||
int v = calculate_volume(*i, disp);
|
||||
if(v < distance_volume) {
|
||||
distance_volume = v;
|
||||
}
|
||||
}
|
||||
|
||||
if(!sound::is_sound_playing(last_id)) {
|
||||
sound::play_sound_positioned(_files, last_id, _loops, distance_volume);
|
||||
}
|
||||
if(distance_volume >= DISTANCE_SILENT)
|
||||
return;
|
||||
|
||||
sound::play_sound_positioned(_files, _id, _loops, distance_volume);
|
||||
}
|
||||
}
|
||||
|
||||
void positional_source::update_positions(unsigned int time, const display &disp)
|
||||
{
|
||||
const bool was_visible = _visible;
|
||||
SDL_Rect area = disp.map_outside_area();
|
||||
int distance_volume = DISTANCE_SILENT;
|
||||
for(std::vector<gamemap::location>::iterator i = _locations.begin(); i != _locations.end(); ++i) {
|
||||
if(disp.shrouded(*i) || (_check_fogged && disp.fogged(*i)))
|
||||
continue;
|
||||
|
||||
_visible = false;
|
||||
|
||||
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)
|
||||
|| (_check_fogged && disp.fogged(*i)))
|
||||
continue;
|
||||
else {
|
||||
_visible = true;
|
||||
if(!sound::is_sound_playing(last_id)) {
|
||||
if(!was_visible)
|
||||
_last_played = 0; // hack make the previously invisible source to play
|
||||
|
||||
update(time, disp);
|
||||
continue;
|
||||
}
|
||||
|
||||
sound::reposition_sound(last_id, calculate_volume(locx, locy, disp));
|
||||
int v = calculate_volume(*i, disp);
|
||||
if(v < distance_volume) {
|
||||
distance_volume = v;
|
||||
}
|
||||
}
|
||||
|
||||
if(!_visible)
|
||||
sound::stop_sound(last_id);
|
||||
if(sound::is_sound_playing(_id)) {
|
||||
sound::reposition_sound(_id, distance_volume);
|
||||
} else {
|
||||
update(time, disp);
|
||||
}
|
||||
}
|
||||
|
||||
int positional_source::calculate_volume(const gamemap::location &loc, const display &disp)
|
||||
{
|
||||
assert(_range > 0);
|
||||
|
||||
SDL_Rect area = disp.map_area();
|
||||
gamemap::location center = disp.hex_clicked_on(area.x + area.w / 2, area.y + area.h / 2);
|
||||
int distance = distance_between(loc, center);
|
||||
|
||||
if(distance <= _range) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int calced = static_cast<int>(( ( (distance - _range) / (double) _range) * DISTANCE_SILENT));
|
||||
return calced;
|
||||
}
|
||||
|
||||
void positional_source::add_location(const gamemap::location &loc)
|
||||
|
|
|
@ -40,9 +40,9 @@ class positional_source {
|
|||
unsigned int _min_delay;
|
||||
unsigned int _chance;
|
||||
unsigned int _loops;
|
||||
unsigned int _id;
|
||||
const unsigned int _id;
|
||||
unsigned int _range;
|
||||
bool _check_fogged;
|
||||
bool _visible;
|
||||
std::string _files;
|
||||
std::vector<gamemap::location> _locations;
|
||||
|
||||
|
@ -64,6 +64,8 @@ class positional_source {
|
|||
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);
|
||||
|
||||
int calculate_volume(const gamemap::location &loc, const display &disp);
|
||||
};
|
||||
|
||||
class manager : public events::observer {
|
||||
|
@ -103,17 +105,15 @@ class sourcespec {
|
|||
int chance;
|
||||
|
||||
int loops;
|
||||
int range;
|
||||
bool 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_)
|
||||
: id(id_), files(files_), min_delay(min_delay_), chance(chance_), loops(0), check_fogged(false)
|
||||
{
|
||||
loops = 0;
|
||||
check_fogged = false;
|
||||
|
||||
}
|
||||
|
||||
sourcespec& loop(int loops_) {
|
||||
|
@ -131,6 +131,11 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
sourcespec& full_range(int range_) {
|
||||
range = maximum<int>(1, range_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend class manager;
|
||||
friend class positional_source;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue