From 2f978ea5085678e98e391317cc50ac991cd726a8 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Mon, 26 Mar 2018 18:02:37 +0200 Subject: Ambient sounds. Using Tremulous sounds (CC-BY-SA) as placeholders for wind.ogg and water.ogg. --- src/audio.cpp | 29 +++++++++++++++++++++++++++++ src/common.hpp | 30 ++++++++++++++++++++++++++++++ src/game/assets.cpp | 8 ++++++++ src/game/game.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- src/game/game.hpp | 5 +++++ src/main.cpp | 2 ++ src/render.cpp | 6 ++++++ 7 files changed, 129 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/audio.cpp b/src/audio.cpp index 2f70fee..af6d24b 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -20,6 +20,7 @@ along with Minitrem. If not, see . namespace audio { static std::list playing_sounds; +static std::list ambient_sounds; void clean_sounds(void) { @@ -41,4 +42,32 @@ void sound_t::play(void) sound->play(); } +void ambient_t::load(const char *path) +{ + printf("load %s\n", path); + sound.openFromFile(path); + sound.setLoop(true); + ambient_sounds.push_back(this); +} + +void update_ambience(bool playing) +{ + for (ambient_t *ambient : ambient_sounds) { + if (!playing) { + if (ambient->playing) { + ambient->sound.stop(); + ambient->playing = false; + } + continue; + } + + if (!ambient->playing) { + ambient->sound.play(); + ambient->playing = true; + } + + ambient->sound.setVolume(ambient->weight * 100.0f); + } +} + } // namespace audio diff --git a/src/common.hpp b/src/common.hpp index 181139f..6042e08 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -260,6 +260,7 @@ namespace game { void start(void); void stop(void); void tick(ntime_t time); + void compute_ambience(render::state_t *render); void pause(void); void resume(void); @@ -389,11 +390,14 @@ namespace render { void render_line(v2f_t x0, v2f_t x1, sf::Color color); void debug_path(v2f_t x, std::list *path); + + rectf_t window_in_world_space(void); }; } namespace audio { void clean_sounds(void); + void update_ambience(bool playing); class sound_t { sf::SoundBuffer buffer; @@ -402,6 +406,15 @@ namespace audio { void load(const char *path); void play(void); }; + + class ambient_t { + public: + sf::Music sound; + bool playing = false; + float weight = 0.0f; + + void load(const char *path); + }; } extern render::state_t *debug_render; @@ -429,6 +442,23 @@ T lerp(T a, T b, T x) return a * (1 - x) + b * x; } +// Linear map between intervals. +template +T remap(T am, T ap, T bm, T bp, T x) +{ + return (x - am) * (bp - bm) / (ap - am) + bm; +} + +template +T clamp(T x, T m, T p) +{ + if (x < m) + return m; + if (x > p) + return p; + return x; +} + // Bilinear interpolation. template T bilerp(T a, T b, T c, T d, T x, T y) diff --git a/src/game/assets.cpp b/src/game/assets.cpp index ef7be9b..96199a6 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -24,6 +24,7 @@ spider_assets_t spider; nest_assets_t nest; fx_assets_t fx; deco_assets_t deco; +ambience_assets_t ambience; render::animated_texture_t unit_selected; render::animated_texture_t unit_selected_halo; @@ -73,6 +74,13 @@ void load(void) render::register_tile(TILE_WATER, "assets/tiles/water.png", NULL, 0.0f); 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; } } // namespace game::assets diff --git a/src/game/game.cpp b/src/game/game.cpp index 44ea95d..58b2c9d 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -194,7 +194,6 @@ void state_t::resume(void) paused = false; } - #define TIME_DELTA ((ntime_t)1000000000 / 60) void state_t::tick(ntime_t time_) @@ -234,6 +233,55 @@ void state_t::tick(ntime_t time_) } } +void state_t::compute_ambience(render::state_t *render) +{ + rectf_t area; + size_t plains = 0, cave = 0, water = 0, weird = 0; + float scale, volume; + + area = render->window_in_world_space(); + + // 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; + + point[0] = lerp(area[0][0], area[1][0], y / 4.0f); + point[1] = lerp(area[0][1], area[1][1], x / 4.0f); + + tile = world.get_tile(world::tile_index_t(point), world::SECTOR_FULL); + + switch (tile->type) { + case TILE_DIRT: + plains++; + break; + + case TILE_GRAVEL: + case TILE_STONE: + cave++; + break; + + case TILE_WATER: + water++; + break; + + case TILE_DIRT_RED: + case TILE_STONE_RED: + weird++; + break; + } + } + + scale = 1.0f / area.dims().len(); + volume = clamp(remap(0.002f, 0.08f, 0.0f, 1.0f, scale), 0.0f, 1.0f); + + 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; +} + die_t::die_t(size_t sides_) { sides = sides_; diff --git a/src/game/game.hpp b/src/game/game.hpp index 85e3849..8486412 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -77,11 +77,16 @@ 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 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/main.cpp b/src/main.cpp index ea0092d..20110e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,8 +68,10 @@ int main() window.clear(); render.begin_frame(now, dt); render.render(&game); + game.compute_ambience(&render); interface.render_to(&render); audio::clean_sounds(); + audio::update_ambience(!game.paused); render.end_frame(); } diff --git a/src/render.cpp b/src/render.cpp index 7a798ab..8d4949b 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -194,6 +194,12 @@ static rectf_t window_bounds(sf::RenderWindow *window) return bounds; } +// NOTE: this includes the margin +rectf_t state_t::window_in_world_space(void) +{ + return window_bounds(window); +} + void state_t::render(game::state_t *game) { rectf_t bounds; -- cgit