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 -->
<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 -->
<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 <SDL_timer.h>
#include <optional>
#include <span>
#include "gameplay/entity.h"
#include "gameplay/weapons/weapon.h"
#include "utility/mousestate.h"
#include <utility/component.h>
class AI;
class Weapon;
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
class GameActor : public Entity
@ -25,11 +25,12 @@ public:
~GameActor();
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 draw() override;
const std::shared_ptr<Weapon> getHeldWeapon() const;
Weapon* getHeldWeapon() const;
std::span<Weapon*> getAllWeapons();
void setRotation(const float& rotation) override;
@ -49,14 +50,12 @@ public:
void cycleWeapons(const MouseState&);
void followMouse(const MouseState&);
private:
using component_vector_t = std::vector<std::unique_ptr<Component>>;
using weapon_vector_t = std::vector<std::shared_ptr<Weapon>>;
component_vector_t components;
weapon_vector_t weapons;
std::vector<std::unique_ptr<Component>> components;
std::vector<std::unique_ptr<Weapon>> weapons;
std::vector<Weapon*> weaponCache;
size_t currentWeaponIndex = 0;
ISceneContext* sceneContext;
};
#endif //_H_GAMEACTOR_H
#endif //_H_GAMEACTOR_H

View file

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

View file

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

View file

