From 7919f7f69b0abd54a6df92f34e1392b84dae3669 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Mon, 30 Sep 2019 15:13:37 -0400
Subject: created base audiosystem

---
 src/audio.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/audio.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)
 create mode 100644 src/audio.cpp
 create mode 100644 src/audio.hpp

(limited to 'src')

diff --git a/src/audio.cpp b/src/audio.cpp
new file mode 100644
index 0000000..7dec4c3
--- /dev/null
+++ b/src/audio.cpp
@@ -0,0 +1,51 @@
+/**
+ * @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"
+
+AudioSystem::AudioSystem(void) :
+    device(nullptr, [](ALCdevice *d) { alcCloseDevice(d); }),
+    context(nullptr, [](ALCcontext *c) { alcDestroyContext(c); }) {}
+
+AudioSystem::~AudioSystem(void)
+{
+    // Delete context before device
+    context.get_deleter()(context.get());
+}
+
+void AudioSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
+                            [[maybe_unused]] entityx::EventManager& events)
+{
+    // 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
+}
+
+void AudioSystem::update([[maybe_unused]] entityx::EntityManager& entities,
+                         [[maybe_unused]] entityx::EventManager& events,
+                         [[maybe_unused]] entityx::TimeDelta dt)
+{}
+
diff --git a/src/audio.hpp b/src/audio.hpp
new file mode 100644
index 0000000..4d617c7
--- /dev/null
+++ b/src/audio.hpp
@@ -0,0 +1,52 @@
+/**
+ * @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>
+
+class AudioSystem : public entityx::System<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;
+};
+
+#endif // SYSTEM_AUDIO_HPP_
+
-- 
cgit v1.2.3


From bebc6e955114a0907c43df9a9c00f22b1f743446 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Mon, 30 Sep 2019 15:29:49 -0400
Subject: created Audio component

---
 src/audio.cpp            | 18 ++++++++++++++++--
 src/audio.hpp            |  9 +++++++--
 src/components/Audio.hpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 4 deletions(-)
 create mode 100644 src/components/Audio.hpp

(limited to 'src')

diff --git a/src/audio.cpp b/src/audio.cpp
index 7dec4c3..975cfce 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -27,12 +27,16 @@ AudioSystem::AudioSystem(void) :
 AudioSystem::~AudioSystem(void)
 {
     // Delete context before device
-    context.get_deleter()(context.get());
+    context.reset();
+    device.reset();
 }
 
 void AudioSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
-                            [[maybe_unused]] entityx::EventManager& events)
+                            entityx::EventManager& events)
 {
+    events.subscribe<entityx::ComponentAddedEvent<Audio>>(*this);
+    events.subscribe<entityx::ComponentRemovedEvent<Audio>>(*this);
+
     // Access device
     device.reset(alcOpenDevice(nullptr));
     if (!device)
@@ -49,3 +53,13 @@ void AudioSystem::update([[maybe_unused]] entityx::EntityManager& entities,
                          [[maybe_unused]] entityx::TimeDelta dt)
 {}
 
+void AudioSystem::receive(const entityx::ComponentAddedEvent<Audio>& cae)
+{
+    alGenSources(1, const_cast<ALuint*>(&cae.component->source));
+}
+
+void AudioSystem::receive(const entityx::ComponentRemovedEvent<Audio>& cae)
+{
+    alDeleteSources(1, &cae.component->source);
+}
+
diff --git a/src/audio.hpp b/src/audio.hpp
index 4d617c7..97fff99 100644
--- a/src/audio.hpp
+++ b/src/audio.hpp
@@ -21,10 +21,12 @@
 #define SYSTEM_AUDIO_HPP_
 
 #include <AL/alut.h>
-
 #include <entityx/entityx.h>
 
-class AudioSystem : public entityx::System<AudioSystem>
+#include <components/Audio.hpp>
+
+class AudioSystem : public entityx::System<AudioSystem>,
+                    public entityx::Receiver<AudioSystem>
 {
 private:
     std::unique_ptr<ALCdevice, void (*)(ALCdevice *)> device;
@@ -46,6 +48,9 @@ public:
     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);
 };
 
 #endif // SYSTEM_AUDIO_HPP_
diff --git a/src/components/Audio.hpp b/src/components/Audio.hpp
new file mode 100644
index 0000000..3f7296d
--- /dev/null
+++ b/src/components/Audio.hpp
@@ -0,0 +1,47 @@
+/**
+ * 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:
+    ALuint source;
+
+    Audio(ALuint _source = 0) :
+        source(_source) {}
+
+    Audio FromLua([[maybe_unused]] sol::object ref)
+    {
+        // TODO load from file name?
+        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_
+
-- 
cgit v1.2.3


From af39f2e08b0503db723ae707a5c7278d8c85f812 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Tue, 1 Oct 2019 20:50:28 -0400
Subject: Audio component loading, getting ready to play

---
 Assets/jump.wav          | Bin 0 -> 303194 bytes
 Scripts/init.lua         |   3 +++
 src/audio.cpp            |  25 +++++++++++++++++++++++++
 src/audio.hpp            |   3 +++
 src/components/Audio.hpp |  17 +++++++++++++----
 src/engine.cpp           |   2 ++
 src/script.cpp           |  10 ++++++++++
 7 files changed, 56 insertions(+), 4 deletions(-)
 create mode 100644 Assets/jump.wav

(limited to 'src')

diff --git a/Assets/jump.wav b/Assets/jump.wav
new file mode 100644
index 0000000..1cd1681
Binary files /dev/null and b/Assets/jump.wav differ
diff --git a/Scripts/init.lua b/Scripts/init.lua
index ec9e350..ea5a833 100644
--- a/Scripts/init.lua
+++ b/Scripts/init.lua
@@ -37,6 +37,9 @@ player = {
     },
     Physics = 0,
     Name = "bord",
+    Audio = {
+        file = "Assets/jump.wav"
+    },
     hellotrue = true,
     hellofalse = false,
     Render = {
diff --git a/src/audio.cpp b/src/audio.cpp
index 975cfce..8bb1413 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -20,13 +20,19 @@
 
 #include "audio.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();
 }
@@ -46,6 +52,9 @@ void AudioSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
     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
 }
 
 void AudioSystem::update([[maybe_unused]] entityx::EntityManager& entities,
@@ -56,10 +65,26 @@ void AudioSystem::update([[maybe_unused]] entityx::EntityManager& entities,
 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);
+
+        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
index 97fff99..7a2076a 100644
--- a/src/audio.hpp
+++ b/src/audio.hpp
@@ -24,6 +24,7 @@
 #include <entityx/entityx.h>
 
 #include <components/Audio.hpp>
+#include <components/Position.hpp>
 
 class AudioSystem : public entityx::System<AudioSystem>,
                     public entityx::Receiver<AudioSystem>
@@ -51,6 +52,8 @@ public:
 
     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
index 3f7296d..a97b235 100644
--- a/src/components/Audio.hpp
+++ b/src/components/Audio.hpp
@@ -24,14 +24,23 @@
 struct Audio : Component<Audio>
 {
 public:
+    std::string fileName;
     ALuint source;
+    ALuint buffer;
 
-    Audio(ALuint _source = 0) :
-        source(_source) {}
+    Audio(std::string _fileName = "") :
+        fileName(_fileName), source(0), buffer(0) {}
 
-    Audio FromLua([[maybe_unused]] sol::object ref)
+    Audio FromLua(sol::object ref)
     {
-        // TODO load from file name?
+        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;
     }
 
diff --git a/src/engine.cpp b/src/engine.cpp
index b1d9a56..3fc4fdd 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
diff --git a/src/script.cpp b/src/script.cpp
index 6cda627..20011b4 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>
@@ -127,6 +128,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,
@@ -173,6 +178,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();
-- 
cgit v1.2.3


From 9d79ba461a399ce5c211dc7ca2fc49b8934c1cd7 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Tue, 1 Oct 2019 20:57:25 -0400
Subject: sound on jump

---
 Scripts/init.lua | 1 +
 src/engine.cpp   | 3 +++
 2 files changed, 4 insertions(+)

(limited to 'src')

diff --git a/Scripts/init.lua b/Scripts/init.lua
index ea5a833..d09fb14 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,
diff --git a/src/engine.cpp b/src/engine.cpp
index ed5ba07..c6bec27 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -66,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();
     
 
-- 
cgit v1.2.3


From eed19ec73698c8180a51c33fa56c7cfe7c0e60f0 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Thu, 3 Oct 2019 10:24:01 -0400
Subject: positional audio working

---
 Assets/boing.wav | Bin 605018 -> 302628 bytes
 Assets/jump.wav  | Bin 303194 -> 151716 bytes
 src/audio.cpp    |  18 ++++++++++++++++--
 src/engine.cpp   |   1 +
 4 files changed, 17 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/Assets/boing.wav b/Assets/boing.wav
index a142197..088963d 100644
Binary files a/Assets/boing.wav and b/Assets/boing.wav differ
diff --git a/Assets/jump.wav b/Assets/jump.wav
index 1cd1681..b9849ab 100644
Binary files a/Assets/jump.wav and b/Assets/jump.wav differ
diff --git a/src/audio.cpp b/src/audio.cpp
index 8bb1413..2f14c97 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -19,6 +19,7 @@
  */
 
 #include "audio.hpp"
