diff --git a/Resources/sounds/gun/mach_pew.ogg b/Resources/sounds/gun/mach_pew.ogg new file mode 100644 index 0000000..9f69035 Binary files /dev/null and b/Resources/sounds/gun/mach_pew.ogg differ diff --git a/Resources/sounds/gun/reload.ogg b/Resources/sounds/gun/reload.ogg new file mode 100644 index 0000000..7738d87 Binary files /dev/null and b/Resources/sounds/gun/reload.ogg differ diff --git a/Resources/sounds/gun_effects.xml b/Resources/sounds/gun_effects.xml index ce9f250..187b7ec 100644 --- a/Resources/sounds/gun_effects.xml +++ b/Resources/sounds/gun_effects.xml @@ -6,5 +6,9 @@ + + + + diff --git a/YuppleMayham/include/gameplay/gameactor.h b/YuppleMayham/include/gameplay/gameactor.h index de16286..47a66e7 100644 --- a/YuppleMayham/include/gameplay/gameactor.h +++ b/YuppleMayham/include/gameplay/gameactor.h @@ -5,17 +5,17 @@ #include #include #include +#include #include "gameplay/entity.h" +#include "gameplay/weapons/weapon.h" #include "utility/mousestate.h" #include 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); - void pickupWeapon(std::shared_ptr weapon); + void pickupWeapon(std::unique_ptr weapon); void update(double deltaTime) override; void draw() override; - const std::shared_ptr getHeldWeapon() const; + Weapon* getHeldWeapon() const; + std::span 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>; - using weapon_vector_t = std::vector>; - - component_vector_t components; - weapon_vector_t weapons; + std::vector> components; + std::vector> weapons; + std::vector weaponCache; size_t currentWeaponIndex = 0; ISceneContext* sceneContext; }; -#endif //_H_GAMEACTOR_H \ No newline at end of file +#endif //_H_GAMEACTOR_H diff --git a/YuppleMayham/include/gameplay/weapons/weapon.h b/YuppleMayham/include/gameplay/weapons/weapon.h index 0994e68..8cf1047 100644 --- a/YuppleMayham/include/gameplay/weapons/weapon.h +++ b/YuppleMayham/include/gameplay/weapons/weapon.h @@ -24,7 +24,7 @@ class WeaponScript; struct PhysicsComponent; struct WeaponData; -class Weapon : public Entity, public std::enable_shared_from_this +class Weapon : public Entity { public: Weapon(const WeaponData* data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager); diff --git a/YuppleMayham/include/sound/soundmanager.h b/YuppleMayham/include/sound/soundmanager.h index bfde6c0..33e947e 100644 --- a/YuppleMayham/include/sound/soundmanager.h +++ b/YuppleMayham/include/sound/soundmanager.h @@ -15,6 +15,7 @@ public: private: struct AudioSource { ALuint source; + ALuint buffer; bool inUse; int priority; }; diff --git a/YuppleMayham/include/utility/resourcemanager.h b/YuppleMayham/include/utility/resourcemanager.h index 23016ea..a5af8ac 100644 --- a/YuppleMayham/include/utility/resourcemanager.h +++ b/YuppleMayham/include/utility/resourcemanager.h @@ -43,7 +43,7 @@ public: const unsigned loadSoundEffect (const std::string& id); std::unique_ptr loadAIScript (const std::string& path); std::unique_ptr loadWeaponScript (const std::string& path); - std::shared_ptr loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID); + std::unique_ptr loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID); std::shared_ptr 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 shaderIDs; std::unordered_map> sounds; std::unordered_map> sprites; - std::unordered_map> weapons; + //std::unordered_map> weapons; //std::unordered_map scripts; std::unordered_map> backgrounds; std::unordered_map> tileSets; diff --git a/YuppleMayham/src/gameplay/gameactor.cpp b/YuppleMayham/src/gameplay/gameactor.cpp index b1cc8f8..be45128 100644 --- a/YuppleMayham/src/gameplay/gameactor.cpp +++ b/YuppleMayham/src/gameplay/gameactor.cpp @@ -16,18 +16,24 @@ void GameActor::addComponent(std::unique_ptr component) components.push_back(std::move(component)); } -const std::shared_ptr 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) +std::span GameActor::getAllWeapons() +{ + return weaponCache; +} + +void GameActor::pickupWeapon(std::unique_ptr 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){ entityid, newDir }); + eventManager->notify({ 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){ entityid }); + event->notify({ entityid }); } wasMoving = true; } else if (!isMoving && wasMoving) { if (auto event = sceneContext->getEventManager().lock()) { - event->notify((EntityStopEvent){ entityid }); + event->notify({ 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){0.01f, 0.8f}); - gEvent->notify((ScreenBlurEvent){1.f, 0.8f}); + gEvent->notify({0.01f, 0.8f}); + gEvent->notify({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){ entityid, getDirectionFromRotation(newRotation) }); + event->notify({ entityid, getDirectionFromRotation(newRotation) }); } } //setRotation(glm::degrees(glm::atan(direction.y, direction.x))); diff --git a/YuppleMayham/src/gameplay/scene.cpp b/YuppleMayham/src/gameplay/scene.cpp index ff42dc9..670a2a2 100644 --- a/YuppleMayham/src/gameplay/scene.cpp +++ b/YuppleMayham/src/gameplay/scene.cpp @@ -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) //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); } }); diff --git a/YuppleMayham/src/gameplay/weapons/weapon.cpp b/YuppleMayham/src/gameplay/weapons/weapon.cpp index ce48c6a..8926315 100644 --- a/YuppleMayham/src/gameplay/weapons/weapon.cpp +++ b/YuppleMayham/src/gameplay/weapons/weapon.cpp @@ -119,9 +119,9 @@ void Weapon::hookEventManager(std::weak_ptr eventManager) } if (auto event = this->eventManager.lock()) { - std::weak_ptr selfWeak = shared_from_this(); - event->subscribe([selfWeak](const AnimationFinishedEvent& e) { - if (auto self = selfWeak.lock()) { + auto self = this; + event->subscribe([self](const AnimationFinishedEvent& e) { + if (self) { if (e.entityid == self->entityid && e.animType == "reload") { if (self->reloading) diff --git a/YuppleMayham/src/sound/engine.cpp b/YuppleMayham/src/sound/engine.cpp index e8031fc..65d217c 100644 --- a/YuppleMayham/src/sound/engine.cpp +++ b/YuppleMayham/src/sound/engine.cpp @@ -28,15 +28,25 @@ void AudioEngine::hookSceneManager(std::weak_ptr _events) sceneEventManager = _events; if (auto weak = sceneEventManager.lock()) { std::weak_ptr weakSelf = shared_from_this(); - weak->subscribe([weakSelf](const EntityFireEvent& e){ + auto play_sound = [weakSelf](const std::string& id, int priority, const std::optional& 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([weakSelf,play_sound](const EntityFireEvent& e){ + play_sound(e.weaponType + "/shoot", 10, e.firePosition); + }); + weak->subscribe([weakSelf,play_sound](const EntityReloadEvent& e) { + play_sound(e.weaponType + "/reload", 9, e.position); }); } } diff --git a/YuppleMayham/src/sound/soundmanager.cpp b/YuppleMayham/src/sound/soundmanager.cpp index 44c754c..8e1b13f 100644 --- a/YuppleMayham/src/sound/soundmanager.cpp +++ b/YuppleMayham/src/sound/soundmanager.cpp @@ -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) diff --git a/YuppleMayham/src/utility/resourcemanager.cpp b/YuppleMayham/src/utility/resourcemanager.cpp index 202eb89..8f19ff9 100644 --- a/YuppleMayham/src/utility/resourcemanager.cpp +++ b/YuppleMayham/src/utility/resourcemanager.cpp @@ -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 ResourceManager::loadWeapon(const std::string& id, const unsigned weaponShaderID, const unsigned bulletShaderID) +std::unique_ptr 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(data, weaponShaderID, bulletShaderID, this); + auto weapon = std::make_unique(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(); } diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..e23b2ae --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1 @@ +-std=c++20