Adding some sound effects

This commit is contained in:
Ethan 2025-04-10 16:12:46 -04:00
parent cb79147e50
commit 6ad1272d7d
14 changed files with 72 additions and 44 deletions

Binary file not shown.

Binary file not shown.

View file

@ -6,5 +6,9 @@
<!-- Pistol Sounds --> <!-- Pistol Sounds -->
<sound id="gun/pistol/shoot" spatial="true" path="sounds/gun/small_pew.ogg"/> <sound id="gun/pistol/shoot" spatial="true" path="sounds/gun/small_pew.ogg"/>
<!-- Machine Gun Sounds -->
<sound id="gun/machine/shoot" spatial="true" path="sounds/gun/mach_pew.ogg"/>
<!-- Generic Sounds --> <!-- Generic Sounds -->
<sound id="gun/generic/shoot" spatial="true" path="sounds/gun/small_pew.ogg"/> <sound id="gun/generic/shoot" spatial="true" path="sounds/gun/small_pew.ogg"/>
<sound id="gun/generic/reload" spatial="true" path="sounds/gun/reload.ogg"/>

View file

@ -5,17 +5,17 @@
#include <unordered_map> #include <unordered_map>
#include <SDL_timer.h> #include <SDL_timer.h>
#include <optional> #include <optional>
#include <span>
#include "gameplay/entity.h" #include "gameplay/entity.h"
#include "gameplay/weapons/weapon.h"
#include "utility/mousestate.h" #include "utility/mousestate.h"
#include <utility/component.h> #include <utility/component.h>
class AI; class AI;
class Weapon;
class ISceneContext; class ISceneContext;
// TODO: Finish weapon cycling code and add default weapon to every actor
// TODO: Add ammo system, then work on some basic UI design // TODO: Add ammo system, then work on some basic UI design
class GameActor : public Entity class GameActor : public Entity
@ -25,11 +25,12 @@ public:
~GameActor(); ~GameActor();
void addComponent(std::unique_ptr<Component> component); void addComponent(std::unique_ptr<Component> component);
void pickupWeapon(std::shared_ptr<Weapon> weapon); void pickupWeapon(std::unique_ptr<Weapon> weapon);
void update(double deltaTime) override; void update(double deltaTime) override;
void draw() override; void draw() override;
const std::shared_ptr<Weapon> getHeldWeapon() const; Weapon* getHeldWeapon() const;
std::span<Weapon*> getAllWeapons();
void setRotation(const float& rotation) override; void setRotation(const float& rotation) override;
@ -49,11 +50,9 @@ public:
void cycleWeapons(const MouseState&); void cycleWeapons(const MouseState&);
void followMouse(const MouseState&); void followMouse(const MouseState&);
private: private:
using component_vector_t = std::vector<std::unique_ptr<Component>>; std::vector<std::unique_ptr<Component>> components;
using weapon_vector_t = std::vector<std::shared_ptr<Weapon>>; std::vector<std::unique_ptr<Weapon>> weapons;
std::vector<Weapon*> weaponCache;
component_vector_t components;
weapon_vector_t weapons;
size_t currentWeaponIndex = 0; size_t currentWeaponIndex = 0;
ISceneContext* sceneContext; ISceneContext* sceneContext;

View file