+#include "components/Player.hpp"
 
 #include <AL/alut.h>
 #include <iostream>
@@ -55,12 +56,25 @@ void AudioSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
 
     if (alutInitWithoutContext(nullptr, nullptr) != AL_TRUE)
         return; // TODO Third uh oh
+
+    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);
 }
 
-void AudioSystem::update([[maybe_unused]] entityx::EntityManager& entities,
+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)
 {
diff --git a/src/engine.cpp b/src/engine.cpp
index c6bec27..dc0c481 100644
--- a/src/engine.cpp
+++ b/src/engine.cpp
@@ -120,6 +120,7 @@ void Engine::logicLoop(void)
             });
         }
 
+        systems.update<AudioSystem>(dt);
         std::this_thread::yield();
     }
 }
-- 
cgit v1.2.3


From 52cfc041425a80ffd7ec63b3aaa94289ec61a977 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Thu, 3 Oct 2019 12:47:40 -0400
Subject: controlled sound fading

---
 src/audio.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'src')

diff --git a/src/audio.cpp b/src/audio.cpp
index 2f14c97..7a5934f 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -57,10 +57,13 @@ void AudioSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
     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,
@@ -85,6 +88,9 @@ void AudioSystem::receive(const entityx::ComponentAddedEvent<Audio>& cae)
         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;
     }
