From d72e8d61de2f7efba3685dda2dc52b31f64f8a6e Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Sat, 31 Mar 2018 16:04:04 +0200 Subject: 3D audio. --- src/audio.cpp | 46 +++++++++++++++++++++++++++++++++++----------- src/common.hpp | 10 ++++++++-- src/game/assets.cpp | 19 ++++++++++--------- src/game/game.cpp | 36 +++++++++++++++++++++++------------- src/game/game.hpp | 14 +++++++++----- src/game/interface.cpp | 4 ++++ src/game/units.cpp | 4 ++-- src/main.cpp | 3 +-- src/math.hpp | 20 +++++++++++++++++--- 9 files changed, 109 insertions(+), 47 deletions(-) (limited to 'src') 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 playing_sounds; static std::list 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 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 @@ -268,6 +268,13 @@ public: return sf::Vector2((U)v[0], (U)v[1]); } + template + operator sf::Vector3() const + { + static_assert(N == 3, "conversion of vec_t with N != 3 to sf::Vector3"); + return sf::Vector3((U)v[0], (U)v[1], (U)v[2]); + } + template vec_t(sf::Vector2 b) { @@ -276,6 +283,15 @@ public: v[1] = b.y; } + template + vec_t(sf::Vector3 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 v) @@ -405,7 +421,5 @@ public: // Shorthands typedef vec_t v2f_t; -typedef vec_t v2d_t; +typedef vec_t v3f_t; typedef rect_t rectf_t; -typedef rect_t rectd_t; - -- cgit