@ -24,7 +24,7 @@ class WeaponScript;
struct PhysicsComponent; struct PhysicsComponent;
struct WeaponData; struct WeaponData;
class Weapon : public Entity, public std::enable_shared_from_this<Weapon> class Weapon : public Entity
{ {
public: public:
Weapon(const WeaponData* data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager); Weapon(const WeaponData* data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager);

View file

@ -15,6 +15,7 @@ public:
private: private:
struct AudioSource { struct AudioSource {
ALuint source; ALuint source;
ALuint buffer;
bool inUse; bool inUse;
int priority; int priority;
}; };

View file

@ -43,7 +43,7 @@ public:
const unsigned loadSoundEffect (const std::string& id); const unsigned loadSoundEffect (const std::string& id);
std::unique_ptr<AIScript> loadAIScript (const std::string& path); std::unique_ptr<AIScript> loadAIScript (const std::string& path);
std::unique_ptr<WeaponScript> loadWeaponScript (const std::string& path); std::unique_ptr<WeaponScript> loadWeaponScript (const std::string& path);
std::shared_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID); std::unique_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID);
std::shared_ptr<AnimationSet> loadAnimationSet (const std::string& name, int entityid = 0); std::shared_ptr<AnimationSet> loadAnimationSet (const std::string& name, int entityid = 0);
const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath); const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath);
@ -62,7 +62,7 @@ private:
std::unordered_map<unsigned, Shader*> shaderIDs; std::unordered_map<unsigned, Shader*> shaderIDs;
std::unordered_map<std::string, std::unique_ptr<SoundEffect>> sounds; std::unordered_map<std::string, std::unique_ptr<SoundEffect>> sounds;
std::unordered_map<std::string, std::unique_ptr<Sprite>> sprites; std::unordered_map<std::string, std::unique_ptr<Sprite>> sprites;
std::unordered_map<std::string, std::shared_ptr<Weapon>> weapons; //std::unordered_map<std::string, std::unique_ptr<Weapon>> weapons;
//std::unordered_map<std::string, std::string> scripts; //std::unordered_map<std::string, std::string> scripts;
std::unordered_map<std::string, std::unique_ptr<Background>> backgrounds; std::unordered_map<std::string, std::unique_ptr<Background>> backgrounds;
std::unordered_map<std::string, std::shared_ptr<TileSetData>> tileSets; std::unordered_map<std::string, std::shared_ptr<TileSetData>> tileSets;

View file