-- 
cgit v1.2.3


From da0913771538fd9b1ca538615fd9aa0388608466 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Sat, 9 May 2020 09:42:18 -0400
Subject: Merge audio; handle mouse events

---
 Scripts/init.lua                 |  5 +++
 src/components/EventListener.hpp |  5 ++-
 src/input.cpp                    | 83 ++++++++++++++++++++++++++++++++++++++++
 src/input.hpp                    | 33 ++++++----------
 src/player.cpp                   | 42 +++++++++-----------
 5 files changed, 120 insertions(+), 48 deletions(-)
 create mode 100644 src/input.cpp

(limited to 'src')

diff --git a/Scripts/init.lua b/Scripts/init.lua
index 572f722..66fbcb1 100644
--- a/Scripts/init.lua
+++ b/Scripts/init.lua
@@ -111,6 +111,11 @@ npc = {
         b = 1.0,
         strength = 0.5
     },
+    EventListeners = {
+        MousePressed = function(self, x, y, button)
+            self.Velocity.y = 3.0;
+        end
+    },
     Idle = function(self)
 		if (self.visibleTick == 0) then
 			self.visibleTick = math.random(40, 60)
diff --git a/src/components/EventListener.hpp b/src/components/EventListener.hpp
index 77a004e..c39b6ad 100644
--- a/src/components/EventListener.hpp
+++ b/src/components/EventListener.hpp
@@ -42,10 +42,11 @@ public:
         return *this;
     }
 
-    void tryListener(const std::string& name, sol::table& self)
+    template<typename... Args>
+    void tryListener(const std::string& name, sol::table& self, Args... args)
     {
         if (listeners[name] == sol::type::function)
-            listeners[name](self);
+            listeners[name](self, args...);
     }
 
     void serialize([[maybe_unused]] cereal::JSONOutputArchive& ar) final {}
