summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio.cpp29
-rw-r--r--src/common.hpp30
-rw-r--r--src/game/assets.cpp8
-rw-r--r--src/game/game.cpp50
-rw-r--r--src/game/game.hpp5
-rw-r--r--src/main.cpp2
-rw-r--r--src/render.cpp6
7 files changed, 129 insertions, 1 deletions
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 <http://www.gnu.org/licenses/>.
namespace audio {
static std::list<sf::Sound> playing_sounds;
+static std::list<ambient_t*> 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<v2f_t> *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 <typename T>
+T remap(T am, T ap, T bm, T bp, T x)
+{
+ return (x - am) * (bp - bm) / (ap - am) + bm;
+}
+
+template <typename T>
+T clamp(T x, T m, T p)
+{
+ if (x < m)
+ return m;
+ if (x > p)
+ return p;
+ return x;
+}
+
// Bilinear interpolation.
template <typename T>
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;