ADD: PlaySound when piece walks to its destination
This commit is contained in:
parent
a5643d794c
commit
64671363dc
@ -246,6 +246,7 @@ add_library(Engine STATIC
|
||||
engine/src/core/events/EventBus.cpp
|
||||
engine/src/core/events/EventBus.h
|
||||
engine/src/core/audio/ecs/PlaySoundComponent.h
|
||||
engine/src/core/animation/events/AnimationMarkerEvent.h
|
||||
)
|
||||
target_include_directories(Engine PUBLIC engine/src ${dr_libs_SOURCE_DIR})
|
||||
target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image OpenAL::OpenAL)
|
||||
|
||||
@ -15,6 +15,11 @@ namespace engine::animation {
|
||||
for (auto& [entity, animation] : m_registry.getPool<TransformAnimationComponent>()) {
|
||||
animation.time += deltaTime;
|
||||
|
||||
while (animation.nextMarkerIndex < animation.markers.size() && animation.markers[animation.nextMarkerIndex].time <= animation.time) {
|
||||
animation.markers[animation.nextMarkerIndex].callback();
|
||||
animation.nextMarkerIndex++;
|
||||
}
|
||||
|
||||
auto& transform = m_registry.getComponent<TransformComponent>(entity);
|
||||
|
||||
if (!animation.position.keys.empty()) {
|
||||
@ -30,6 +35,7 @@ namespace engine::animation {
|
||||
if (animation.time >= animation.duration) {
|
||||
if (animation.loop) {
|
||||
animation.time = 0.f;
|
||||
animation.nextMarkerIndex = 0;
|
||||
} else {
|
||||
if (animation.onFinished) {
|
||||
animation.onFinished();
|
||||
|
||||
@ -21,6 +21,11 @@ namespace engine::animation {
|
||||
};
|
||||
};
|
||||
|
||||
struct AnimationMarker {
|
||||
float time;
|
||||
std::function<void()> callback;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct AnimationTrack {
|
||||
@ -35,6 +40,9 @@ namespace engine::animation {
|
||||
AnimationTrack<glm::vec3> rotation;
|
||||
AnimationTrack<glm::vec3> scale;
|
||||
|
||||
std::vector<AnimationMarker> markers;
|
||||
size_t nextMarkerIndex = 0;
|
||||
|
||||
std::function<void()> onFinished;
|
||||
bool loop = false;
|
||||
bool finished = false;
|
||||
|
||||
18
engine/src/core/animation/events/AnimationMarkerEvent.h
Normal file
18
engine/src/core/animation/events/AnimationMarkerEvent.h
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by sebastian on 05.08.26.
|
||||
//
|
||||
|
||||
#ifndef COLORRACE_ANIMATIONMARKEREVENT_H
|
||||
#define COLORRACE_ANIMATIONMARKEREVENT_H
|
||||
#include <string>
|
||||
|
||||
#include "ecs/Entity.h"
|
||||
|
||||
namespace engine::animation {
|
||||
struct AnimationMarkerEvent {
|
||||
engine::Entity entity;
|
||||
std::string tag;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //COLORRACE_ANIMATIONMARKEREVENT_H
|
||||
@ -14,7 +14,6 @@ void engine::audio::AudioSystem::update(float deltaTime) const {
|
||||
for (auto& [entity, playSound] : m_registry.getPool<PlaySoundComponent>()) {
|
||||
auto& source = m_registry.getComponent<SoundSource>(entity);
|
||||
if (!playSound.started) {
|
||||
source.setBuffer(*playSound.soundBuffer);
|
||||
source.setGain(playSound.gain);
|
||||
source.play();
|
||||
playSound.started = true;
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
|
||||
namespace engine::audio {
|
||||
struct PlaySoundComponent {
|
||||
std::shared_ptr<SoundBuffer> soundBuffer;
|
||||
float gain = 1.f;
|
||||
bool started = false;
|
||||
bool blocking = false;
|
||||
|
||||
@ -13,8 +13,8 @@ namespace engine {
|
||||
|
||||
class DebugLayer: public Layer {
|
||||
public:
|
||||
DebugLayer(Camera& camera, engine::EntityRegistry& registry, Keyboard &keyboard, Mouse &mouse, std::shared_ptr<Model> sphereModel)
|
||||
: Layer(keyboard, mouse), m_entityRegistry(registry), m_sphereModel(std::move(sphereModel)), m_camera(camera) {
|
||||
DebugLayer(engine::EventBus<animation::AnimationMarkerEvent>& animationEventbus, Camera& camera, engine::EntityRegistry& registry, Keyboard &keyboard, Mouse &mouse, std::shared_ptr<Model> sphereModel)
|
||||
: Layer(keyboard, mouse, animationEventbus), m_entityRegistry(registry), m_sphereModel(std::move(sphereModel)), m_camera(camera) {
|
||||
}
|
||||
|
||||
void onUpdate(float deltaTime) override;
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#ifndef COLORRACE_LAYER_H
|
||||
#define COLORRACE_LAYER_H
|
||||
#include "core/animation/events/AnimationMarkerEvent.h"
|
||||
#include "core/events/EventBus.h"
|
||||
#include "core/inputsOutputs/context/InputContextStack.h"
|
||||
#include "core/inputsOutputs/inputs/Keyboard.h"
|
||||
#include "core/inputsOutputs/inputs/Mouse.h"
|
||||
@ -13,7 +15,7 @@
|
||||
namespace engine {
|
||||
class Layer {
|
||||
public:
|
||||
Layer(Keyboard& keyboard, Mouse& mouse) : m_keyboard(keyboard), m_mouse(mouse){};
|
||||
Layer(Keyboard& keyboard, Mouse& mouse, EventBus<animation::AnimationMarkerEvent>& animationEventBus) : m_keyboard(keyboard), m_mouse(mouse), m_animationEventBus(animationEventBus){};
|
||||
virtual ~Layer() = default;
|
||||
void onAttach(InputContextStack& inputStack);
|
||||
void onDetach(InputContextStack& inputStack);
|
||||
@ -26,12 +28,14 @@ namespace engine {
|
||||
InputContextStack& getInputStack() { return *m_inputStack; }
|
||||
Keyboard& getKeyboard() { return m_keyboard; }
|
||||
Mouse& getMouse() { return m_mouse; }
|
||||
EventBus<animation::AnimationMarkerEvent>& getAnimationEventBus() { return m_animationEventBus; }
|
||||
private:
|
||||
std::shared_ptr<InputContext> m_context;
|
||||
InputContextStack* m_inputStack = nullptr;
|
||||
|
||||
engine::Keyboard& m_keyboard;
|
||||
engine::Mouse& m_mouse;
|
||||
engine::EventBus<animation::AnimationMarkerEvent>& m_animationEventBus;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Layer.h"
|
||||
#include "core/animation/events/AnimationMarkerEvent.h"
|
||||
#include "core/events/EventBus.h"
|
||||
#include "loader/assets/AssetManager.h"
|
||||
#include "loader/assets/AssetRequests.h"
|
||||
@ -40,6 +41,7 @@ namespace engine {
|
||||
virtual std::vector<AssetRequest> getRequiredAssets() const { return {}; }
|
||||
protected:
|
||||
std::vector<std::unique_ptr<Layer>> m_layers;
|
||||
EventBus<animation::AnimationMarkerEvent>& getAnimationEventBus() { return m_animationMarkerEventBus; }
|
||||
|
||||
void addLayer(std::unique_ptr<Layer> layer);
|
||||
|
||||
@ -49,6 +51,9 @@ namespace engine {
|
||||
|
||||
engine::Keyboard& m_keyboard;
|
||||
engine::Mouse& m_mouse;
|
||||
|
||||
private:
|
||||
EventBus<animation::AnimationMarkerEvent> m_animationMarkerEventBus;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,9 @@
|
||||
|
||||
#include "../../engine/src/core/audio/ecs/PlaySoundComponent.h"
|
||||
#include "core/audio/ecs/BlockingSoundComponent.h"
|
||||
#include "ecs/standardComponents/TransformComponent.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
void ludo::AudioLayer::onUpdate(float deltaTime) {
|
||||
Layer::onUpdate(deltaTime);
|
||||
@ -20,13 +22,14 @@ void ludo::AudioLayer::onAttachImpl() {
|
||||
|
||||
auto rollingDiceSoundBuffer = m_assetManager.getSound("rolling_dice");
|
||||
m_diceSoundEntity = m_registry.createEntity();
|
||||
m_registry.addComponent<engine::audio::SoundSource>(m_diceSoundEntity, engine::audio::SoundSource());
|
||||
auto diceSoundSource = engine::audio::SoundSource();
|
||||
diceSoundSource.setBuffer(*rollingDiceSoundBuffer);
|
||||
m_registry.addComponent<engine::audio::SoundSource>(m_diceSoundEntity, std::move(diceSoundSource));
|
||||
|
||||
m_eventBus.subscribe([this, rollingDiceSoundBuffer](const ludo::LudoEvent& event) {
|
||||
std::visit([this, rollingDiceSoundBuffer]<typename T>(const T& e) {
|
||||
if constexpr (std::is_same_v<T, ludo::DiceRolledEvent>) {
|
||||
engine::audio::PlaySoundComponent playSound;
|
||||
playSound.soundBuffer = rollingDiceSoundBuffer;
|
||||
playSound.gain = 1.0f;
|
||||
playSound.blocking = true;
|
||||
m_registry.addComponent<engine::audio::PlaySoundComponent>(m_diceSoundEntity, playSound);
|
||||
@ -34,4 +37,22 @@ void ludo::AudioLayer::onAttachImpl() {
|
||||
}
|
||||
}, event);
|
||||
});
|
||||
|
||||
|
||||
|
||||
getAnimationEventBus().subscribe([this](const engine::animation::AnimationMarkerEvent& event) {
|
||||
if (event.tag == "step") {
|
||||
engine::audio::PlaySoundComponent playSound;
|
||||
auto& soundSource = this->m_registry.getComponent<engine::audio::SoundSource>(event.entity);
|
||||
playSound.gain = 1.0f;
|
||||
playSound.blocking = false;
|
||||
|
||||
auto& transform = this->m_registry.getComponent<engine::TransformComponent>(event.entity);
|
||||
|
||||
|
||||
soundSource.setPosition(transform.m_position.x, transform.m_position.y, transform.m_position.z);
|
||||
spdlog::info("Insert PlaySoundComponent for Entity {}", event.entity.value());
|
||||
this->m_registry.addComponent<engine::audio::PlaySoundComponent>(event.entity, playSound);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -19,8 +19,8 @@ namespace ludo {
|
||||
class AudioLayer :public engine::Layer {
|
||||
public:
|
||||
AudioLayer(engine::AssetManager& assetManager, engine::Keyboard &keyboard, engine::Mouse &mouse, std::shared_ptr<LudoGameMode> gameMode,
|
||||
engine::EntityRegistry& registry, engine::EventBus<LudoEvent>& eventBus)
|
||||
: Layer(keyboard, mouse), m_assetManager(assetManager), m_gameMode(std::move(gameMode)), m_registry(registry),
|
||||
engine::EntityRegistry& registry, engine::EventBus<LudoEvent>& eventBus, engine::EventBus<engine::animation::AnimationMarkerEvent>& animationEventbus)
|
||||
: Layer(keyboard, mouse, animationEventbus), m_assetManager(assetManager), m_gameMode(std::move(gameMode)), m_registry(registry),
|
||||
m_eventBus(eventBus), m_audioSystem(m_registry) {
|
||||
}
|
||||
|
||||
|
||||
@ -24,10 +24,10 @@
|
||||
|
||||
class GameLayer: public engine::Layer {
|
||||
public:
|
||||
GameLayer(std::shared_ptr<ludo::LudoGameMode> gameMode, engine::EntityRegistry& entityRegistry, std::shared_ptr<engine::Camera> cam, std::shared_ptr<engine::PointLight> light,
|
||||
engine::Keyboard& keyboard, engine::Mouse& mouse, std::shared_ptr<engine::Model> boardModel, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModdels)
|
||||
: Layer(keyboard, mouse), m_gameMode(std::move(gameMode)), m_entityRegistry(entityRegistry), m_camera(std::move(cam)), m_renderer(std::make_unique<engine::MeshRenderer>()),
|
||||
m_pointLight(std::move(light)), m_boardLayout(std::move(boardModel)), m_piecePresenter(m_entityRegistry, std::move(pieceModdels), m_boardLayout),
|
||||
GameLayer(engine::EventBus<engine::animation::AnimationMarkerEvent>& animationEventbus, std::shared_ptr<ludo::LudoGameMode> gameMode, engine::EntityRegistry& entityRegistry, std::shared_ptr<engine::Camera> cam, std::shared_ptr<engine::PointLight> light,
|
||||
engine::Keyboard& keyboard, engine::Mouse& mouse, std::shared_ptr<engine::Model> boardModel, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModdels, std::unordered_map<std::string, std::shared_ptr<engine::audio::SoundBuffer>> pieceSounds)
|
||||
: Layer(keyboard, mouse, animationEventbus), m_gameMode(std::move(gameMode)), m_entityRegistry(entityRegistry), m_camera(std::move(cam)), m_renderer(std::make_unique<engine::MeshRenderer>()),
|
||||
m_pointLight(std::move(light)), m_boardLayout(std::move(boardModel)), m_piecePresenter(animationEventbus, m_entityRegistry, std::move(pieceModdels), std::move(pieceSounds), m_boardLayout),
|
||||
m_pickingSystem(*m_camera), m_highlightSystem(*m_camera), m_animationSystem(m_entityRegistry) {
|
||||
for (auto playerID : m_gameMode->getPlayerOrder()) {
|
||||
if (playerID != m_localPlayer) {
|
||||
|
||||
@ -39,10 +39,12 @@ void GameScene::onEnter() {
|
||||
pieceModels["Green"] = assetManager->getModel("pawn_green");
|
||||
pieceModels["Yellow"] = assetManager->getModel("pawn_yellow");
|
||||
|
||||
addLayer(std::make_unique<ludo::AudioLayer>(*assetManager, m_keyboard, m_mouse, m_gameMode, entityRegistry, m_eventBus));
|
||||
addLayer(std::make_unique<engine::DebugLayer>(*m_camera, entityRegistry, m_keyboard, m_mouse, engine::SphereFactory::createUVSphere(1.0f)));
|
||||
addLayer(std::make_unique<GameLayer>(m_gameMode, entityRegistry, m_camera, m_pointLight, m_keyboard, m_mouse, assetManager->getModel("gameboard"), pieceModels));
|
||||
std::unordered_map<std::string, std::shared_ptr<engine::audio::SoundBuffer>> pieceSounds;
|
||||
pieceSounds["step"] = assetManager->getSound("pawn_step");
|
||||
|
||||
addLayer(std::make_unique<ludo::AudioLayer>(*assetManager, m_keyboard, m_mouse, m_gameMode, entityRegistry, m_eventBus, getAnimationEventBus()));
|
||||
addLayer(std::make_unique<engine::DebugLayer>(getAnimationEventBus(), *m_camera, entityRegistry, m_keyboard, m_mouse, engine::SphereFactory::createUVSphere(1.0f)));
|
||||
addLayer(std::make_unique<GameLayer>(getAnimationEventBus(), m_gameMode, entityRegistry, m_camera, m_pointLight, m_keyboard, m_mouse, assetManager->getModel("gameboard"), pieceModels, pieceSounds));
|
||||
}
|
||||
|
||||
void GameScene::onExit() {
|
||||
|
||||
@ -24,6 +24,13 @@ void ludo::PiecePresenter::spawnPieces(const ludo::LudoGameState &state) {
|
||||
m_registry.addComponent<engine::TransformComponent>(entity, transform);
|
||||
m_registry.addComponent<engine::MeshComponent>(entity, engine::MeshComponent(m_pieceModels[std::string(ludo::toString(piece.color))]));
|
||||
m_registry.addComponent<engine::PickableComponent>(entity, engine::PickableComponent());
|
||||
|
||||
auto soundSource = engine::audio::SoundSource();
|
||||
soundSource.setBuffer(*m_pieceSounds["step"]);
|
||||
soundSource.setPosition(transform.m_position.x, transform.m_position.y, transform.m_position.z);
|
||||
soundSource.setGain(1.0f);
|
||||
soundSource.setLooping(false);
|
||||
m_registry.addComponent<engine::audio::SoundSource>(entity, std::move(soundSource));
|
||||
m_pieceEntities.push_back(entity);
|
||||
}
|
||||
}
|
||||
@ -41,6 +48,7 @@ void ludo::PiecePresenter::onPieceMoved(const ludo::PieceMovedEvent &event, cons
|
||||
}
|
||||
|
||||
std::vector<engine::animation::Keyframe<glm::vec3>> keyframes;
|
||||
std::vector<engine::animation::AnimationMarker> animationMarkers;
|
||||
float time = 0;
|
||||
constexpr int kHopSubdivisions = 8; // Punkte zwischen den beiden Endpunkten
|
||||
constexpr float kHopHeight = 0.3f; // Sprunghöhe in Weltkoordinaten
|
||||
@ -64,6 +72,11 @@ void ludo::PiecePresenter::onPieceMoved(const ludo::PieceMovedEvent &event, cons
|
||||
time += 0.5f / (kHopSubdivisions + 1);
|
||||
}
|
||||
keyframes.emplace_back(time, to);
|
||||
animationMarkers.emplace_back(time, [this, entity]() {
|
||||
spdlog::info("Should play step");
|
||||
auto animationMarkerEvent = engine::animation::AnimationMarkerEvent(entity, "step");
|
||||
this->m_animationEventBus.publish(animationMarkerEvent);
|
||||
});
|
||||
time += 0.5f / (kHopSubdivisions + 1);
|
||||
}
|
||||
|
||||
@ -80,6 +93,7 @@ void ludo::PiecePresenter::onPieceMoved(const ludo::PieceMovedEvent &event, cons
|
||||
animationComponent.onFinished = [this, entity]() {
|
||||
m_registry.removeComponent<engine::animation::BlockingAnimationComponent>(entity);
|
||||
};
|
||||
animationComponent.markers = animationMarkers;
|
||||
|
||||
m_registry.addComponent<engine::animation::TransformAnimationComponent>(entity, animationComponent);
|
||||
m_registry.addComponent<engine::animation::BlockingAnimationComponent>(entity, engine::animation::BlockingAnimationComponent());
|
||||
|
||||
@ -5,9 +5,13 @@
|
||||
#ifndef COLORRACE_PIECEPRESENTER_H
|
||||
#define COLORRACE_PIECEPRESENTER_H
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "BoardLayout.h"
|
||||
#include "LudoGameState.h"
|
||||
#include "core/animation/events/AnimationMarkerEvent.h"
|
||||
#include "core/audio/SoundSource.h"
|
||||
#include "core/events/EventBus.h"
|
||||
#include "ecs/EntityRegistry.h"
|
||||
#include "loader/assets/AssetManager.h"
|
||||
#include "loader/models/Model.h"
|
||||
@ -16,8 +20,8 @@
|
||||
namespace ludo {
|
||||
class PiecePresenter {
|
||||
public:
|
||||
PiecePresenter(engine::EntityRegistry& registry, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModels, BoardLayout& layout)
|
||||
: m_registry(registry), m_pieceModels(std::move(pieceModels)), m_layout(layout) {}
|
||||
PiecePresenter(engine::EventBus<engine::animation::AnimationMarkerEvent>& animationEventbus, engine::EntityRegistry& registry, std::unordered_map<std::string, std::shared_ptr<engine::Model>> pieceModels, std::unordered_map<std::string, std::shared_ptr<engine::audio::SoundBuffer>> pieceSounds, BoardLayout& layout)
|
||||
: m_registry(registry), m_pieceModels(std::move(pieceModels)), m_layout(layout), m_animationEventBus(animationEventbus), m_pieceSounds(std::move(pieceSounds)) {}
|
||||
|
||||
void spawnPieces(const ludo::LudoGameState& state);
|
||||
void onPieceMoved(const ludo::PieceMovedEvent& event, const ludo::LudoGameState& state);
|
||||
@ -28,8 +32,10 @@ namespace ludo {
|
||||
private:
|
||||
engine::EntityRegistry& m_registry;
|
||||
std::unordered_map<std::string, std::shared_ptr<engine::Model>> m_pieceModels;
|
||||
std::unordered_map<std::string, std::shared_ptr<engine::audio::SoundBuffer>> m_pieceSounds;
|
||||
BoardLayout& m_layout;
|
||||
std::vector<engine::Entity> m_pieceEntities;
|
||||
engine::EventBus<engine::animation::AnimationMarkerEvent>& m_animationEventBus;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user