diff --git a/src/input.cpp b/src/input.cpp
new file mode 100644
index 0000000..21959c1
--- /dev/null
+++ b/src/input.cpp
@@ -0,0 +1,83 @@
+/**
+ * @file input.cpp
+ * Handles user input received from SDL.
+ *
+ * Copyright (C) 2020 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include "input.hpp"
+
+#include "components/EventListener.hpp"
+#include "components/Script.hpp"
+
+InputSystem::InputSystem() :
+    isMouseDown(false) {}
+
+/**
+ * Prepares the system for running.
+ */
+void InputSystem::configure([[maybe_unused]] entityx::EntityManager& entities,
+                            [[maybe_unused]] entityx::EventManager& events) {}
+
+/**
+ * Updates the system by checking for SDL events.
+ */
+void InputSystem::update(entityx::EntityManager& entities,
+            entityx::EventManager& events,
+            [[maybe_unused]] entityx::TimeDelta dt)
+{
+    for (SDL_Event event; SDL_PollEvent(&event);) {
+        switch (event.type) {
+        case SDL_KEYUP:
+            if (auto key = event.key; key.repeat == 0)
+                events.emit<KeyUpEvent>(key.keysym);
+            break;
+        case SDL_KEYDOWN:
+            if (auto key = event.key; key.repeat == 0)
+                events.emit<KeyDownEvent>(key.keysym);
+            break;
+        case SDL_MOUSEBUTTONDOWN:
+            if (!isMouseDown) {
+                isMouseDown = true;
+                entities.each<EventListener>(
+                    [&event](entityx::Entity e, EventListener& el) {
+                        el.tryListener("MousePressed",
+                            e.component<Scripted>()->caller,
+                            event.button.x,
+                            event.button.y,
+                            event.button.button);
+                    });
+            }
+            break;
+        case SDL_MOUSEBUTTONUP:
+            if (isMouseDown) {
+                isMouseDown = false;
+                entities.each<EventListener>(
+                    [&event](entityx::Entity e, EventListener& el) {
+                        el.tryListener("MouseReleased",
+                            e.component<Scripted>()->caller,
+                            event.button.x,
+                            event.button.y,
+                            event.button.button);
+                    });
+            }
+            break;
+        default:
+            break;
+        }
+    }
+}
+
diff --git a/src/input.hpp b/src/input.hpp
index fa92c39..6180388 100644
--- a/src/input.hpp
+++ b/src/input.hpp
@@ -1,5 +1,5 @@
 /**
- * @file window.hpp
+ * @file input.hpp
  * Handles user input received from SDL.
  *
  * Copyright (C) 2019 Clyne Sullivan
@@ -56,34 +56,23 @@ struct KeyDownEvent {
 class InputSystem : public entityx::System<InputSystem>
 {
 public:
+    InputSystem();
+
     /**
      * Prepares the system for running.
      */
-    void configure([[maybe_unused]] entityx::EntityManager& entities,
-                   [[maybe_unused]] entityx::EventManager& events) final {}
+    void configure(entityx::EntityManager& entities,
+                   entityx::EventManager& events) final;
 
     /**
      * Updates the system by checking for SDL events.
      */
-    void update([[maybe_unused]] entityx::EntityManager& entities,
-                [[maybe_unused]] entityx::EventManager& events,
-                [[maybe_unused]] entityx::TimeDelta dt) final
-    {
-        for (SDL_Event event; SDL_PollEvent(&event);) {
-            switch (event.type) {
-            case SDL_KEYUP:
-                if (auto key = event.key; key.repeat == 0)
-                    events.emit<KeyUpEvent>(key.keysym);
-                break;
-            case SDL_KEYDOWN:
-                if (auto key = event.key; key.repeat == 0)
-                    events.emit<KeyDownEvent>(key.keysym);
-                break;
-            default:
-                break;
-            }
-        }
-    }
+    void update(entityx::EntityManager& entities,
+                entityx::EventManager& events,
+                entityx::TimeDelta dt) final;
+
+private:
+    bool isMouseDown;
 };
 
 #endif // SYSTEM_INPUT_HPP_
diff --git a/src/player.cpp b/src/player.cpp
index b914672..f40a1d1 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -54,26 +54,23 @@ void PlayerSystem::receive(const KeyDownEvent& kue)
 {
     if (player.valid()) {
         if (kue.sym == SDLK_a) {
-            entities.each<EventListener>([&]([[maybe_unused]] entityx::Entity e,
-                                             EventListener& el)
-            {
+            entities.each<EventListener>(
+                [](entityx::Entity e, EventListener& el) {
                     el.tryListener("MoveLeftPressed",
                                    e.component<Scripted>()->caller);
-            });
+                });
         } else if (kue.sym == SDLK_d) {
-            entities.each<EventListener>([&]([[maybe_unused]] entityx::Entity e,
-                                             EventListener& el)
-            {
+            entities.each<EventListener>(
+                [](entityx::Entity e, EventListener& el) {
                     el.tryListener("MoveRightPressed",
                                    e.component<Scripted>()->caller);
-            });
+                });
         } else if (kue.sym == SDLK_SPACE) {
-            entities.each<EventListener>([&]([[maybe_unused]] entityx::Entity e,
-                                             EventListener& el)
-            {
+            entities.each<EventListener>(
+                [](entityx::Entity e, EventListener& el) {
                     el.tryListener("JumpKeyPressed",
                                    e.component<Scripted>()->caller);
-            });
+                });
         }
     }
 }
