All sound effects now accept positions as well for surround sound effects during combat.

pull/29/head
sigonasr2 11 months ago
parent 57f482016f
commit 8a1d8868c9
  1. 8
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 29
      Adventures in Lestoria/Audio.cpp
  3. 4
      Adventures in Lestoria/Audio.h
  4. 2
      Adventures in Lestoria/BuyItemWindow.cpp
  5. 2
      Adventures in Lestoria/CharacterMenuWindow.cpp
  6. 4
      Adventures in Lestoria/Item.cpp
  7. 2
      Adventures in Lestoria/ItemDrop.cpp
  8. 6
      Adventures in Lestoria/Monster.cpp
  9. 10
      Adventures in Lestoria/Ranger.cpp
  10. 2
      Adventures in Lestoria/SellItemWindow.cpp
  11. 10
      Adventures in Lestoria/SlimeKing.cpp
  12. 21
      Adventures in Lestoria/SoundEffect.cpp
  13. 3
      Adventures in Lestoria/SoundEffect.h
  14. 8
      Adventures in Lestoria/Unlock.cpp
  15. 2
      Adventures in Lestoria/Version.h
  16. 2
      Adventures in Lestoria/assets/config/audio/audio.txt
  17. 4
      Adventures in Lestoria/assets/config/audio/bgm.txt
  18. 2
      Adventures in Lestoria/assets/config/audio/events.txt
  19. 5
      Adventures in Lestoria/olcPGEX_MiniAudio.h