@ -43,7 +43,7 @@ public:
const unsigned loadSoundEffect (const std::string& id);
std::unique_ptr<AIScript> loadAIScript (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);
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<std::string, std::unique_ptr<SoundEffect>> sounds;
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::unique_ptr<Background>> backgrounds;
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));
}
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);
if (auto eventManager = sceneContext->getEventManager().lock()) {
weapon->hookEventManager(eventManager);
}
weapons.push_back(weapon);
weaponCache.push_back(weapon.get());
weapons.push_back(std::move(weapon));
// wield the newly picked up weapon.
getHeldWeapon()->putaway();
currentWeaponIndex = weapons.size() - 1;
@ -40,7 +46,7 @@ void GameActor::setRotation(const float& rotation)
if (auto eventManager = sceneContext->getEventManager().lock()) {
Direction newDir = getDirectionFromRotation(rotation);
if (getDirectionFromRotation(this->rotation) != newDir)
eventManager->notify<DirectionChangeEvent>((DirectionChangeEvent){ entityid, newDir });
eventManager->notify<DirectionChangeEvent>({ entityid, newDir });
}
}
this->rotation = rotation;
@ -59,14 +65,14 @@ void GameActor::update(double deltaTime)
if (isMoving && !wasMoving)
{
if (auto event = sceneContext->getEventManager().lock()) {
event->notify<EntityMoveEvent>((EntityMoveEvent){ entityid });
event->notify<EntityMoveEvent>({ entityid });
}
wasMoving = true;
}
else if (!isMoving && wasMoving)
{
if (auto event = sceneContext->getEventManager().lock()) {
event->notify<EntityStopEvent>((EntityStopEvent){ entityid });
event->notify<EntityStopEvent>({ entityid });
}
wasMoving = false;
}
@ -95,12 +101,12 @@ void GameActor::moveRight(){ if (physics) physics->rigidBody.applyForce(glm::vec
// top-down shooter mode controls
void GameActor::fireWeapon()const {
if (auto& weapon = getHeldWeapon()) {
if (auto weapon = getHeldWeapon()) {
if (weapon->shoot()) {
if (sceneContext->getPlayerID() == entityid) {
if (auto gEvent = sceneContext->getGlobalEventManager().lock()) {
gEvent->notify<ScreenShakeEvent>((ScreenShakeEvent){0.01f, 0.8f});
gEvent->notify<ScreenBlurEvent>((ScreenBlurEvent){1.f, 0.8f});
gEvent->notify<ScreenShakeEvent>({0.01f, 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));
if (getDirectionFromRotation(rotation) != getDirectionFromRotation(newRotation)) {
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)));

View file

@ -92,8 +92,8 @@ void Scene::loadDebugShooterScene()
auto defaultWeapon = resourceManager->loadWeapon("gun/pistol", weaponShader, bubbleShader);
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
entity->pickupWeapon(defaultWeapon);
entity->pickupWeapon(entityWeapon);
entity->pickupWeapon(std::move(defaultWeapon));
entity->pickupWeapon(std::move(entityWeapon));
entity->setPosition(glm::vec3(entityData.x * mapData->tileSize, entityData.y * mapData->tileSize, 0.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();
renderer->addDrawable(RenderLayer::GameObjects, e.get());
if (e->getHeldWeapon()) {
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon().get());
for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) {
renderer->addDrawable(RenderLayer::GameObjects, bullet.get());
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon());
const auto& weapons = e->getAllWeapons();
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* target = self->getGameActorByID(e.victimID);
if (shooter && target)
if (auto& weapon = shooter->getHeldWeapon())
if (auto weapon = shooter->getHeldWeapon())
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()) {
std::weak_ptr<Weapon> selfWeak = shared_from_this();
event->subscribe<AnimationFinishedEvent>([selfWeak](const AnimationFinishedEvent& e) {
if (auto self = selfWeak.lock()) {
auto self = this;
event->subscribe<AnimationFinishedEvent>([self](const AnimationFinishedEvent& e) {
if (self) {
if (e.entityid == self->entityid && e.animType == "reload")
{
if (self->reloading)

View file

@ -28,15 +28,25 @@ void AudioEngine::hookSceneManager(std::weak_ptr<EventManager> _events)
sceneEventManager = _events;
if (auto weak = sceneEventManager.lock()) {
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 res = self->resourceManager.lock()) {
auto buf = res->loadSoundEffect(e.weaponType + "/shoot");
auto buf = res->loadSoundEffect(id);
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;
alSourcef(s.source, AL_REFERENCE_DISTANCE, 1.0f);
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);
}
@ -25,6 +25,7 @@ void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
if (!sources[ring].inUse) {
sources[ring].inUse = true;
sources[ring].priority = priority;
sources[ring].buffer = buffer;
alSourcei(sources[ring].source, AL_BUFFER, buffer);
if (pos != glm::vec3(0)) {
//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) {
sources[ring].inUse = true;
sources[ring].priority = priority;
sources[ring].buffer = buffer;
alSourcei(sources[ring].source, AL_BUFFER, buffer);
if (pos != glm::vec3(0)) {
//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);
}
alSourcePlay(sources[ring].source);
lastUsed = ring;
lastUsed = nextIndex(ring);
return;
}
if (sources[ring].priority <= priority) {
if (sources[ring].priority > priority || (sources[ring].buffer != buffer && sources[ring].priority == priority)) {
if (nextBest) {
if (nextBest->priority > sources[ring].priority) {
if (nextBest->priority >= sources[ring].priority) {
nextBest = &sources[ring];
secIndex = ring;
}
@ -65,7 +67,9 @@ void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
}
if (nextBest) {
nextBest->priority = priority;
alSourcei(nextBest->source, AL_BUFFER, 0);
alSourcei(nextBest->source, AL_BUFFER, buffer);
nextBest->buffer = buffer;
if (pos != glm::vec3(0)) {
//alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 1);
alSourcefv(nextBest->source, AL_POSITION, glm::value_ptr(pos));
@ -86,6 +90,7 @@ void SoundManager::pollSources()
alGetSourcei(s.source, AL_SOURCE_STATE, &state);
if (state == AL_STOPPED) {
s.inUse = false;
s.buffer = 0;
alSourcei(s.source, AL_BUFFER, 0);
}
//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
// 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);
if (!data) {
LOG(ERROR, "Could not load weapon id '{}', falling back to pistol", id);
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())
weapon->attachScript(loadWeaponScript(data->script));
return weapon;
return std::move(weapon);
}
const unsigned ResourceManager::loadSoundEffect(const std::string& id)
@ -139,7 +139,6 @@ void ResourceManager::clearResources()
sprites.clear();
shaders.clear();
shaderIDs.clear();
weapons.clear();
tileSets.clear();
}

1
compile_flags.txt Normal file
View file

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