@ -16,18 +16,24 @@ void GameActor::addComponent(std::unique_ptr<Component> component)
components.push_back(std::move(component)); components.push_back(std::move(component));
} }
const std::shared_ptr<Weapon> GameActor::getHeldWeapon() const Weapon* GameActor::getHeldWeapon() const
{ {
return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? nullptr : weapons[currentWeaponIndex]; return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? nullptr : weapons[currentWeaponIndex].get();
} }
void GameActor::pickupWeapon(std::shared_ptr<Weapon> weapon) std::span<Weapon*> GameActor::getAllWeapons()
{
return weaponCache;
}
void GameActor::pickupWeapon(std::unique_ptr<Weapon> weapon)
{ {
weapon->setWielder(this); weapon->setWielder(this);
if (auto eventManager = sceneContext->getEventManager().lock()) { if (auto eventManager = sceneContext->getEventManager().lock()) {
weapon->hookEventManager(eventManager); weapon->hookEventManager(eventManager);
} }
weapons.push_back(weapon); weaponCache.push_back(weapon.get());
weapons.push_back(std::move(weapon));
// wield the newly picked up weapon. // wield the newly picked up weapon.
getHeldWeapon()->putaway(); getHeldWeapon()->putaway();
currentWeaponIndex = weapons.size() - 1; currentWeaponIndex = weapons.size() - 1;
@ -40,7 +46,7 @@ void GameActor::setRotation(const float& rotation)
if (auto eventManager = sceneContext->getEventManager().lock()) { if (auto eventManager = sceneContext->getEventManager().lock()) {
Direction newDir = getDirectionFromRotation(rotation); Direction newDir = getDirectionFromRotation(rotation);
if (getDirectionFromRotation(this->rotation) != newDir) if (getDirectionFromRotation(this->rotation) != newDir)
eventManager->notify<DirectionChangeEvent>((DirectionChangeEvent){ entityid, newDir }); eventManager->notify<DirectionChangeEvent>({ entityid, newDir });
} }
} }
this->rotation = rotation; this->rotation = rotation;
@ -59,14 +65,14 @@ void GameActor::update(double deltaTime)
if (isMoving && !wasMoving) if (isMoving && !wasMoving)
{ {
if (auto event = sceneContext->getEventManager().lock()) { if (auto event = sceneContext->getEventManager().lock()) {
event->notify<EntityMoveEvent>((EntityMoveEvent){ entityid }); event->notify<EntityMoveEvent>({ entityid });
} }
wasMoving = true; wasMoving = true;
} }
else if (!isMoving && wasMoving) else if (!isMoving && wasMoving)
{ {
if (auto event = sceneContext->getEventManager().lock()) { if (auto event = sceneContext->getEventManager().lock()) {
event->notify<EntityStopEvent>((EntityStopEvent){ entityid }); event->notify<EntityStopEvent>({ entityid });
} }
wasMoving = false; wasMoving = false;
} }
@ -95,12 +101,12 @@ void GameActor::moveRight(){ if (physics) physics->rigidBody.applyForce(glm::vec
// top-down shooter mode controls // top-down shooter mode controls
void GameActor::fireWeapon()const { void GameActor::fireWeapon()const {
if (auto& weapon = getHeldWeapon()) { if (auto weapon = getHeldWeapon()) {
if (weapon->shoot()) { if (weapon->shoot()) {
if (sceneContext->getPlayerID() == entityid) { if (sceneContext->getPlayerID() == entityid) {
if (auto gEvent = sceneContext->getGlobalEventManager().lock()) { if (auto gEvent = sceneContext->getGlobalEventManager().lock()) {
gEvent->notify<ScreenShakeEvent>((ScreenShakeEvent){0.01f, 0.8f}); gEvent->notify<ScreenShakeEvent>({0.01f, 0.8f});
gEvent->notify<ScreenBlurEvent>((ScreenBlurEvent){1.f, 0.8f}); gEvent->notify<ScreenBlurEvent>({1.f, 0.8f});
} }
} }
} }
@ -134,7 +140,7 @@ void GameActor::followMouse(const MouseState& mouse_state)
float newRotation = glm::degrees(glm::atan(direction.y, direction.x)); float newRotation = glm::degrees(glm::atan(direction.y, direction.x));
if (getDirectionFromRotation(rotation) != getDirectionFromRotation(newRotation)) { if (getDirectionFromRotation(rotation) != getDirectionFromRotation(newRotation)) {
if (auto event = sceneContext->getEventManager().lock()) { if (auto event = sceneContext->getEventManager().lock()) {
event->notify<DirectionChangeEvent>((DirectionChangeEvent){ entityid, getDirectionFromRotation(newRotation) }); event->notify<DirectionChangeEvent>({ entityid, getDirectionFromRotation(newRotation) });
} }
} }
//setRotation(glm::degrees(glm::atan(direction.y, direction.x))); //setRotation(glm::degrees(glm::atan(direction.y, direction.x)));

View file

@ -92,8 +92,8 @@ void Scene::loadDebugShooterScene()
auto defaultWeapon = resourceManager->loadWeapon("gun/pistol", weaponShader, bubbleShader); auto defaultWeapon = resourceManager->loadWeapon("gun/pistol", weaponShader, bubbleShader);
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader); auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
entity->pickupWeapon(defaultWeapon); entity->pickupWeapon(std::move(defaultWeapon));
entity->pickupWeapon(entityWeapon); entity->pickupWeapon(std::move(entityWeapon));
entity->setPosition(glm::vec3(entityData.x * mapData->tileSize, entityData.y * mapData->tileSize, 0.f)); entity->setPosition(glm::vec3(entityData.x * mapData->tileSize, entityData.y * mapData->tileSize, 0.f));
entity->setScale(glm::vec3(mapData->tileSize, mapData->tileSize, 1.f)); entity->setScale(glm::vec3(mapData->tileSize, mapData->tileSize, 1.f));
@ -166,9 +166,12 @@ void Scene::render(std::shared_ptr<Renderer> renderer)
//e->draw(); //e->draw();
renderer->addDrawable(RenderLayer::GameObjects, e.get()); renderer->addDrawable(RenderLayer::GameObjects, e.get());
if (e->getHeldWeapon()) { if (e->getHeldWeapon()) {
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon().get()); renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon());
for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) { const auto& weapons = e->getAllWeapons();
renderer->addDrawable(RenderLayer::GameObjects, bullet.get()); for (auto& w : weapons) {
for (auto b : w->getBulletManager()->getBullets()) {
renderer->addDrawable(RenderLayer::GameObjects, b.get());
}
} }
} }
} }
@ -222,7 +225,7 @@ void Scene::hookSceneEvents()
GameActor* shooter = self->getGameActorByID(e.ownerID); GameActor* shooter = self->getGameActorByID(e.ownerID);
GameActor* target = self->getGameActorByID(e.victimID); GameActor* target = self->getGameActorByID(e.victimID);
if (shooter && target) if (shooter && target)
if (auto& weapon = shooter->getHeldWeapon()) if (auto weapon = shooter->getHeldWeapon())
weapon->onHitCallback(target, e.bullet.get(), e.normal); weapon->onHitCallback(target, e.bullet.get(), e.normal);
} }
}); });

