Skip to content

Commit

Permalink
Volume change on ambient sounds based on proximity to sound tiles
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanmoffat committed May 13, 2022
1 parent ab1b045 commit ba4c6df
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
28 changes: 28 additions & 0 deletions EOLib/Domain/Extensions/MapExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using EOLib.Domain.Map;
using EOLib.IO.Map;
using System;

namespace EOLib.Domain.Extensions
{
public static class MapExtensions
{
public static int GetDistanceToClosestTileSpec(this IMapFile map, TileSpec spec, MapCoordinate source)
{
var shortestDistance = int.MaxValue;
for (int row = 0; row < map.Properties.Height; row++)
{
for (int col = 0; col < map.Properties.Width; col++)
{
if (map.Tiles[row, col] != spec)
continue;

var distance = Math.Abs(source.X - col) + Math.Abs(source.Y - row);
if (distance < shortestDistance)
shortestDistance = distance;
}
}

return shortestDistance;
}
}
}
26 changes: 19 additions & 7 deletions EndlessClient/Audio/SfxPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace EndlessClient.Audio
public sealed class SfxPlayer : ISfxPlayer
{
private readonly IContentProvider _contentProvider;
private SoundEffectInstance _activeSfx;
private SoundEffectInstance _loopingSfx;

public SfxPlayer(IContentProvider contentProvider)
{
Expand Down Expand Up @@ -39,20 +39,30 @@ public void PlayGuitarNote(int index)

public void PlayLoopingSfx(SoundEffectID id)
{
if (_activeSfx != null && _activeSfx.State != SoundState.Stopped)
if (_loopingSfx != null && _loopingSfx.State != SoundState.Stopped)
return;

StopLoopingSfx();

_activeSfx = _contentProvider.SFX[id].CreateInstance();
_activeSfx.IsLooped = true;
_activeSfx.Play();
_loopingSfx = _contentProvider.SFX[id].CreateInstance();
_loopingSfx.IsLooped = true;
_loopingSfx.Volume = 0.5f;
_loopingSfx.Play();
}

public void SetLoopingSfxVolume(float volume)
{
if (volume < 0 || volume > 1)
throw new ArgumentException($"Volume {volume} must be between 0 and 1", nameof(volume));

if (_loopingSfx != null)
_loopingSfx.Volume = volume;
}

public void StopLoopingSfx()
{
_activeSfx?.Stop();
_activeSfx?.Dispose();
_loopingSfx?.Stop();
_loopingSfx?.Dispose();
}

public void Dispose()
Expand All @@ -71,6 +81,8 @@ public interface ISfxPlayer : IDisposable

void PlayLoopingSfx(SoundEffectID id);

void SetLoopingSfxVolume(float volume);

void StopLoopingSfx();
}
}
24 changes: 22 additions & 2 deletions EndlessClient/Rendering/Character/CharacterRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using EndlessClient.Rendering.Sprites;
using EndlessClient.UIControls;
using EOLib;
using EOLib.Config;
using EOLib.Domain.Character;
using EOLib.Domain.Extensions;
using EOLib.Domain.Map;
Expand Down Expand Up @@ -38,7 +39,9 @@ public class CharacterRenderer : DrawableGameComponent, ICharacterRenderer
private readonly IGameStateProvider _gameStateProvider;
private readonly ICurrentMapProvider _currentMapProvider;
private readonly IUserInputProvider _userInputProvider;
private readonly IConfigurationProvider _configurationProvider;
private readonly ISfxPlayer _sfxPlayer;

private readonly IEffectRenderer _effectRenderer;