@ -504,9 +504,9 @@ void AiL::HandleUserInput(float fElapsedTime){
}
if(inWater){
SoundEffect::PlaySFX("Footstep - Wet");
SoundEffect::PlaySFX("Footstep - Wet",SoundEffect::CENTERED);
}else{
SoundEffect::PlaySFX("Footstep");
SoundEffect::PlaySFX("Footstep",SoundEffect::CENTERED);
}
}
}
@ -2251,7 +2251,7 @@ void AiL::DisplayBossEncounterInfo(){
alpha=uint8_t((bossDisplayTimer)*255);
}
vf2d textScale={3,5};
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/2)}-vf2d{GetTextSizeProp(displayText)}*textScale/2,displayText,{252, 186, 3, alpha},{128,0,0,alpha},textScale,2);
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/2)}-vf2d{GetTextSizeProp(displayText)}*textScale/2,displayText,{252, 186, 3, alpha},{128,0,0,alpha},textScale,std::numeric_limits<float>::max(),2);
}
if(InBossEncounter()){
Pixel displayCol=totalBossEncounterMobs==0?Pixel{224, 133, 29}:WHITE;
@ -2489,7 +2489,7 @@ bool AiL::UseLoadoutItem(int slot){
Inventory::UseItem(GetLoadoutItem(slot).lock()->ActualName());
GetLoadoutItem(slot).lock()->amt--;
if(GetLoadoutItem(slot).lock()->UseSound().length()>0){
SoundEffect::PlaySFX(GetLoadoutItem(slot).lock()->UseSound());
SoundEffect::PlaySFX(GetLoadoutItem(slot).lock()->UseSound(),SoundEffect::CENTERED);
}
return true;
}

@ -38,6 +38,7 @@ All rights reserved.
#include "Audio.h"
#include "AdventuresInLestoria.h"
#include "DEFINES.h"
#include "util.h"
INCLUDE_game
INCLUDE_DATA
@ -231,8 +232,13 @@ void Audio::SetAudioEvent(const Event&eventName){
if(Audio::BGMIsPlaying()){
BGM&currentBgm=Self().bgm[Self().currentBGM];
Self().targetVolumes.clear();
Self().fadeToTargetVolumeTime=currentBgm.GetFadeTime();
for(int currentTrackIndex=0;int trackID:currentBgm.GetChannelIDs()){
Engine().SetVolume(trackID,currentBgm.GetVolume(eventName,currentTrackIndex));
//Engine().SetVolume(trackID,currentBgm.GetVolume(eventName,currentTrackIndex));
Self().targetVolumes.push_back(currentBgm.GetVolume(eventName,currentTrackIndex)); //Set the target volumes so that the engine can gradually move the volumes over to the new settings.
currentTrackIndex++;
}
}
@ -252,16 +258,35 @@ void Audio::Update(){
if(Self().playBGMWaitTime==0.f){
BGM&track=Self().bgm[Self().playParams.sound];
track.Load();
Self().prevVolumes.clear();
Self().targetVolumes.clear();
Self().fadeToTargetVolumeTime=0.f;
for(int channelListIndex=0;int trackID:track.GetChannelIDs()){
Engine().SetVolume(trackID,track.GetVolume(Self().currentAudioEvent,channelListIndex));
float channelVol=track.GetVolume(Self().currentAudioEvent,channelListIndex);
Self().prevVolumes.push_back(channelVol);
Self().targetVolumes.push_back(channelVol);
Engine().SetVolume(trackID,channelVol);
Engine().Play(trackID,Self().playParams.loop);
channelListIndex++;
}
Self().fullyLoaded=true;
}
}
if(Self().fadeToTargetVolumeTime>0.f){
Self().fadeToTargetVolumeTime=std::max(0.f,Self().fadeToTargetVolumeTime-game->GetElapsedTime());
for(int counter=0;float&vol:Self().prevVolumes){
const BGM&currentBgm=Self().bgm[Self().currentBGM];
Engine().SetVolume(currentBgm.GetChannelIDs()[counter],util::lerp(vol,Self().targetVolumes[counter],1-(Self().fadeToTargetVolumeTime/currentBgm.GetFadeTime())));
counter++;
}
}
}
const bool Audio::BGMFullyLoaded(){
return Self().fullyLoaded;
}
const float&Audio::BGM::GetFadeTime()const{
return fadeTime;
}

@ -93,6 +93,7 @@ private:
void SetFadeTime(const float fadeTime);
const ChannelID&GetChannelID(const int index);
const ChannelIDList&GetChannelIDs()const;
const float&GetFadeTime()const;
private:
std::string songName; //Name of the track.
std::string songFileName; //Name of the key in bgm.
@ -109,6 +110,9 @@ private:
std::set<Event>events;
static float defaultFadeTime;
Event currentAudioEvent="Default Volume";
std::vector<float>prevVolumes;
std::vector<float>targetVolumes;
float fadeToTargetVolumeTime=0.f;
bool fullyLoaded=true;
float playBGMWaitTime=0.0f;
BGMPlayParams playParams;

@ -86,7 +86,7 @@ void Menu::InitializeBuyItemWindow(){
Merchant&merchant=Merchant::GetCurrentTravelingMerchant();
const std::string&item=Component<MenuLabel>(BUY_ITEM,"Item Purchase Header")->GetString(A::ITEM_NAME);
merchant.PurchaseItem(item,GetQuantity());
SoundEffect::PlaySFX("Buy Item");
SoundEffect::PlaySFX("Buy Item",SoundEffect::CENTERED);
Menu::CloseMenu();
return true;
})END;

@ -149,7 +149,7 @@ void Menu::InitializeCharacterMenuWindow(){
if(comp!=nullptr){
if(OppositeRingSlotDoesNotMatchCurrentEquip(comp)){ //If we find that the opposite ring slot is equipped to us, this would be an item swap or the exact same ring, therefore no stat calculations apply.
Inventory::EquipItem(comp->GetItem(),EquipSlot(comp->I(Attribute::EQUIP_TYPE)));
SoundEffect::PlaySFX(comp->GetItem().lock()->UseSound());
SoundEffect::PlaySFX(comp->GetItem().lock()->UseSound(),SoundEffect::CENTERED);
for(MenuComponent*button:((ScrollableWindowComponent*)data.parentComponent)->GetComponents()){
RowItemDisplay*comp=DYNAMIC_CAST<RowItemDisplay*>(button);
if(comp!=nullptr){

@ -855,7 +855,7 @@ void Item::EnhanceItem(uint8_t qty){
}
game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost());
SoundEffect::PlaySFX("Enhance Item");
SoundEffect::PlaySFX("Enhance Item",SoundEffect::CENTERED);
}else{ //This is a craftable, so we have to give the player the item they crafted.
Inventory::AddItem(ActualName());
@ -866,7 +866,7 @@ void Item::EnhanceItem(uint8_t qty){
}
game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost());
SoundEffect::PlaySFX("Craft Item");
SoundEffect::PlaySFX("Craft Item",SoundEffect::CENTERED);
}
}
};

