aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2020-05-09 09:40:59 -0400
committerClyne Sullivan <clyne@bitgloo.com>2020-05-09 09:40:59 -0400
commitf461087223a80cd06619517e355690654f406d63 (patch)
treea5f5d573bec36f63284438c72157699f3a8fed98
parent1c52ee2e02bc3c09e7cac3b20c81c910b7151144 (diff)
parent3fb5e6b1eca24e536f8ab1130a7e4bd9c418fa41 (diff)
Merge branch 'audio'
-rw-r--r--Assets/boing.wavbin0 -> 302628 bytes
-rw-r--r--Assets/jump.wavbin0 -> 151716 bytes
-rw-r--r--Makefile2
-rw-r--r--Scripts/init.lua8
-rw-r--r--src/audio.cpp110
-rw-r--r--src/audio.hpp60
-rw-r--r--src/components/Audio.hpp56
-rw-r--r--src/engine.cpp6
-rw-r--r--src/script.cpp10
9 files changed, 251 insertions, 1 deletions
diff --git a/Assets/boing.wav b/Assets/boing.wav
new file mode 100644
index 0000000..088963d
--- /dev/null
+++ b/Assets/boing.wav
Binary files differ
diff --git a/Assets/jump.wav b/Assets/jump.wav
new file mode 100644
index 0000000..b9849ab
--- /dev/null
+++ b/Assets/jump.wav
Binary files differ
diff --git a/Makefile b/Makefile
index dcbac2b..357d7ff 100644
--- a/Makefile
+++ b/Makefile
@@ -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();