diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2020-05-09 09:40:59 -0400 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2020-05-09 09:40:59 -0400 |
commit | f461087223a80cd06619517e355690654f406d63 (patch) | |
tree | a5f5d573bec36f63284438c72157699f3a8fed98 | |
parent | 1c52ee2e02bc3c09e7cac3b20c81c910b7151144 (diff) | |
parent | 3fb5e6b1eca24e536f8ab1130a7e4bd9c418fa41 (diff) |
Merge branch 'audio'
-rw-r--r-- | Assets/boing.wav | bin | 0 -> 302628 bytes | |||
-rw-r--r-- | Assets/jump.wav | bin | 0 -> 151716 bytes | |||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Scripts/init.lua | 8 | ||||
-rw-r--r-- | src/audio.cpp | 110 | ||||
-rw-r--r-- | src/audio.hpp | 60 | ||||
-rw-r--r-- | src/components/Audio.hpp | 56 | ||||
-rw-r--r-- | src/engine.cpp | 6 | ||||
-rw-r--r-- | src/script.cpp | 10 |
9 files changed, 251 insertions, 1 deletions
diff --git a/Assets/boing.wav b/Assets/boing.wav Binary files differnew file mode 100644 index 0000000..088963d --- /dev/null +++ b/Assets/boing.wav diff --git a/Assets/jump.wav b/Assets/jump.wav Binary files differnew file mode 100644 index 0000000..b9849ab --- /dev/null +++ b/Assets/jump.wav @@ -37,7 +37,7 @@ DEPEXT = d LIBDIR = lib LIBS = -L$(LIBDIR) -lSDL2 -lpthread -lentityx -lluajit -ldl -lGLEW -lGL \ - -lSDL2_image -lSOIL -lfreetype + -lSDL2_image -lSOIL -lfreetype -lopenal -lalut CXXFLAGS = -ggdb -std=c++17 -Wall -Wextra -Werror -pedantic \ -Wno-class-memaccess -Wno-implicit-fallthrough -m64 diff --git a/Scripts/init.lua b/Scripts/init.lua index dc5093b..572f722 100644 --- a/Scripts/init.lua +++ b/Scripts/init.lua @@ -21,6 +21,7 @@ player = { end, JumpKeyPressed = function(self) if self.Physics.standing == true then + game.play(self.Position, self.Audio) self.Velocity.y = self.Velocity.y + 9 end end, @@ -37,6 +38,9 @@ player = { }, Physics = 0, Name = "bord", + Audio = { + file = "Assets/jump.wav" + }, hellotrue = true, hellofalse = false, Render = { @@ -76,10 +80,14 @@ ball = { }, Idle = function(self) if self.Physics.standing == true then + game.play(self.Position, self.Audio) self.Velocity.y = self.Velocity.y + 15 self.Velocity.x = math.random(-1, 1); end end, + Audio = { + file = "Assets/boing.wav" + }, } npc = { diff --git a/src/audio.cpp b/src/audio.cpp new file mode 100644 index 0000000..7a5934f --- /dev/null +++ b/src/audio.cpp @@ -0,0 +1,110 @@ +/** + * @file audio.cpp + * Handles audio loading and playback + * + * Copyright (C) 2019 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "audio.hpp" +#include "components/Player.hpp" + +#include <AL/alut.h> +#include <iostream> + +AudioSystem::AudioSystem(void) : + device(nullptr, [](ALCdevice *d) { alcCloseDevice(d); }), + context(nullptr, [](ALCcontext *c) { alcDestroyContext(c); }) {} + +AudioSystem::~AudioSystem(void) +{ + alutExit(); + + // Delete context before device + alcMakeContextCurrent(nullptr); + context.reset(); + device.reset(); +} + +void AudioSystem::configure([[maybe_unused]] entityx::EntityManager& entities, + entityx::EventManager& events) +{ + events.subscribe<entityx::ComponentAddedEvent<Audio>>(*this); + events.subscribe<entityx::ComponentRemovedEvent<Audio>>(*this); + + // Access device + device.reset(alcOpenDevice(nullptr)); + if (!device) + return; // TODO Uh oh + + // Create context + context.reset(alcCreateContext(device.get(), nullptr)); + if (!alcMakeContextCurrent(context.get())) + return; // TODO Another uh oh + + if (alutInitWithoutContext(nullptr, nullptr) != AL_TRUE) + return; // TODO Third uh oh + + // Set up listener + ALfloat listenerOri[] = { 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }; + alListener3f(AL_POSITION, 0, 0, 0.0f); + alListener3f(AL_VELOCITY, 0, 0, 0); + alListenerfv(AL_ORIENTATION, listenerOri); + + alDistanceModel(AL_LINEAR_DISTANCE); +} + +void AudioSystem::update(entityx::EntityManager& entities, + [[maybe_unused]] entityx::EventManager& events, + [[maybe_unused]] entityx::TimeDelta dt) +{ + entities.each<Player, Position>( + []([[maybe_unused]] entityx::Entity e, + [[maybe_unused]] Player& p, + Position &pos) + { + alListener3f(AL_POSITION, pos.x, pos.y, 0.0f); + }); +} + +void AudioSystem::receive(const entityx::ComponentAddedEvent<Audio>& cae) +{ + alGenSources(1, const_cast<ALuint*>(&cae.component->source)); + //alGenBuffers(1, const_cast<ALuint*>(&cae.component->buffer)); + + if (auto buf = alutCreateBufferFromFile(cae.component->fileName.c_str()); + buf != AL_NONE) { + const_cast<Audio*>(cae.component.get())->buffer = buf; + alSourcei(cae.component->source, AL_BUFFER, buf); + // TODO Do these values need to be scaled to the world or window? + alSourcef(cae.component->source, AL_MAX_DISTANCE, 25); + alSourcef(cae.component->source, AL_REFERENCE_DISTANCE, 2); + + std::cout << "Loaded audio: " << cae.component->fileName << std::endl; + } +} + +void AudioSystem::receive(const entityx::ComponentRemovedEvent<Audio>& cae) +{ + alDeleteBuffers(1, &cae.component->buffer); + alDeleteSources(1, &cae.component->source); +} + +void AudioSystem::playSound(const Position& pos, const Audio& audio) +{ + alSource3f(audio.source, AL_POSITION, pos.x, pos.y, 0); + alSourcePlay(audio.source); +} + diff --git a/src/audio.hpp b/src/audio.hpp new file mode 100644 index 0000000..7a2076a --- /dev/null +++ b/src/audio.hpp @@ -0,0 +1,60 @@ +/** + * @file audio.hpp + * Handles audio loading and playback + * + * Copyright (C) 2019 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef SYSTEM_AUDIO_HPP_ +#define SYSTEM_AUDIO_HPP_ + +#include <AL/alut.h> +#include <entityx/entityx.h> + +#include <components/Audio.hpp> +#include <components/Position.hpp> + +class AudioSystem : public entityx::System<AudioSystem>, + public entityx::Receiver<AudioSystem> +{ +private: + std::unique_ptr<ALCdevice, void (*)(ALCdevice *)> device; + std::unique_ptr<ALCcontext, void (*)(ALCcontext *)> context; + +public: + AudioSystem(void); + ~AudioSystem(void); + + /** + * Prepares the system for running. + */ + void configure(entityx::EntityManager& entities, + entityx::EventManager& events) final; + + /** + * Updates the render system. + */ + void update(entityx::EntityManager& entities, + entityx::EventManager& events, + entityx::TimeDelta dt) final; + + void receive(const entityx::ComponentAddedEvent<Audio>& cae); + void receive(const entityx::ComponentRemovedEvent<Audio>& cae); + + void playSound(const Position& pos, const Audio& audio); +}; + +#endif // SYSTEM_AUDIO_HPP_ + diff --git a/src/components/Audio.hpp b/src/components/Audio.hpp new file mode 100644 index 0000000..a97b235 --- /dev/null +++ b/src/components/Audio.hpp @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2019 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef COMPONENT_AUDIO_HPP_ +#define COMPONENT_AUDIO_HPP_ + +#include <AL/al.h> + +#include "Component.hpp" + +struct Audio : Component<Audio> +{ +public: + std::string fileName; + ALuint source; + ALuint buffer; + + Audio(std::string _fileName = "") : + fileName(_fileName), source(0), buffer(0) {} + + Audio FromLua(sol::object ref) + { + if (ref.get_type() == sol::type::table) { + sol::table tab = ref; + if (tab["file"] != nullptr) + this->fileName = tab["file"]; + } else { + throw std::string("Audio table not formatted properly"); + } + + return *this; + } + + void serialize([[maybe_unused]] cereal::JSONOutputArchive& ar) final {} + void serialize([[maybe_unused]] cereal::JSONInputArchive& ar) final {} + + std::string serializeName(void) const final { + return "Audio"; + } +}; + +#endif // COMPONENT_AUDIO_HPP_ + diff --git a/src/engine.cpp b/src/engine.cpp index 81e0272..dc0c481 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -19,6 +19,7 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#include "audio.hpp" #include "config.hpp" #include "engine.hpp" #include "gamestate.hpp" @@ -54,6 +55,7 @@ int Engine::init(void) systems.add<ScriptSystem>(entities, *(systems.system<WorldSystem>().get())); systems.add<PhysicsSystem>(); systems.add<TextSystem>(); + systems.add<AudioSystem>(); systems.configure(); // Load game script and entity data @@ -64,6 +66,9 @@ int Engine::init(void) script->addToGameNamespace("puts", bindInstance(&TextSystem::put, systems.system<TextSystem>().get())); + script->addToGameNamespace("play", + bindInstance(&AudioSystem::playSound, + systems.system<AudioSystem>().get())); script->init(); @@ -115,6 +120,7 @@ void Engine::logicLoop(void) }); } + systems.update<AudioSystem>(dt); std::this_thread::yield(); } } diff --git a/src/script.cpp b/src/script.cpp index 0f940d3..9fae1c9 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -75,6 +75,7 @@ void ScriptSystem::doFile(void) /******************** * SCRIPT PARSING * ********************/ +#include <components/Audio.hpp> #include <components/EventListener.hpp> #include <components/Position.hpp> #include <components/Player.hpp> @@ -121,6 +122,10 @@ void ScriptSystem::scriptExport(void) sol::constructors<Physics(void), Physics()>(), "standing", &Physics::standing); + lua.new_usertype<Audio>("Audio", + sol::constructors<Audio(std::string)>(), + "file", &Audio::fileName); + lua.new_usertype<World>("World", sol::constructors<World(sol::object), World(void)>(), "Generate", &World::generate, @@ -168,6 +173,11 @@ sol::table ScriptSystem::spawn(sol::object param) e.assign<Name>(Name().FromLua(tab["Name"])).get(); } + if (tab["Audio"] != nullptr) { + (*toRet)["Audio"] = + e.assign<Audio>(Audio().FromLua(tab["Audio"])).get(); + } + if (tab["Render"] != nullptr) { if (!e.has_component<Position>()) // Position must exist for render (*toRet)["Position"] = e.assign<Position>().get(); |