private EOLib.Domain.Character.Character _character;
Expand Down Expand Up @@ -95,6 +98,7 @@ public CharacterRenderer(INativeGraphicsManager nativeGraphicsmanager,
IGameStateProvider gameStateProvider,
ICurrentMapProvider currentMapProvider,
IUserInputProvider userInputProvider,
IConfigurationProvider configurationProvider,
ISfxPlayer sfxPlayer)
: base(game)
{
Expand All @@ -111,6 +115,7 @@ public CharacterRenderer(INativeGraphicsManager nativeGraphicsmanager,
_gameStateProvider = gameStateProvider;
_currentMapProvider = currentMapProvider;
_userInputProvider = userInputProvider;
_configurationProvider = configurationProvider;
_sfxPlayer = sfxPlayer;

_effectRenderer = new EffectRenderer(nativeGraphicsmanager, _sfxPlayer, this);
Expand Down Expand Up @@ -183,7 +188,8 @@ public override void Update(GameTime gameTime)

if (_gameStateProvider.CurrentState == GameStates.PlayingTheGame)
{
UpdateNameLabel(gameTime);
UpdateNameLabel();
UpdateAmbientNoiseVolume();

if (DrawArea.Contains(_userInputProvider.CurrentMouseState.Position))
{
Expand Down Expand Up @@ -341,7 +347,7 @@ private int GetMainCharacterOffsetY()
return _renderOffsetCalculator.CalculateOffsetY(_characterProvider.MainCharacter.RenderProperties);
}

private void UpdateNameLabel(GameTime gameTime)
private void UpdateNameLabel()
{
if (_gameStateProvider.CurrentState != GameStates.PlayingTheGame ||
_healthBarRenderer == null ||
Expand Down Expand Up @@ -383,6 +389,20 @@ private Vector2 GetNameLabelPosition()
TopPixelWithOffset - 8 - _nameLabel.ActualHeight);
}

// todo: find a better place to put this
private void UpdateAmbientNoiseVolume()
{
if (_currentMapProvider.CurrentMap.Properties.AmbientNoise <= 0 || !_configurationProvider.SoundEnabled || Character != _characterProvider.MainCharacter)
return;

// the algorithm in EO main seems to scale volume with distance to the closest ambient source
// distance is the sum of the components of the vector from character position to closest ambient source
// this is scaled from 0-25, with 0 being on top of the tile and 25 being too far away to hear the ambient sound from it
var props = _characterProvider.MainCharacter.RenderProperties;
var distance = _currentMapProvider.CurrentMap.GetDistanceToClosestTileSpec(TileSpec.AmbientSource, new MapCoordinate(props.MapX, props.MapY));
_sfxPlayer.SetLoopingSfxVolume(Math.Max((25 - distance) / 25f, 0));
}

private bool GetIsSteppingStone(CharacterRenderProperties renderProps)
{
if (_gameStateProvider.CurrentState != GameStates.PlayingTheGame)
Expand Down
5 changes: 5 additions & 0 deletions EndlessClient/Rendering/Factories/CharacterRendererFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using EndlessClient.Rendering.CharacterProperties;
using EndlessClient.Rendering.Chat;
using EndlessClient.Rendering.Sprites;
using EOLib.Config;
using EOLib.Domain.Character;
using EOLib.Domain.Map;
using EOLib.Graphics;
Expand All @@ -31,6 +32,7 @@ public class CharacterRendererFactory : ICharacterRendererFactory
private readonly IGameStateProvider _gameStateProvider;
private readonly ICurrentMapProvider _currentMapProvider;
private readonly IUserInputProvider _userInputProvider;
private readonly IConfigurationProvider _configurationProvider;
private readonly ISfxPlayer _sfxPlayer;

public CharacterRendererFactory(INativeGraphicsManager nativeGraphicsManager,
Expand All @@ -47,6 +49,7 @@ public CharacterRendererFactory(INativeGraphicsManager nativeGraphicsManager,
IGameStateProvider gameStateProvider,
ICurrentMapProvider currentMapProvider,
IUserInputProvider userInputProvider,
IConfigurationProvider configurationProvider,
ISfxPlayer sfxPlayer)
{
_nativeGraphicsManager = nativeGraphicsManager;
Expand All @@ -63,6 +66,7 @@ public CharacterRendererFactory(INativeGraphicsManager nativeGraphicsManager,
_gameStateProvider = gameStateProvider;
_currentMapProvider = currentMapProvider;
_userInputProvider = userInputProvider;
_configurationProvider = configurationProvider;
_sfxPlayer = sfxPlayer;
}

Expand All @@ -84,6 +88,7 @@ public ICharacterRenderer CreateCharacterRenderer(EOLib.Domain.Character.Charact
_gameStateProvider,
_currentMapProvider,
_userInputProvider,
_configurationProvider,
_sfxPlayer);
}
}
Expand Down

0 comments on commit ba4c6df

Please sign in to comment.