@@ -82,26 +79,23 @@ void PlayerSystem::receive(const KeyUpEvent& kue)
 {
     if (player.valid()) {
         if (kue.sym == SDLK_a) {
-            entities.each<EventListener>([&]([[maybe_unused]] entityx::Entity e,
-                                             EventListener& el)
-            {
+            entities.each<EventListener>(
+                [](entityx::Entity e, EventListener& el) {
                     el.tryListener("MoveLeftReleased",
                                    e.component<Scripted>()->caller);
-            });
+                });
         } else if (kue.sym == SDLK_d) {
-            entities.each<EventListener>([&]([[maybe_unused]] entityx::Entity e,
-                                             EventListener& el)
-            {
+            entities.each<EventListener>(
+                [](entityx::Entity e, EventListener& el) {
                     el.tryListener("MoveRightReleased",
                                    e.component<Scripted>()->caller);
-            });
+                });
         } else if (kue.sym == SDLK_SPACE) {
-            entities.each<EventListener>([&]([[maybe_unused]] entityx::Entity e,
-                                             EventListener& el)
-            {
+            entities.each<EventListener>(
+                [](entityx::Entity e, EventListener& el) {
                     el.tryListener("JumpKeyReleased",
                                    e.component<Scripted>()->caller);
-            });
+                });
         }
     }
 }
-- 
cgit v1.2.3


From bdc0e843a4762a1abddebc53d12a351debe8d457 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Fri, 19 Aug 2022 20:52:59 -0400
Subject: add cereal and entityx submodules; fix compile errors

---
 .gitmodules                      |   7 +++++++
 Makefile                         |  15 ++++++++++-----
 lib/cereal                       |   1 +
 lib/entityx                      |   1 +
 lib/libentityx.a                 | Bin 414808 -> 945228 bytes
 src/components/Audio.hpp         |   2 +-
 src/components/Component.hpp     |   2 +-
 src/components/EventListener.hpp |   2 +-
 src/components/Light.hpp         |   2 +-
 src/components/Name.hpp          |   2 +-
 src/components/Physics.hpp       |   2 +-
 src/components/Player.hpp        |   2 +-
 src/components/Position.hpp      |   2 +-
 src/components/Render.hpp        |   2 +-
 src/components/Script.hpp        |   2 +-
 src/components/Velocity.hpp      |   2 +-
 src/gamestate.hpp                |  26 +++++++++++++++++++++++++-
 17 files changed, 55 insertions(+), 17 deletions(-)
 create mode 160000 lib/cereal
 create mode 160000 lib/entityx

(limited to 'src')

diff --git a/.gitmodules b/.gitmodules
index 340f9cd..e2f5cf7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,10 @@
 [submodule "lib/sol2"]
 	path = lib/sol2
 	url = https://github.com/ThePhD/sol2
+[submodule "lib/entityx"]
+	path = lib/entityx
+	url = https://github.com/tcsullivan/entityx
+	branch = remove-std-iterator
+[submodule "lib/cereal"]
+	path = lib/cereal
+	url = https://github.com/USCiLab/cereal
diff --git a/Makefile b/Makefile
index 357d7ff..23f522e 100644
--- a/Makefile
+++ b/Makefile
@@ -40,11 +40,16 @@ LIBS   = -L$(LIBDIR) -lSDL2 -lpthread -lentityx -lluajit -ldl -lGLEW -lGL \
 		 -lSDL2_image -lSOIL -lfreetype -lopenal -lalut
 
 CXXFLAGS = -ggdb -std=c++17 -Wall -Wextra -Werror -pedantic \