@ -137,7 +137,7 @@ void ItemDrop::UpdateDrops(float fElapsedTime){
if(drop.collected){
Inventory::AddItem(drop.GetItem()->Name(),1,true);
ItemOverlay::AddToItemOverlay(*drop.GetItem());
SoundEffect::PlaySFX("Collect Item");
SoundEffect::PlaySFX("Collect Item",SoundEffect::CENTERED);
return true;
}
return false;

@ -282,7 +282,7 @@ void Monster::Moved(){
monsterWalkSoundTimer+=game->GetElapsedTime();
if(monsterWalkSoundTimer>1.f){
monsterWalkSoundTimer-=1.f;
SoundEffect::PlaySFX(GetWalkSound());
SoundEffect::PlaySFX(GetWalkSound(),GetPos());
}
}
std::string Monster::GetDeathAnimationName(){
@ -326,13 +326,13 @@ bool Monster::Hurt(int damage,bool onUpperLevel,float z){
if(!IsAlive()){
OnDeath();
SoundEffect::PlaySFX(GetDeathSound());
SoundEffect::PlaySFX(GetDeathSound(),GetPos());
}else{
hp=std::max(1,hp); //Make sure it stays alive if it's supposed to be alive...
if(monsterHurtSoundCooldown==0.f){
monsterHurtSoundCooldown=util::random(0.5f)+0.5f;
SoundEffect::PlaySFX(GetHurtSound());
SoundEffect::PlaySFX(GetHurtSound(),GetPos());
}
}
if(game->InBossEncounter()){

@ -75,7 +75,7 @@ bool Ranger::AutoAttack(){
BULLET_LIST.push_back(std::make_unique<Arrow>(Arrow(GetPos(),extendedLine,vf2d{cos(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F,float(sin(angleToCursor)*"Ranger.Auto Attack.ArrowSpd"_F-PI/8*"Ranger.Auto Attack.ArrowSpd"_F)}+movementVelocity,"Ranger.Auto Attack.Radius"_F/100*12,int(GetAttack()*"Ranger.Auto Attack.DamageMult"_F),OnUpperLevel(),true)));
SetState(State::SHOOT_ARROW);
SetAnimationBasedOnTargetingDirection(angleToCursor);
SoundEffect::PlaySFX("Ranger.Auto Attack.Sound"_S);
SoundEffect::PlaySFX("Ranger.Auto Attack.Sound"_S,SoundEffect::CENTERED);
return true;
}
@ -94,7 +94,7 @@ void Ranger::InitializeClassAbilities(){
float angleToCursor=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
p->SetAnimationBasedOnTargetingDirection(angleToCursor);
p->SetState(State::RETREAT);
SoundEffect::PlaySFX("Ranger.Right Click Ability.Sound"_S);
SoundEffect::PlaySFX("Ranger.Right Click Ability.Sound"_S,SoundEffect::CENTERED);
return true;
};
#pragma endregion
@ -106,7 +106,7 @@ void Ranger::InitializeClassAbilities(){
if("Ranger.Ability 1.IsAnimationLocked"_I){
p->SetState(State::ANIMATION_LOCK);
}
SoundEffect::PlaySFX("Ranger.Ability 1.Sound"_S);
SoundEffect::PlaySFX("Ranger.Ability 1.Sound"_S,SoundEffect::CENTERED);
return true;
};
#pragma endregion
@ -118,7 +118,7 @@ void Ranger::InitializeClassAbilities(){
p->SetAnimationBasedOnTargetingDirection(atan2(arrowVelocity.y,arrowVelocity.x));
game->SetupWorldShake("Ranger.Ability 2.WorldShakeTime"_F);
p->Knockback(-1.f*arrowVelocity.norm()*"Ranger.Ability 2.Knockback"_F);
SoundEffect::PlaySFX("Ranger.Ability 2.Sound"_S);
SoundEffect::PlaySFX("Ranger.Ability 2.Sound"_S,SoundEffect::CENTERED);
return true;
};
#pragma endregion
@ -141,7 +141,7 @@ void Ranger::InitializeClassAbilities(){
BULLET_LIST.push_back(std::make_unique<Arrow>(Arrow(p->GetPos(),extendedLine,vf2d{cos(newAngle)*"Ranger.Ability 3.ArrowSpd"_F,float(sin(newAngle)*"Ranger.Ability 3.ArrowSpd"_F-PI/8*"Ranger.Ability 3.ArrowSpd"_F)}+p->movementVelocity,12*"Ranger.Ability 3.ArrowRadius"_F/100,int(p->GetAttack()*"Ranger.Ability 3.DamageMult"_F),p->OnUpperLevel(),true)));
}
p->SetAnimationBasedOnTargetingDirection(shootingAngle);
SoundEffect::PlaySFX("Ranger.Ability 3.Sound"_S);
SoundEffect::PlaySFX("Ranger.Ability 3.Sound"_S,SoundEffect::CENTERED);
return true;
};
#pragma endregion

@ -85,7 +85,7 @@ void Menu::InitializeSellItemWindow(){
sellItemWindow->ADD("Sell Button",MenuComponent)({{sellItemWindow->size.x/2+18,70},{64,12}},"Sell",[&](MenuFuncData data){
Merchant&merchant=Merchant::GetCurrentTravelingMerchant();
merchant.SellItem(Component<ItemMenuLabel>(SELL_ITEM,"Item Sell Header")->GetItem(),GetQuantity());
SoundEffect::PlaySFX("Sell Item");
SoundEffect::PlaySFX("Sell Item",SoundEffect::CENTERED);
Menu::CloseMenu();
return true;
})END;

@ -69,14 +69,14 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
float angle=((2*PI)/bulletCount)*i+angleOffset;
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(angle),sin(angle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
}
SoundEffect::PlaySFX("Slime King Shoot");
SoundEffect::PlaySFX("Slime King Shoot",m.GetPos());
};
const auto Landed=[&ShootBulletRing,&m](int currentPhase){
if(currentPhase==1){
ShootBulletRing(m.F(A::SHOOT_RING_OFFSET));
}
SoundEffect::PlaySFX("Slime King Land");
SoundEffect::PlaySFX("Slime King Land",m.GetPos());
};
const auto TransitionPhase=[&](int newPhase){
@ -291,7 +291,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
float angle=(i-(bulletCount/2))*util::degToRad(ConfigFloat("Phase2.ShootAngleSpread"))+initialAngle;
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(angle),sin(angle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
}
SoundEffect::PlaySFX("Slime King Shoot");
SoundEffect::PlaySFX("Slime King Shoot",m.GetPos());
}
if(m.I(A::PATTERN_REPEAT_COUNT)>ConfigInt("Phase2.ShootCount")){
m.I(A::PATTERN_REPEAT_COUNT)=0;
@ -321,7 +321,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
float angle=(i-(bulletCount/2))*util::degToRad(ConfigFloat("Phase3.ShootAngleSpread"))+initialAngle;
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(angle),sin(angle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
}
SoundEffect::PlaySFX("Slime King Shoot");
SoundEffect::PlaySFX("Slime King Shoot",m.GetPos());
}else
if(m.I(A::PATTERN_REPEAT_COUNT)>=4){
m.F(A::RECOVERY_TIME)=ConfigFloat("Phase3.PhaseRecoveryTime");
@ -351,7 +351,7 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,std::string strat
float spreadAngle=util::degToRad(ConfigFloat("Phase4.RandomOffsetAngle"));
bulletAngle+=util::random(spreadAngle*2)-spreadAngle;
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(bulletAngle),sin(bulletAngle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
SoundEffect::PlaySFX("Slime King Shoot");
SoundEffect::PlaySFX("Slime King Shoot",m.GetPos());
}else
if(m.I(A::PATTERN_REPEAT_COUNT)==5){
m.I(A::PATTERN_REPEAT_COUNT)++;

@ -41,10 +41,13 @@ All rights reserved.
#include "Audio.h"
#include "util.h"
#include "DEFINES.h"
#include "AdventuresInLestoria.h"
INCLUDE_DATA
INCLUDE_game
std::multimap<EventName,SoundEffect>SoundEffect::SOUND_EFFECTS;
const vf2d SoundEffect::CENTERED={-8419.f,-3289.f};
SoundEffect::SoundEffect(const std::string_view filename,const float&vol)
:filename(filename),vol(vol){
@ -62,7 +65,7 @@ void SoundEffect::Initialize(){
}
}
void SoundEffect::PlaySFX(const std::string_view eventName){
void SoundEffect::PlaySFX(const std::string_view eventName,const vf2d&pos){
if(eventName.length()==0)return;
auto itr=SOUND_EFFECTS.equal_range(std::string(eventName));
size_t soundCount=std::distance(itr.first,itr.second);
@ -74,5 +77,19 @@ void SoundEffect::PlaySFX(const std::string_view eventName){
++it;
}
const SoundEffect&sfx=(*it).second;
Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),sfx.vol);
if(pos==CENTERED){
Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),sfx.vol);
}else{
const float soundActivationRange="Audio.Environmental Audio Activation Range"_F;
float distanceFromPlayer=geom2d::line<float>(game->GetPlayer()->GetPos(),pos).length();
if(distanceFromPlayer<soundActivationRange){
float distRatio=1-distanceFromPlayer/soundActivationRange; //0-1 where 1 is full volume.
float xDistRatio=(pos.x-game->GetPlayer()->GetX())/soundActivationRange; //0-1 where 1 is full volume.
float vol=distRatio*sfx.vol;
float pan=xDistRatio;
Audio::Engine().Play(operator""_SFX(sfx.filename.c_str(),sfx.filename.length()),vol,pan);
}
}
}

@ -46,8 +46,9 @@ using EventName=std::string;
class SoundEffect{
public:
SoundEffect(const std::string_view filename,const float&vol);
static void PlaySFX(const std::string_view eventName);
static void PlaySFX(const std::string_view eventName,const vf2d&pos);
static void Initialize();
static const vf2d CENTERED;
private:
static std::multimap<EventName,SoundEffect>SOUND_EFFECTS;
std::string filename;

@ -43,6 +43,14 @@ std::set<std::string>Unlock::unlocks;
void Unlock::Initialize(){
UnlockArea("WORLD_MAP");
UnlockArea("CAMPAIGN_1_1");
UnlockArea("BOSS_1");
UnlockArea("CAMPAIGN_1_2");
UnlockArea("CAMPAIGN_1_3");
UnlockArea("CAMPAIGN_1_4");
UnlockArea("CAMPAIGN_1_5");
UnlockArea("CAMPAIGN_1_6");
UnlockArea("CAMPAIGN_1_7");
UnlockArea("CAMPAIGN_1_8");
}
void Unlock::UnlockArea(std::string mapName){

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
#define VERSION_BUILD 5517
#define VERSION_BUILD 5528
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -1,4 +1,4 @@
Audio
{
Environmental Audio Activation Range = 300
Environmental Audio Activation Range = 400
}

@ -85,8 +85,8 @@ BGM
Events
{
Default Volume = 0%,0%,0%,0%,0%,70%
TitleScreenLoaded = 70%,0%,0%,0%,70%,70%
Default Volume = 0%,0%,0%,0%,50%,0%
TitleScreenLoaded = 30%,0%,0%,0%,50%,30%
}
}
}

@ -113,7 +113,7 @@ Events
Slime King Shoot
{
# Specify file names, followed by volume %
File[0] = slime_king_shoot.ogg, 100%
File[0] = slime_king_shoot.ogg, 60%
}
Slime Shoot
{

@ -89,7 +89,7 @@ namespace olc
// plays a sample, can be set to loop
void Play(const int id, const bool loop = false);
// plays a sound file, as a one off, and automatically unloads it
void Play(const std::string& path,const float&vol=1.0f);
void Play(const std::string& path,const float&vol=1.0f,const float&pan=0.0f);
// stops a sample, rewinds to beginning
void Stop(const int id);
// pauses a sample, does not change position
@ -335,7 +335,7 @@ namespace olc
ma_sound_start(vecSounds.at(id));
}
void MiniAudio::Play(const std::string& path,const float&vol)
void MiniAudio::Play(const std::string& path,const float&vol,const float&pan)
{
// create the sound
ma_sound* sound = new ma_sound();
@ -345,6 +345,7 @@ namespace olc
throw MiniAudioSoundException();
ma_sound_set_volume(sound,vol);
ma_sound_set_pan(sound,pan);
ma_sound_start(sound);
vecOneOffSounds.push_back(sound);
}

Loading…
Cancel
Save