summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2018-03-31 16:04:04 +0200
committerPaweł Redman <pawel.redman@gmail.com>2018-03-31 16:04:04 +0200
commitd72e8d61de2f7efba3685dda2dc52b31f64f8a6e (patch)
tree2cda01dcc5b0e17fcf109469ac99296c2212346b /src
parentd87217dffc1582b8dbed10da62b3b4d3f7b511de (diff)
3D audio.
Diffstat (limited to 'src')
-rw-r--r--src/audio.cpp46
-rw-r--r--src/common.hpp10
-rw-r--r--src/game/assets.cpp19
-rw-r--r--src/game/game.cpp36
-rw-r--r--src/game/game.hpp14
-rw-r--r--src/game/interface.cpp4
-rw-r--r--src/game/units.cpp4
-rw-r--r--src/main.cpp3
-rw-r--r--src/math.hpp20
9 files changed, 109 insertions, 47 deletions
diff --git a/src/audio.cpp b/src/audio.cpp
index ff4fcd3..b806959 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -22,13 +22,6 @@ namespace audio {
static std::list<sf::Sound> playing_sounds;
static std::list<ambient_t*> ambient_sounds;
-void clean_sounds(void)
-{
- playing_sounds.remove_if( [](sf::Sound &sound) {
- return sound.getStatus() == sf::Sound::Stopped;
- });
-}
-
void sound_t::load(const char *path)
{
printf("load %s\n", path);
@@ -45,6 +38,19 @@ void sound_t::play(void)
auto sound = playing_sounds.emplace(playing_sounds.end());
sound->setBuffer(sounds[rand() % sounds.size()]);
sound->setVolume(volume * 100.0f);
+ sound->setRelativeToListener(true); // disable spatialization
+ sound->play();
+}
+
+void sound_t::play_3d(v2f_t x)
+{
+ if (!sounds.size())
+ return;
+
+ auto sound = playing_sounds.emplace(playing_sounds.end());
+ sound->setBuffer(sounds[rand() % sounds.size()]);
+ sound->setVolume(volume * 100.0f);
+ sound->setPosition(x[0], x[1], 0.0f);
sound->play();
}
@@ -53,14 +59,28 @@ void ambient_t::load(const char *path)
printf("load %s\n", path);
sound.openFromFile(path);
sound.setLoop(true);
- sound.setRelativeToListener(true);
ambient_sounds.push_back(this);
}
-void update_ambience(bool playing)
+void update(v3f_t camera, bool paused)
{
+ // update 3D settings
+ // the listener is looking down at the XY plane with +X pointing right
+ // and +Y pointing down
+ sf::Listener::setPosition(camera);
+ sf::Listener::setDirection(0.0f, 0.0f, -1.0f);
+ sf::Listener::setUpVector(0.0f, 1.0f, 0.0f);
+
+ // remove sounds that finished playing from playing_sounds
+ playing_sounds.remove_if( [](sf::Sound &sound) {
+ return sound.getStatus() == sf::Sound::Stopped;
+ });
+
+ // update ambient sounds (weights set by game)
for (ambient_t *ambient : ambient_sounds) {
- if (!playing) {
+ v3f_t origin;
+
+ if (paused) {
if (ambient->playing) {
ambient->sound.stop();
ambient->playing = false;
@@ -73,7 +93,11 @@ void update_ambience(bool playing)
ambient->playing = true;
}
- ambient->sound.setVolume(ambient->weight * 100.0f);
+ origin[0] = ambient->origin[0];
+ origin[1] = ambient->origin[1];
+ origin[2] = 0.0f;
+ ambient->sound.setPosition(origin);
+ ambient->sound.setVolume(ambient->volume * ambient->weight * 100.0f);
}
}
diff --git a/src/common.hpp b/src/common.hpp
index 2b9b9ca..fcda5e5 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -340,7 +340,10 @@ namespace interface {
void start_following(void);
void stop_following(void);
+
public:
+ v3f_t camera_3d; // for audio
+
state_t(sf::RenderWindow *window_, game::state_t *game);
void tick(double dt);
void render_to(render::state_t *render);
@@ -428,8 +431,7 @@ namespace render {
}
namespace audio {
- void clean_sounds(void);
- void update_ambience(bool playing);
+ void update(v3f_t view, bool paused);
class sound_t {
std::vector<sf::SoundBuffer> sounds;
@@ -438,12 +440,16 @@ namespace audio {
float volume = 1.0f;
void load(const char *path);
void play(void);
+ void play_3d(v2f_t x);
};
class ambient_t {
public:
sf::Music sound;
bool playing = false;
+
+ float volume = 1.0f;
+ v2f_t origin = v2f_t(0.0f, 0.0f);
float weight = 0.0f;
void load(const char *path);
diff --git a/src/game/assets.cpp b/src/game/assets.cpp
index f0dddbf..a020bf6 100644
--- a/src/game/assets.cpp
+++ b/src/game/assets.cpp
@@ -24,7 +24,7 @@ spider_assets_t spider;
nest_assets_t nest;
fx_assets_t fx;
deco_assets_t deco;
-ambience_assets_t ambience;
+audio::ambient_t ambients[AMBIENT_COUNT];
render::animated_texture_t unit_selected;
render::animated_texture_t unit_selected_halo;
@@ -42,13 +42,14 @@ void load(void)
soldier.dead.load("assets/units/soldier/dead_", 1);
soldier.fire.load("assets/units/soldier/fire.ogg");
-
+ soldier.fire.volume = 4.0f;
+
soldier.step_stone.load("assets/units/soldier/step_stone_1.ogg");
soldier.step_stone.load("assets/units/soldier/step_stone_2.ogg");
soldier.step_stone.load("assets/units/soldier/step_stone_3.ogg");
soldier.step_stone.load("assets/units/soldier/step_stone_4.ogg");
soldier.step_stone.load("assets/units/soldier/step_stone_5.ogg");
- soldier.step_stone.volume = 0.4f;
+ soldier.step_stone.volume = 1.0f;
spider.idle.load("assets/units/spider/idle", 2, 2, 2);
spider.walking.load("assets/units/spider/walking", 2, 2, 2);
@@ -83,12 +84,12 @@ void load(void)
world::register_tile(TILE_GRAVEL, 0);
render::register_tile(TILE_GRAVEL, "assets/tiles/gravel.png", NULL, 0.0f);
- ambience.nexus.load("assets/ambience/nexus.ogg");
- ambience.chasm.load("assets/ambience/chasm.ogg");
- ambience.wind.load("assets/ambience/wind.ogg");
- ambience.water.load("assets/ambience/water.ogg");
-
- ambience.nexus.weight = 1.0f;
+ ambients[AMBIENT_NEXUS].load("assets/ambience/nexus.ogg");
+ ambients[AMBIENT_CHASM].load("assets/ambience/chasm.ogg");
+ ambients[AMBIENT_CHASM].volume = 4.0f;
+ ambients[AMBIENT_WIND].load("assets/ambience/wind.ogg");
+ ambients[AMBIENT_WATER].load("assets/ambience/water.ogg");
+ ambients[AMBIENT_WATER].volume = 0.2f;
}
} // namespace game::assets
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 79685cb..2818c0b 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -285,17 +285,24 @@ void state_t::tick(ntime_t time_)
void state_t::compute_ambience(render::state_t *render)
{
+ const size_t samples = 25;
rectf_t area;
- size_t plains = 0, cave = 0, water = 0, weird = 0;
- float scale, volume;
+ v2f_t origins[AMBIENT_COUNT];
+ size_t hits[AMBIENT_COUNT];
area = render->window_in_world_space();
+ for (size_t i = 0; i < AMBIENT_COUNT; i++) {
+ origins[i] = v2f_t(0, 0);
+ hits[i] = 0;
+ }
+
// resolution chosen arbitrarily
for (size_t y = 0; y < 5; y++)
for (size_t x = 0; x < 5; x++) {
v2f_t point;
world::tile_t *tile;
+ int type;
point[0] = lerp(area[0][0], area[1][0], y / 4.0f);
point[1] = lerp(area[0][1], area[1][1], x / 4.0f);
@@ -304,32 +311,35 @@ void state_t::compute_ambience(render::state_t *render)
switch (tile->type) {
case TILE_DIRT:
- plains++;
+ type = AMBIENT_WIND;
break;
case TILE_GRAVEL:
case TILE_STONE:
- cave++;
+ type = AMBIENT_CHASM;
break;
case TILE_WATER:
- water++;
+ type = AMBIENT_WATER;
break;
case TILE_DIRT_RED:
case TILE_STONE_RED:
- weird++;
+ type = AMBIENT_NEXUS;
break;
+
+ default:
+ continue;
}
- }
- scale = 1.0f / area.dims().len();
- volume = clamp(remap(0.002f, 0.05f, 0.0f, 1.0f, scale), 0.0f, 1.0f);
+ origins[type] += point;
+ hits[type]++;
+ }
- assets::ambience.wind.weight = plains / 25.0f * volume;
- assets::ambience.chasm.weight = cave / 25.0f * volume;
- assets::ambience.water.weight = water / 25.0f * volume;
- assets::ambience.nexus.weight = weird / 25.0f * volume;
+ for (size_t i = 0; i < AMBIENT_COUNT; i++) {
+ assets::ambients[i].origin = origins[i] / hits[i];
+ assets::ambients[i].weight = (float)hits[i] / samples;
+ }
}
die_t::die_t(size_t sides_)
diff --git a/src/game/game.hpp b/src/game/game.hpp
index bb2ce69..331c1d1 100644
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -41,6 +41,14 @@ namespace game {
CF_BODY_SMALL = 8,
CF_WATER = 16
};
+
+ enum {
+ AMBIENT_NEXUS,
+ AMBIENT_CHASM,
+ AMBIENT_WIND,
+ AMBIENT_WATER,
+ AMBIENT_COUNT
+ };
extern size_t selection_cookie;
@@ -77,16 +85,12 @@ namespace game {
render::animated_texture_t wart;
} deco_assets_t;
- typedef struct {
- audio::ambient_t nexus, chasm, wind, water;
- } ambience_assets_t;
-
extern soldier_assets_t soldier;
extern spider_assets_t spider;
extern nest_assets_t nest;
extern fx_assets_t fx;
extern deco_assets_t deco;
- extern ambience_assets_t ambience;
+ extern audio::ambient_t ambients[AMBIENT_COUNT];
extern render::animated_texture_t unit_selected;
extern render::animated_texture_t unit_selected_halo;
extern render::animated_texture_t move_marker;
diff --git a/src/game/interface.cpp b/src/game/interface.cpp
index d3ef661..25d256c 100644
--- a/src/game/interface.cpp
+++ b/src/game/interface.cpp
@@ -165,6 +165,10 @@ void state_t::tick(double dt)
window->setView(sf::View(view_center, view_size));
}
+ camera_3d[0] = view_center[0];
+ camera_3d[1] = view_center[1];
+ camera_3d[2] = view_scale;
+
mouse = sf::Mouse::getPosition(*window);
wmouse = window->mapPixelToCoords(sf::Mouse::getPosition(*window));
diff --git a/src/game/units.cpp b/src/game/units.cpp
index 30cfdd5..47e729c 100644
--- a/src/game/units.cpp
+++ b/src/game/units.cpp
@@ -354,7 +354,7 @@ void unit_soldier_t::shoot(v2f_t aim)
flash->place(&game->world);
last_attack = game->now;
- assets::soldier.fire.play();
+ assets::soldier.fire.play_3d(x);
//target->damage(3, this); FIXME
}
@@ -458,7 +458,7 @@ void unit_soldier_t::on_think(void)
if (move.moving && (x - move.last_step).len() > 0.5f) {
move.last_step = x;
- assets::soldier.step_stone.play();
+ assets::soldier.step_stone.play_3d(x);
}
}
diff --git a/src/main.cpp b/src/main.cpp
index 20110e5..9af2736 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -70,8 +70,7 @@ int main()
render.render(&game);
game.compute_ambience(&render);
interface.render_to(&render);
- audio::clean_sounds();
- audio::update_ambience(!game.paused);
+ audio::update(interface.camera_3d, game.paused);
render.end_frame();
}
diff --git a/src/math.hpp b/src/math.hpp
index dc077e1..9b909cf 100644
--- a/src/math.hpp
+++ b/src/math.hpp
@@ -269,6 +269,13 @@ public:
}
template <typename U>
+ operator sf::Vector3<U>() const
+ {
+ static_assert(N == 3, "conversion of vec_t with N != 3 to sf::Vector3");
+ return sf::Vector3<U>((U)v[0], (U)v[1], (U)v[2]);
+ }
+
+ template <typename U>
vec_t(sf::Vector2<U> b)
{
static_assert(N == 2, "conversion of sf::Vector2 to vec_t with N != 2");
@@ -276,6 +283,15 @@ public:
v[1] = b.y;
}
+ template <typename U>
+ vec_t(sf::Vector3<U> b)
+ {
+ static_assert(N == 3, "conversion of sf::Vector2 to vec_t with N != 3");
+ v[0] = b.x;
+ v[1] = b.y;
+ v[2] = b.z;
+ }
+
// Compatibility with iostream
friend std::ostream& operator<<(std::ostream& stream, vec_t<T, N> v)
@@ -405,7 +421,5 @@ public:
// Shorthands
typedef vec_t<float, 2> v2f_t;
-typedef vec_t<double, 2> v2d_t;
+typedef vec_t<float, 3> v3f_t;
typedef rect_t<float, 2> rectf_t;
-typedef rect_t<double, 2> rectd_t;
-