-		   -Wno-class-memaccess -Wno-implicit-fallthrough -m64
-
-CXXINCS = -Isrc -I$(LIBDIR)/LuaJIT/src -I$(LIBDIR)/entityx \
-		  -I$(LIBDIR)/LuaBridge/Source -I$(LIBDIR)/sol2/include \
-		  -I$(LIBDIR)/soil -I$(LIBDIR)/cereal/include -I$(LIBDIR)/freetype
+		   -Wno-class-memaccess -Wno-implicit-fallthrough -Wno-unused-parameter
+
+CXXINCS = -I$(SRCDIR) \
+          -I$(LIBDIR)/entityx \
+          -I$(LIBDIR)/LuaJIT/src \
+          -I$(LIBDIR)/LuaBridge/Source \
+          -I$(LIBDIR)/sol2/include \
+          -I$(LIBDIR)/soil \
+          -I$(LIBDIR)/cereal/include \
+	  -I$(LIBDIR)/freetype
 
 CXXSRC := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
 CXXOBJ := $(patsubst $(SRCDIR)/%,$(OUTDIR)/%,$(CXXSRC:.$(SRCEXT)=.$(OBJEXT)))
diff --git a/lib/cereal b/lib/cereal
new file mode 160000
index 0000000..ddd4672
--- /dev/null
+++ b/lib/cereal
@@ -0,0 +1 @@
+Subproject commit ddd467244713ea4fe63733628992efcdd6a9187d
diff --git a/lib/entityx b/lib/entityx
new file mode 160000
index 0000000..39e0709
--- /dev/null
+++ b/lib/entityx
@@ -0,0 +1 @@
+Subproject commit 39e07099da7227d7d7baec072411ddc0abfd8be4
diff --git a/lib/libentityx.a b/lib/libentityx.a
index c1b2a0d..b0042eb 100644
Binary files a/lib/libentityx.a and b/lib/libentityx.a differ
diff --git a/src/components/Audio.hpp b/src/components/Audio.hpp
index a97b235..2bb63eb 100644
--- a/src/components/Audio.hpp
+++ b/src/components/Audio.hpp
@@ -47,7 +47,7 @@ public:
     void serialize([[maybe_unused]] cereal::JSONOutputArchive& ar) final {}
     void serialize([[maybe_unused]] cereal::JSONInputArchive& ar) final {}
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Audio";
     }
 };
diff --git a/src/components/Component.hpp b/src/components/Component.hpp
index 2928366..576a059 100644
--- a/src/components/Component.hpp
+++ b/src/components/Component.hpp
@@ -33,7 +33,7 @@ public:
     virtual void serialize(cereal::JSONOutputArchive& ar) = 0;
     virtual void serialize(cereal::JSONInputArchive& ar) = 0;
 
-    void internal_serialize(bool save, void *ar) final {
+    virtual void internal_serialize(bool save, void *ar) final {
         if (save)
             serialize(*reinterpret_cast<cereal::JSONOutputArchive*>(ar));
         else
diff --git a/src/components/EventListener.hpp b/src/components/EventListener.hpp
index c39b6ad..fb55d95 100644
--- a/src/components/EventListener.hpp
+++ b/src/components/EventListener.hpp
@@ -52,7 +52,7 @@ public:
     void serialize([[maybe_unused]] cereal::JSONOutputArchive& ar) final {}
     void serialize([[maybe_unused]] cereal::JSONInputArchive& ar) final {}
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "EventListener";
     }
 };
diff --git a/src/components/Light.hpp b/src/components/Light.hpp
index 6849d7c..c63b6cc 100644
--- a/src/components/Light.hpp
+++ b/src/components/Light.hpp
@@ -58,7 +58,7 @@ public:
         ar(CEREAL_NVP(r), CEREAL_NVP(g), CEREAL_NVP(b), CEREAL_NVP(strength));
     }
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Light";
     }
 };
diff --git a/src/components/Name.hpp b/src/components/Name.hpp
index a6a6d8a..6390d5e 100644
--- a/src/components/Name.hpp
+++ b/src/components/Name.hpp
@@ -47,7 +47,7 @@ public:
         ar(CEREAL_NVP(name));
     }
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Name";
     }
 };
diff --git a/src/components/Physics.hpp b/src/components/Physics.hpp
index 378e87f..edf5ac5 100644
--- a/src/components/Physics.hpp
+++ b/src/components/Physics.hpp
@@ -33,7 +33,7 @@ public:
     void serialize([[maybe_unused]] cereal::JSONOutputArchive& ar) final {}
     void serialize([[maybe_unused]] cereal::JSONInputArchive& ar) final {}
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Physics";
     }
 };