View file

@ -119,9 +119,9 @@ void Weapon::hookEventManager(std::weak_ptr<EventManager> eventManager)
} }
if (auto event = this->eventManager.lock()) { if (auto event = this->eventManager.lock()) {
std::weak_ptr<Weapon> selfWeak = shared_from_this(); auto self = this;
event->subscribe<AnimationFinishedEvent>([selfWeak](const AnimationFinishedEvent& e) { event->subscribe<AnimationFinishedEvent>([self](const AnimationFinishedEvent& e) {
if (auto self = selfWeak.lock()) { if (self) {
if (e.entityid == self->entityid && e.animType == "reload") if (e.entityid == self->entityid && e.animType == "reload")
{ {
if (self->reloading) if (self->reloading)

View file

@ -28,15 +28,25 @@ void AudioEngine::hookSceneManager(std::weak_ptr<EventManager> _events)
sceneEventManager = _events; sceneEventManager = _events;
if (auto weak = sceneEventManager.lock()) { if (auto weak = sceneEventManager.lock()) {
std::weak_ptr<AudioEngine> weakSelf = shared_from_this(); std::weak_ptr<AudioEngine> weakSelf = shared_from_this();
weak->subscribe<EntityFireEvent>([weakSelf](const EntityFireEvent& e){ auto play_sound = [weakSelf](const std::string& id, int priority, const std::optional<glm::vec3>& pos = std::nullopt) {
if (auto self = weakSelf.lock()) { if (auto self = weakSelf.lock()) {
if (auto res = self->resourceManager.lock()) { if (auto res = self->resourceManager.lock()) {
auto buf = res->loadSoundEffect(e.weaponType + "/shoot"); auto buf = res->loadSoundEffect(id);
if (buf != 0) { if (buf != 0) {
self->soundManager->playSound(buf, 10, e.firePosition); if (pos != std::nullopt)
self->soundManager->playSound(buf, priority, pos.value());
else
self->soundManager->playSound(buf, priority);
} }
} }
} }
};
weak->subscribe<EntityFireEvent>([weakSelf,play_sound](const EntityFireEvent& e){
play_sound(e.weaponType + "/shoot", 10, e.firePosition);
});
weak->subscribe<EntityReloadEvent>([weakSelf,play_sound](const EntityReloadEvent& e) {
play_sound(e.weaponType + "/reload", 9, e.position);
}); });
} }
} }

View file

@ -10,7 +10,7 @@ SoundManager::SoundManager()
s.priority = 0; s.priority = 0;
alSourcef(s.source, AL_REFERENCE_DISTANCE, 1.0f); alSourcef(s.source, AL_REFERENCE_DISTANCE, 1.0f);
alSourcef(s.source, AL_MAX_DISTANCE, 10000.f); alSourcef(s.source, AL_MAX_DISTANCE, 10000.f);
alSourcef(s.source, AL_ROLLOFF_FACTOR, 1.0f); alSourcef(s.source, AL_ROLLOFF_FACTOR, 0.3f);
} }
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
} }
@ -25,6 +25,7 @@ void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
if (!sources[ring].inUse) { if (!sources[ring].inUse) {
sources[ring].inUse = true; sources[ring].inUse = true;
sources[ring].priority = priority; sources[ring].priority = priority;
sources[ring].buffer = buffer;
alSourcei(sources[ring].source, AL_BUFFER, buffer); alSourcei(sources[ring].source, AL_BUFFER, buffer);
if (pos != glm::vec3(0)) { if (pos != glm::vec3(0)) {
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1); //alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1);
@ -40,6 +41,7 @@ void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
if (!sources[ring].inUse) { if (!sources[ring].inUse) {
sources[ring].inUse = true; sources[ring].inUse = true;
sources[ring].priority = priority; sources[ring].priority = priority;
sources[ring].buffer = buffer;
alSourcei(sources[ring].source, AL_BUFFER, buffer); alSourcei(sources[ring].source, AL_BUFFER, buffer);
if (pos != glm::vec3(0)) { if (pos != glm::vec3(0)) {
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1); //alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1);
@ -48,12 +50,12 @@ void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 0); //alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 0);
} }
alSourcePlay(sources[ring].source); alSourcePlay(sources[ring].source);
lastUsed = ring; lastUsed = nextIndex(ring);
return; return;
} }
if (sources[ring].priority <= priority) { if (sources[ring].priority > priority || (sources[ring].buffer != buffer && sources[ring].priority == priority)) {
if (nextBest) { if (nextBest) {
if (nextBest->priority > sources[ring].priority) { if (nextBest->priority >= sources[ring].priority) {
nextBest = &sources[ring]; nextBest = &sources[ring];
secIndex = ring; secIndex = ring;
} }
@ -65,7 +67,9 @@ void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
} }
if (nextBest) { if (nextBest) {
nextBest->priority = priority; nextBest->priority = priority;
alSourcei(nextBest->source, AL_BUFFER, 0);
alSourcei(nextBest->source, AL_BUFFER, buffer); alSourcei(nextBest->source, AL_BUFFER, buffer);
nextBest->buffer = buffer;
if (pos != glm::vec3(0)) { if (pos != glm::vec3(0)) {
//alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 1); //alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 1);
alSourcefv(nextBest->source, AL_POSITION, glm::value_ptr(pos)); alSourcefv(nextBest->source, AL_POSITION, glm::value_ptr(pos));
@ -86,6 +90,7 @@ void SoundManager::pollSources()
alGetSourcei(s.source, AL_SOURCE_STATE, &state); alGetSourcei(s.source, AL_SOURCE_STATE, &state);
if (state == AL_STOPPED) { if (state == AL_STOPPED) {
s.inUse = false; s.inUse = false;
s.buffer = 0;
alSourcei(s.source, AL_BUFFER, 0); alSourcei(s.source, AL_BUFFER, 0);
} }
//else if (state != AL_PLAYING) //else if (state != AL_PLAYING)

View file

@ -78,17 +78,17 @@ Background* ResourceManager::loadBackground(const std::string& path)
// We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an // We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an
// incomplete reference to our script. // incomplete reference to our script.
std::shared_ptr<Weapon> ResourceManager::loadWeapon(const std::string& id, const unsigned weaponShaderID, const unsigned bulletShaderID) std::unique_ptr<Weapon> ResourceManager::loadWeapon(const std::string& id, const unsigned weaponShaderID, const unsigned bulletShaderID)
{ {
const WeaponData* data = xmlLoader->getWeaponData(id); const WeaponData* data = xmlLoader->getWeaponData(id);
if (!data) { if (!data) {
LOG(ERROR, "Could not load weapon id '{}', falling back to pistol", id); LOG(ERROR, "Could not load weapon id '{}', falling back to pistol", id);
data = xmlLoader->getWeaponData("gun/pistol");// using this as a fallback for now data = xmlLoader->getWeaponData("gun/pistol");// using this as a fallback for now
} }
auto weapon = std::make_shared<Weapon>(data, weaponShaderID, bulletShaderID, this); auto weapon = std::make_unique<Weapon>(data, weaponShaderID, bulletShaderID, this);
if (!data->script.empty()) if (!data->script.empty())
weapon->attachScript(loadWeaponScript(data->script)); weapon->attachScript(loadWeaponScript(data->script));
return weapon; return std::move(weapon);
} }
const unsigned ResourceManager::loadSoundEffect(const std::string& id) const unsigned ResourceManager::loadSoundEffect(const std::string& id)
@ -139,7 +139,6 @@ void ResourceManager::clearResources()
sprites.clear(); sprites.clear();
shaders.clear(); shaders.clear();
shaderIDs.clear(); shaderIDs.clear();
weapons.clear();
tileSets.clear(); tileSets.clear();
} }

1
compile_flags.txt Normal file
View file

@ -0,0 +1 @@
-std=c++20