diff --git a/src/components/Player.hpp b/src/components/Player.hpp
index a550c4f..43d083e 100644
--- a/src/components/Player.hpp
+++ b/src/components/Player.hpp
@@ -36,7 +36,7 @@ public:
     void serialize([[maybe_unused]] cereal::JSONOutputArchive& ar) final {}
     void serialize([[maybe_unused]] cereal::JSONInputArchive& ar) final {}
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Player";
     }
 };
diff --git a/src/components/Position.hpp b/src/components/Position.hpp
index 56e8707..fcd62f8 100644
--- a/src/components/Position.hpp
+++ b/src/components/Position.hpp
@@ -51,7 +51,7 @@ public:
         ar(CEREAL_NVP(x), CEREAL_NVP(y));
     }
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Position";
     }
 };
diff --git a/src/components/Render.hpp b/src/components/Render.hpp
index 81ca591..93be5d8 100644
--- a/src/components/Render.hpp
+++ b/src/components/Render.hpp
@@ -62,7 +62,7 @@ public:
         ar(CEREAL_NVP(visible), CEREAL_NVP(flipX));
     }
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Render";
     }
 };
diff --git a/src/components/Script.hpp b/src/components/Script.hpp
index 3f96be5..d7bc147 100644
--- a/src/components/Script.hpp
+++ b/src/components/Script.hpp
@@ -119,7 +119,7 @@ public:
 
     }
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Scripted";
     }
 };
diff --git a/src/components/Velocity.hpp b/src/components/Velocity.hpp
index 776c1dd..f48a9f3 100644
--- a/src/components/Velocity.hpp
+++ b/src/components/Velocity.hpp
@@ -52,7 +52,7 @@ public:
         ar(CEREAL_NVP(x), CEREAL_NVP(y));
     }
 
-    std::string serializeName(void) const final {
+    virtual std::string serializeName(void) const final {
         return "Velocity";
     }
 };
diff --git a/src/gamestate.hpp b/src/gamestate.hpp
index 55f4e47..86a4198 100644
--- a/src/gamestate.hpp
+++ b/src/gamestate.hpp
@@ -27,6 +27,30 @@
 
 #include <fstream>
 
+struct EntitySerializer
+{
+    template<class Archive>
+    static void serialize(entityx::EntityManager& entities, entityx::Entity entity, bool save, Archive& ar)
+    {
+        // TODO try and reimplement without modifying entityx?
+        // Or, make a new branch...
+
+        //const auto mask = entity.component_mask();
+
+        //for (size_t i = 0; i < entities.component_helpers_.size(); i++) {
+        //    auto helper = entities.component_helpers_[i];
+        //    if (helper && mask.test(i)) {
+        //        auto* c = helper->get_component(entity);
+        //        ar.setNextName(c->serializeName().c_str());
+        //        ar.startNode();
+        //        c->internal_serialize(save, static_cast<void*>(&ar));
+        //        ar.finishNode();
+        //    }
+        //}
+    }
+};
+
+
 /**
  * @class GameState
  * Manages save files that contain entity data.
@@ -98,7 +122,7 @@ private:
         for (auto entity : entities.entities_for_debugging()) {
             archive.setNextName((name + std::to_string(i++)).c_str());
             archive.startNode();
-            entities.entity_serialize(entity, save, archive);
+            EntitySerializer::serialize(entities, entity, save, archive);
             archive.finishNode();
         }
     }
-- 
cgit v1.2.3


From 2364287a961fa9c860e1146bbcc3391ec5b1fd54 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Fri, 19 Aug 2022 20:53:21 -0400
Subject: add entityx config.h

---
 src/entityx/config.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 src/entityx/config.h

(limited to 'src')

diff --git a/src/entityx/config.h b/src/entityx/config.h
new file mode 100644
index 0000000..630f8a8
--- /dev/null
+++ b/src/entityx/config.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <cstdint>
+#include <cstddef>
+
+namespace entityx {
+
+static const size_t MAX_COMPONENTS = 64;
+typedef double TimeDelta;
+
+}  // namespace entityx
-- 
cgit v1.2.3


From ea719de76706140ce87f16fd9bde61c0e665d089 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Sat, 20 Aug 2022 11:15:45 -0400
Subject: fix serialization support

---
 .gitmodules               |  2 +-
 Makefile                  |  8 +++++---
 lib/entityx               |  2 +-
 lib/soil/Makefile         |  4 ++++
 src/components/Script.hpp |  2 +-
 src/gamestate.hpp         | 32 +++++++-------------------------
 6 files changed, 19 insertions(+), 31 deletions(-)
 create mode 100644 lib/soil/Makefile

(limited to 'src')

diff --git a/.gitmodules b/.gitmodules
index 911085e..812302f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,7 +4,7 @@
 [submodule "lib/entityx"]
 	path = lib/entityx
 	url = https://github.com/tcsullivan/entityx
-	branch = remove-std-iterator
+	branch = serialize
 [submodule "lib/cereal"]
 	path = lib/cereal
 	url = https://github.com/USCiLab/cereal
diff --git a/Makefile b/Makefile
index db7c130..cc46888 100644
--- a/Makefile
+++ b/Makefile
@@ -68,6 +68,8 @@ directories:
 clean:
 	@echo "  CLEAN"
 	@$(RM) -rf $(OUTDIR)
+
+cleanall: clean
 	@$(RM) -f lib/libentityx.a lib/libluajit.a lib/libsoil.a
 
 cleaner: clean
@@ -96,8 +98,8 @@ lib/libluajit.a:
 	@cp lib/luajit/src/libluajit.a lib/libluajit.a
 
 lib/libsoil.a:
-	@gcc -c lib/soil/soil/*.c
-	@ar rcs lib/libsoil.a lib/soil/soil/*.o
+	@make -Clib/soil -j4
+	@cp lib/soil/libsoil.a lib/libsoil.a
 
-.PHONY: all remake clean cleaner resources
+.PHONY: all remake clean cleaner cleanall resources
 
diff --git a/lib/entityx b/lib/entityx
index 39e0709..e04b856 160000
--- a/lib/entityx
+++ b/lib/entityx
@@ -1 +1 @@
-Subproject commit 39e07099da7227d7d7baec072411ddc0abfd8be4
+Subproject commit e04b856006cfe6b7e8ba5d6c1434331351cc791a
diff --git a/lib/soil/Makefile b/lib/soil/Makefile
new file mode 100644
index 0000000..0b67b7c
--- /dev/null
+++ b/lib/soil/Makefile
@@ -0,0 +1,4 @@
+all:
+	@gcc -c soil/*.c
+	@ar rcs libsoil.a *.o
+
diff --git a/src/components/Script.hpp b/src/components/Script.hpp
index d7bc147..93997a9 100644
--- a/src/components/Script.hpp
+++ b/src/components/Script.hpp
@@ -74,7 +74,7 @@ public:
             else if (value.get_type() == sol::type::number)
                 table_components.push_back(std::make_tuple(
                     key.as<std::string>(),
-                    std::string("return " + value.as<std::string>())
+                    std::string("return ") + std::to_string(value.as<double>())
                 ));
             else if (value.get_type() == sol::type::boolean) {
                 table_components.push_back(std::make_tuple(
diff --git a/src/gamestate.hpp b/src/gamestate.hpp
index 86a4198..3ef641f 100644
--- a/src/gamestate.hpp
+++ b/src/gamestate.hpp
@@ -27,30 +27,6 @@
 
 #include <fstream>
 
-struct EntitySerializer
-{
-    template<class Archive>
-    static void serialize(entityx::EntityManager& entities, entityx::Entity entity, bool save, Archive& ar)
-    {
-        // TODO try and reimplement without modifying entityx?
-        // Or, make a new branch...
-
-        //const auto mask = entity.component_mask();
-
-        //for (size_t i = 0; i < entities.component_helpers_.size(); i++) {
-        //    auto helper = entities.component_helpers_[i];
-        //    if (helper && mask.test(i)) {
-        //        auto* c = helper->get_component(entity);
-        //        ar.setNextName(c->serializeName().c_str());
-        //        ar.startNode();
-        //        c->internal_serialize(save, static_cast<void*>(&ar));
-        //        ar.finishNode();
-        //    }
-        //}
-    }
-};
-
-
 /**
  * @class GameState
  * Manages save files that contain entity data.
@@ -122,7 +98,13 @@ private:
         for (auto entity : entities.entities_for_debugging()) {
             archive.setNextName((name + std::to_string(i++)).c_str());
             archive.startNode();
-            EntitySerializer::serialize(entities, entity, save, archive);
+            entities.serialize(entity,
+                [&archive, &save](auto c) {
+                    archive.setNextName(c->serializeName().c_str());
+                    archive.startNode();
+                    c->internal_serialize(save, static_cast<void*>(&archive));
+                    archive.finishNode();
+                });
             archive.finishNode();
         }
     }
-- 
cgit v1.2.3