diff --git a/AdventOfCode2018/.vscode/settings.json b/AdventOfCode2018/.vscode/settings.json
new file mode 100644
index 0000000..cd89cd1
--- /dev/null
+++ b/AdventOfCode2018/.vscode/settings.json
@@ -0,0 +1,42 @@
+{
+ "files.associations": {
+ "cmath": "cpp",
+ "cstddef": "cpp",
+ "cstdint": "cpp",
+ "cstdio": "cpp",
+ "cstdlib": "cpp",
+ "cstring": "cpp",
+ "cwchar": "cpp",
+ "exception": "cpp",
+ "fstream": "cpp",
+ "initializer_list": "cpp",
+ "ios": "cpp",
+ "iosfwd": "cpp",
+ "iostream": "cpp",
+ "istream": "cpp",
+ "limits": "cpp",
+ "memory": "cpp",
+ "new": "cpp",
+ "ostream": "cpp",
+ "stdexcept": "cpp",
+ "streambuf": "cpp",
+ "string": "cpp",
+ "system_error": "cpp",
+ "tuple": "cpp",
+ "type_traits": "cpp",
+ "typeinfo": "cpp",
+ "utility": "cpp",
+ "vector": "cpp",
+ "xfacet": "cpp",
+ "xiosbase": "cpp",
+ "xlocale": "cpp",
+ "xlocinfo": "cpp",
+ "xlocnum": "cpp",
+ "xmemory": "cpp",
+ "xmemory0": "cpp",
+ "xstddef": "cpp",
+ "xstring": "cpp",
+ "xtr1common": "cpp",
+ "xutility": "cpp"
+ }
+}
\ No newline at end of file
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics.sln b/C++/Pixel-Engine/Particle-Physics/Particle-Physics.sln
new file mode 100644
index 0000000..da3f061
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28010.2036
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Particle-Physics", "Particle-Physics\Particle-Physics.vcxproj", "{365A5672-081D-43D8-A2A1-9360CBBA90CB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Debug|x64.ActiveCfg = Debug|x64
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Debug|x64.Build.0 = Debug|x64
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Debug|x86.ActiveCfg = Debug|Win32
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Debug|x86.Build.0 = Debug|Win32
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Release|x64.ActiveCfg = Release|x64
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Release|x64.Build.0 = Release|x64
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Release|x86.ActiveCfg = Release|Win32
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {176D1467-9854-48F0-B5BC-A7662DB8C0AE}
+ EndGlobalSection
+EndGlobal
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics/Particle-Physics.vcxproj b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/Particle-Physics.vcxproj
new file mode 100644
index 0000000..afba1fa
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/Particle-Physics.vcxproj
@@ -0,0 +1,128 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {365A5672-081D-43D8-A2A1-9360CBBA90CB}
+ ParticlePhysics
+ 10.0.17134.0
+
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ Disabled
+ true
+ true
+
+
+
+
+ Level3
+ Disabled
+ true
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics/Particle-Physics.vcxproj.filters b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/Particle-Physics.vcxproj.filters
new file mode 100644
index 0000000..cf461a5
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/Particle-Physics.vcxproj.filters
@@ -0,0 +1,33 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics/main.cpp b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/main.cpp
new file mode 100644
index 0000000..7c1bf11
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/main.cpp
@@ -0,0 +1,79 @@
+#define OLC_PGE_APPLICATION
+#include "olcPixelGameEngine.h"
+
+#include // For Sleep(int ms)
+#include // for std::vector
+#include // for std::thread
+#include // for std::mutex
+#include // for std::atomic
+
+#define WINDOW_WIDTH 600
+#define WINDOW_HEIGHT 400
+
+#define CONSTANT_GRAVITY 9.8
+
+static unsigned long PHYSICS_UPDATE_RATE = 16; // Ms per update
+
+std::atomic isPhysicsRunning = false;
+
+class Particle {
+public:
+ Particle() {};
+ void Render() {};
+};
+
+std::mutex PhysicsMutex;
+std::vector Particles;
+
+void RunPhysics() {
+ while (isPhysicsRunning) {
+ std::cout << 1 << std::endl;
+
+
+
+ Sleep(PHYSICS_UPDATE_RATE);
+ }
+}
+
+class ParticlePhysics : public olc::PixelGameEngine {
+public:
+ ParticlePhysics() {
+ sAppName = "Particle Physics Thing";
+ }
+
+ bool OnUserCreate() override {
+ for (int x = 0; x < ScreenWidth(); x++)
+ for (int y = 0; y < ScreenHeight(); y++)
+ Draw(x, y, olc::Pixel(25, 25, 25));
+
+ isPhysicsRunning = true;
+ m_physicsThread = new std::thread(&RunPhysics);
+
+ return true;
+ }
+
+ bool OnUserUpdate(float fElapsedTime) override {
+ PhysicsMutex.lock();
+ for (unsigned int i = 0; i < Particles.size(); i++) {
+ Particles[i].Render();
+ }
+ PhysicsMutex.unlock();
+
+ return true;
+ }
+
+ void DestroyPhysics() {
+ isPhysicsRunning = false;
+ m_physicsThread->join();
+ }
+private:
+ std::thread* m_physicsThread;
+};
+
+
+int main(int argc, char** argv) {
+ ParticlePhysics demo;
+ if (demo.Construct(WINDOW_WIDTH, WINDOW_HEIGHT, 2, 2))
+ demo.Start();
+ return 0;
+}
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPGEX_Graphics2D.h b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPGEX_Graphics2D.h
new file mode 100644
index 0000000..70d0f39
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPGEX_Graphics2D.h
@@ -0,0 +1,288 @@
+/*
+ olcPGEX_Graphics2D.h
+
+ +-------------------------------------------------------------+
+ | OneLoneCoder Pixel Game Engine Extension |
+ | Advanced 2D Rendering - v0.3 |
+ +-------------------------------------------------------------+
+
+ What is this?
+ ~~~~~~~~~~~~~
+ This is an extension to the olcPixelGameEngine, which provides
+ advanced olc::Sprite manipulation and drawing routines. To use
+ it, simply include this header file.
+
+ License (OLC-3)
+ ~~~~~~~~~~~~~~~
+
+ Copyright 2018 OneLoneCoder.com
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions or derivations of source code must retain the above
+ copyright notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions or derivative works in binary form must reproduce
+ the above copyright notice. This list of conditions and the following
+ disclaimer must be reproduced in the documentation and/or other
+ materials provided with the distribution.
+
+ 3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Links
+ ~~~~~
+ YouTube: https://www.youtube.com/javidx9
+ Discord: https://discord.gg/WhwHUMV
+ Twitter: https://www.twitter.com/javidx9
+ Twitch: https://www.twitch.tv/javidx9
+ GitHub: https://www.github.com/onelonecoder
+ Homepage: https://www.onelonecoder.com
+
+ Author
+ ~~~~~~
+ David Barr, aka javidx9, ©OneLoneCoder 2018
+*/
+
+/*
+ Matrices stored as [Column][Row] (i.e. x, y)
+
+ |C0R0 C1R0 C2R0| | x | | x'|
+ |C0R1 C1R1 C2R1| * | y | = | y'|
+ |C0R2 C1R2 C2R2| |1.0| | - |
+*/
+
+
+
+#ifndef OLC_PGEX_GFX2D
+#define OLC_PGEX_GFX2D
+
+#include
+#undef min
+#undef max
+
+namespace olc
+{
+ // Container class for Advanced 2D Drawing functions
+ class GFX2D : public olc::PGEX
+ {
+ // A representation of an affine transform, used to rotate, scale, offset & shear space
+ public:
+ class Transform2D
+ {
+ public:
+ inline Transform2D();
+
+ public:
+ // Set this transformation to unity
+ inline void Reset();
+ // Append a rotation of fTheta radians to this transform
+ inline void Rotate(float fTheta);
+ // Append a translation (ox, oy) to this transform
+ inline void Translate(float ox, float oy);
+ // Append a scaling operation (sx, sy) to this transform
+ inline void Scale(float sx, float sy);
+ // Append a shear operation (sx, sy) to this transform
+ inline void Shear(float sx, float sy);
+ // Calculate the Forward Transformation of the coordinate (in_x, in_y) -> (out_x, out_y)
+ inline void Forward(float in_x, float in_y, float &out_x, float &out_y);
+ // Calculate the Inverse Transformation of the coordinate (in_x, in_y) -> (out_x, out_y)
+ inline void Backward(float in_x, float in_y, float &out_x, float &out_y);
+ // Regenerate the Inverse Transformation
+ inline void Invert();
+
+ private:
+ inline void Multiply();
+ float matrix[4][3][3];
+ int nTargetMatrix;
+ int nSourceMatrix;
+ bool bDirty;
+ };
+
+ public:
+ // Draws a sprite with the transform applied
+ inline static void DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform);
+ };
+}
+
+
+
+
+namespace olc
+{
+ void GFX2D::DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform)
+ {
+ if (sprite == nullptr)
+ return;
+
+ // Work out bounding rectangle of sprite
+ float ex, ey;
+ float sx, sy;
+ float px, py;
+
+ transform.Forward(0.0f, 0.0f, sx, sy);
+ px = sx; py = sy;
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ transform.Forward((float)sprite->width, (float)sprite->height, px, py);
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ transform.Forward(0.0f, (float)sprite->height, px, py);
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ transform.Forward((float)sprite->width, 0.0f, px, py);
+ sx = std::min(sx, px); sy = std::min(sy, py);
+ ex = std::max(ex, px); ey = std::max(ey, py);
+
+ // Perform inversion of transform if required
+ transform.Invert();
+
+ if (ex < sx)
+ std::swap(ex, sx);
+ if (ey < sy)
+ std::swap(ey, sy);
+
+ // Iterate through render space, and sample Sprite from suitable texel location
+ for (float i = sx; i < ex; i++)
+ {
+ for (float j = sy; j < ey; j++)
+ {
+ float ox, oy;
+ transform.Backward(i, j, ox, oy);
+ pge->Draw((int32_t)i, (int32_t)j, sprite->GetPixel((int32_t)(ox+0.5f), (int32_t)(oy+0.5f)));
+ }
+ }
+ }
+
+ olc::GFX2D::Transform2D::Transform2D()
+ {
+ Reset();
+ }
+
+ void olc::GFX2D::Transform2D::Reset()
+ {
+ nTargetMatrix = 0;
+ nSourceMatrix = 1;
+ bDirty = true;
+
+ // Columns Then Rows
+
+ // Matrices 0 & 1 are used as swaps in Transform accumulation
+ matrix[0][0][0] = 1.0f; matrix[0][1][0] = 0.0f; matrix[0][2][0] = 0.0f;
+ matrix[0][0][1] = 0.0f; matrix[0][1][1] = 1.0f; matrix[0][2][1] = 0.0f;
+ matrix[0][0][2] = 0.0f; matrix[0][1][2] = 0.0f; matrix[0][2][2] = 1.0f;
+
+ matrix[1][0][0] = 1.0f; matrix[1][1][0] = 0.0f; matrix[1][2][0] = 0.0f;
+ matrix[1][0][1] = 0.0f; matrix[1][1][1] = 1.0f; matrix[1][2][1] = 0.0f;
+ matrix[1][0][2] = 0.0f; matrix[1][1][2] = 0.0f; matrix[1][2][2] = 1.0f;
+
+ // Matrix 2 is a cache matrix to hold the immediate transform operation
+ // Matrix 3 is a cache matrix to hold the inverted transform
+ }
+
+ void olc::GFX2D::Transform2D::Multiply()
+ {
+ for (int c = 0; c < 3; c++)
+ {
+ for (int r = 0; r < 3; r++)
+ {
+ matrix[nTargetMatrix][c][r] = matrix[2][0][r] * matrix[nSourceMatrix][c][0] +
+ matrix[2][1][r] * matrix[nSourceMatrix][c][1] +
+ matrix[2][2][r] * matrix[nSourceMatrix][c][2];
+ }
+ }
+
+ std::swap(nTargetMatrix, nSourceMatrix);
+ bDirty = true; // Any transform multiply dirties the inversion
+ }
+
+ void olc::GFX2D::Transform2D::Rotate(float fTheta)
+ {
+ // Construct Rotation Matrix
+ matrix[2][0][0] = cosf(fTheta); matrix[2][1][0] = sinf(fTheta); matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = -sinf(fTheta); matrix[2][1][1] = cosf(fTheta); matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Scale(float sx, float sy)
+ {
+ // Construct Scale Matrix
+ matrix[2][0][0] = sx; matrix[2][1][0] = 0.0f; matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = 0.0f; matrix[2][1][1] = sy; matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Shear(float sx, float sy)
+ {
+ // Construct Shear Matrix
+ matrix[2][0][0] = 1.0f; matrix[2][1][0] = sx; matrix[2][2][0] = 0.0f;
+ matrix[2][0][1] = sy; matrix[2][1][1] = 1.0f; matrix[2][2][1] = 0.0f;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Translate(float ox, float oy)
+ {
+ // Construct Translate Matrix
+ matrix[2][0][0] = 1.0f; matrix[2][1][0] = 0.0f; matrix[2][2][0] = ox;
+ matrix[2][0][1] = 0.0f; matrix[2][1][1] = 1.0f; matrix[2][2][1] = oy;
+ matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
+ Multiply();
+ }
+
+ void olc::GFX2D::Transform2D::Forward(float in_x, float in_y, float &out_x, float &out_y)
+ {
+ out_x = in_x * matrix[nSourceMatrix][0][0] + in_y * matrix[nSourceMatrix][1][0] + matrix[nSourceMatrix][2][0];
+ out_y = in_x * matrix[nSourceMatrix][0][1] + in_y * matrix[nSourceMatrix][1][1] + matrix[nSourceMatrix][2][1];
+ }
+
+ void olc::GFX2D::Transform2D::Backward(float in_x, float in_y, float &out_x, float &out_y)
+ {
+ out_x = in_x * matrix[3][0][0] + in_y * matrix[3][1][0] + matrix[3][2][0];
+ out_y = in_x * matrix[3][0][1] + in_y * matrix[3][1][1] + matrix[3][2][1];
+ }
+
+ void olc::GFX2D::Transform2D::Invert()
+ {
+ if (bDirty) // Obviously costly so only do if needed
+ {
+ float det = matrix[nSourceMatrix][0][0] * (matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][1][2] * matrix[nSourceMatrix][2][1]) -
+ matrix[nSourceMatrix][1][0] * (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][2][1] * matrix[nSourceMatrix][0][2]) +
+ matrix[nSourceMatrix][2][0] * (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][0][2]);
+
+ float idet = 1.0f / det;
+ matrix[3][0][0] = (matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][1][2] * matrix[nSourceMatrix][2][1]) * idet;
+ matrix[3][1][0] = (matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][1][0] * matrix[nSourceMatrix][2][2]) * idet;
+ matrix[3][2][0] = (matrix[nSourceMatrix][1][0] * matrix[nSourceMatrix][2][1] - matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][1][1]) * idet;
+ matrix[3][0][1] = (matrix[nSourceMatrix][2][1] * matrix[nSourceMatrix][0][2] - matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][2]) * idet;
+ matrix[3][1][1] = (matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][0][2]) * idet;
+ matrix[3][2][1] = (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][0] - matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][2][1]) * idet;
+ matrix[3][0][2] = (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][0][2] * matrix[nSourceMatrix][1][1]) * idet;
+ matrix[3][1][2] = (matrix[nSourceMatrix][0][2] * matrix[nSourceMatrix][1][0] - matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][1][2]) * idet;
+ matrix[3][2][2] = (matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][1][1] - matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][0]) * idet;
+ bDirty = false;
+ }
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPGEX_Sound.h b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPGEX_Sound.h
new file mode 100644
index 0000000..37cd9a3
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPGEX_Sound.h
@@ -0,0 +1,513 @@
+/*
+ olcPGEX_Sound.h
+
+ +-------------------------------------------------------------+
+ | OneLoneCoder Pixel Game Engine Extension |
+ | Sound - v0.2 |
+ +-------------------------------------------------------------+
+
+ What is this?
+ ~~~~~~~~~~~~~
+ This is an extension to the olcPixelGameEngine, which provides
+ sound generation and wave playing routines.
+
+ License (OLC-3)
+ ~~~~~~~~~~~~~~~
+
+ Copyright 2018 OneLoneCoder.com
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions or derivations of source code must retain the above
+ copyright notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions or derivative works in binary form must reproduce
+ the above copyright notice. This list of conditions and the following
+ disclaimer must be reproduced in the documentation and/or other
+ materials provided with the distribution.
+
+ 3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Links
+ ~~~~~
+ YouTube: https://www.youtube.com/javidx9
+ Discord: https://discord.gg/WhwHUMV
+ Twitter: https://www.twitter.com/javidx9
+ Twitch: https://www.twitch.tv/javidx9
+ GitHub: https://www.github.com/onelonecoder
+ Homepage: https://www.onelonecoder.com
+ Patreon: https://www.patreon.com/javidx9
+
+ Author
+ ~~~~~~
+ David Barr, aka javidx9, ©OneLoneCoder 2018
+*/
+
+
+#ifndef OLC_PGEX_SOUND
+#define OLC_PGEX_SOUND
+
+#include
+
+#include
+#undef min
+#undef max
+
+namespace olc
+{
+ // Container class for Advanced 2D Drawing functions
+ class SOUND : public olc::PGEX
+ {
+ // A representation of an affine transform, used to rotate, scale, offset & shear space
+ public:
+ class AudioSample
+ {
+ public:
+ AudioSample();
+ AudioSample(std::string sWavFile, olc::ResourcePack *pack = nullptr);
+ olc::rcode LoadFromFile(std::string sWavFile, olc::ResourcePack *pack = nullptr);
+
+ public:
+ WAVEFORMATEX wavHeader;
+ float *fSample = nullptr;
+ long nSamples = 0;
+ int nChannels = 0;
+ bool bSampleValid = false;
+ };
+
+ struct sCurrentlyPlayingSample
+ {
+ int nAudioSampleID = 0;
+ long nSamplePosition = 0;
+ bool bFinished = false;
+ bool bLoop = false;
+ bool bFlagForStop = false;
+ };
+
+ static std::list listActiveSamples;
+
+ public:
+ static bool InitialiseAudio(unsigned int nSampleRate = 44100, unsigned int nChannels = 1, unsigned int nBlocks = 8, unsigned int nBlockSamples = 512);
+ static bool DestroyAudio();
+ static void SetUserSynthFunction(std::function func);
+ static void SetUserFilterFunction(std::function func);
+
+ public:
+ static unsigned int LoadAudioSample(std::string sWavFile, olc::ResourcePack *pack = nullptr);
+ static void PlaySample(int id, bool bLoop = false);
+ static void StopSample(int id);
+ static void StopAll();
+ static float GetMixerOutput(int nChannel, float fGlobalTime, float fTimeStep);
+
+#ifdef WIN32
+ private:
+ static void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwParam1, DWORD dwParam2);
+ static void AudioThread();
+ static unsigned int m_nSampleRate;
+ static unsigned int m_nChannels;
+ static unsigned int m_nBlockCount;
+ static unsigned int m_nBlockSamples;
+ static unsigned int m_nBlockCurrent;
+ static short* m_pBlockMemory;
+ static WAVEHDR *m_pWaveHeaders;
+ static HWAVEOUT m_hwDevice;
+ static std::thread m_AudioThread;
+ static std::atomic m_bAudioThreadActive;
+ static std::atomic m_nBlockFree;
+ static std::condition_variable m_cvBlockNotZero;
+ static std::mutex m_muxBlockNotZero;
+ static std::atomic m_fGlobalTime;
+ static std::function funcUserSynth;
+ static std::function funcUserFilter;
+#endif
+
+ };
+}
+
+
+#ifdef WIN32
+#pragma comment(lib, "winmm.lib")
+namespace olc
+{
+ SOUND::AudioSample::AudioSample()
+ {
+
+
+
+ }
+
+ SOUND::AudioSample::AudioSample(std::string sWavFile, olc::ResourcePack *pack)
+ {
+ LoadFromFile(sWavFile, pack);
+ }
+
+ olc::rcode SOUND::AudioSample::LoadFromFile(std::string sWavFile, olc::ResourcePack *pack)
+ {
+ auto ReadWave = [&](std::istream &is)
+ {
+ char dump[4];
+ is.read(dump, sizeof(char) * 4); // Read "RIFF"
+ if (strncmp(dump, "RIFF", 4) != 0) return olc::FAIL;
+ is.read(dump, sizeof(char) * 4); // Not Interested
+ is.read(dump, sizeof(char) * 4); // Read "WAVE"
+ if (strncmp(dump, "WAVE", 4) != 0) return olc::FAIL;
+
+ // Read Wave description chunk
+ is.read(dump, sizeof(char) * 4); // Read "fmt "
+ unsigned int nHeaderSize = 0;
+ is.read((char*)&nHeaderSize, sizeof(unsigned int)); // Not Interested
+ is.read((char*)&wavHeader, nHeaderSize);// sizeof(WAVEFORMATEX)); // Read Wave Format Structure chunk
+ // Note the -2, because the structure has 2 bytes to indicate its own size
+ // which are not in the wav file
+
+ // Just check if wave format is compatible with olcPGE
+ if (wavHeader.wBitsPerSample != 16 || wavHeader.nSamplesPerSec != 44100)
+ return olc::FAIL;
+
+ // Search for audio data chunk
+ long nChunksize = 0;
+ is.read(dump, sizeof(char) * 4); // Read chunk header
+ is.read((char*)&nChunksize, sizeof(long)); // Read chunk size
+ while (strncmp(dump, "data", 4) != 0)
+ {
+ // Not audio data, so just skip it
+ //std::fseek(f, nChunksize, SEEK_CUR);
+ is.seekg(nChunksize, std::istream::cur);
+ is.read(dump, sizeof(char) * 4);
+ is.read((char*)&nChunksize, sizeof(long));
+ }
+
+ // Finally got to data, so read it all in and convert to float samples
+ nSamples = nChunksize / (wavHeader.nChannels * (wavHeader.wBitsPerSample >> 3));
+ nChannels = wavHeader.nChannels;
+
+ // Create floating point buffer to hold audio sample
+ fSample = new float[nSamples * nChannels];
+ float *pSample = fSample;
+
+ // Read in audio data and normalise
+ for (long i = 0; i < nSamples; i++)
+ {
+ for (int c = 0; c < nChannels; c++)
+ {
+ short s = 0;
+ if (!is.eof())
+ {
+ is.read((char*)&s, sizeof(short));
+
+ *pSample = (float)s / (float)(MAXSHORT);
+ pSample++;
+ }
+ }
+ }
+
+ // All done, flag sound as valid
+ bSampleValid = true;
+ return olc::OK;
+ };
+
+ if (pack != nullptr)
+ {
+ std::istream is(&(pack->GetStreamBuffer(sWavFile)));
+ return ReadWave(is);
+ }
+ else
+ {
+ // Read from file
+ std::ifstream ifs(sWavFile, std::ifstream::binary);
+ if (ifs.is_open())
+ {
+ return ReadWave(ifs);
+ }
+ else
+ return olc::FAIL;
+ }
+ }
+
+ bool SOUND::InitialiseAudio(unsigned int nSampleRate, unsigned int nChannels, unsigned int nBlocks, unsigned int nBlockSamples)
+ {
+ // Initialise Sound Engine
+ m_bAudioThreadActive = false;
+ m_nSampleRate = nSampleRate;
+ m_nChannels = nChannels;
+ m_nBlockCount = nBlocks;
+ m_nBlockSamples = nBlockSamples;
+ m_nBlockFree = m_nBlockCount;
+ m_nBlockCurrent = 0;
+ m_pBlockMemory = nullptr;
+ m_pWaveHeaders = nullptr;
+
+ // Device is available
+ WAVEFORMATEX waveFormat;
+ waveFormat.wFormatTag = WAVE_FORMAT_PCM;
+ waveFormat.nSamplesPerSec = m_nSampleRate;
+ waveFormat.wBitsPerSample = sizeof(short) * 8;
+ waveFormat.nChannels = m_nChannels;
+ waveFormat.nBlockAlign = (waveFormat.wBitsPerSample / 8) * waveFormat.nChannels;
+ waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
+ waveFormat.cbSize = 0;
+
+ listActiveSamples.clear();
+
+ // Open Device if valid
+ if (waveOutOpen(&m_hwDevice, WAVE_MAPPER, &waveFormat, (DWORD_PTR)SOUND::waveOutProc, (DWORD_PTR)0, CALLBACK_FUNCTION) != S_OK)
+ return DestroyAudio();
+
+ // Allocate Wave|Block Memory
+ m_pBlockMemory = new short[m_nBlockCount * m_nBlockSamples];
+ if (m_pBlockMemory == nullptr)
+ return DestroyAudio();
+ ZeroMemory(m_pBlockMemory, sizeof(short) * m_nBlockCount * m_nBlockSamples);
+
+ m_pWaveHeaders = new WAVEHDR[m_nBlockCount];
+ if (m_pWaveHeaders == nullptr)
+ return DestroyAudio();
+ ZeroMemory(m_pWaveHeaders, sizeof(WAVEHDR) * m_nBlockCount);
+
+ // Link headers to block memory
+ for (unsigned int n = 0; n < m_nBlockCount; n++)
+ {
+ m_pWaveHeaders[n].dwBufferLength = m_nBlockSamples * sizeof(short);
+ m_pWaveHeaders[n].lpData = (LPSTR)(m_pBlockMemory + (n * m_nBlockSamples));
+ }
+
+ m_bAudioThreadActive = true;
+ m_AudioThread = std::thread(&SOUND::AudioThread);
+
+ // Start the ball rolling with the sound delivery thread
+ std::unique_lock lm(m_muxBlockNotZero);
+ m_cvBlockNotZero.notify_one();
+ return true;
+ }
+
+ // Stop and clean up audio system
+ bool SOUND::DestroyAudio()
+ {
+ m_bAudioThreadActive = false;
+ m_AudioThread.join();
+ return false;
+ }
+
+ // Handler for soundcard request for more data
+ void CALLBACK SOUND::waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
+ {
+ if (uMsg != WOM_DONE) return;
+ m_nBlockFree++;
+ std::unique_lock lm(m_muxBlockNotZero);
+ m_cvBlockNotZero.notify_one();
+ }
+
+ // Audio thread. This loop responds to requests from the soundcard to fill 'blocks'
+ // with audio data. If no requests are available it goes dormant until the sound
+ // card is ready for more data. The block is fille by the "user" in some manner
+ // and then issued to the soundcard.
+ void SOUND::AudioThread()
+ {
+ m_fGlobalTime = 0.0f;
+ static float fTimeStep = 1.0f / (float)m_nSampleRate;
+
+ // Goofy hack to get maximum integer for a type at run-time
+ short nMaxSample = (short)pow(2, (sizeof(short) * 8) - 1) - 1;
+ float fMaxSample = (float)nMaxSample;
+ short nPreviousSample = 0;
+
+ while (m_bAudioThreadActive)
+ {
+ // Wait for block to become available
+ if (m_nBlockFree == 0)
+ {
+ std::unique_lock lm(m_muxBlockNotZero);
+ while (m_nBlockFree == 0) // sometimes, Windows signals incorrectly
+ m_cvBlockNotZero.wait(lm);
+ }
+
+ // Block is here, so use it
+ m_nBlockFree--;
+
+ // Prepare block for processing
+ if (m_pWaveHeaders[m_nBlockCurrent].dwFlags & WHDR_PREPARED)
+ waveOutUnprepareHeader(m_hwDevice, &m_pWaveHeaders[m_nBlockCurrent], sizeof(WAVEHDR));
+
+ short nNewSample = 0;
+ int nCurrentBlock = m_nBlockCurrent * m_nBlockSamples;
+
+ auto clip = [](float fSample, float fMax)
+ {
+ if (fSample >= 0.0)
+ return fmin(fSample, fMax);
+ else
+ return fmax(fSample, -fMax);
+ };
+
+ for (unsigned int n = 0; n < m_nBlockSamples; n += m_nChannels)
+ {
+ // User Process
+ for (unsigned int c = 0; c < m_nChannels; c++)
+ {
+ nNewSample = (short)(clip(GetMixerOutput(c, m_fGlobalTime, fTimeStep), 1.0) * fMaxSample);
+ m_pBlockMemory[nCurrentBlock + n + c] = nNewSample;
+ nPreviousSample = nNewSample;
+ }
+
+ m_fGlobalTime = m_fGlobalTime + fTimeStep;
+ }
+
+ // Send block to sound device
+ waveOutPrepareHeader(m_hwDevice, &m_pWaveHeaders[m_nBlockCurrent], sizeof(WAVEHDR));
+ waveOutWrite(m_hwDevice, &m_pWaveHeaders[m_nBlockCurrent], sizeof(WAVEHDR));
+ m_nBlockCurrent++;
+ m_nBlockCurrent %= m_nBlockCount;
+ }
+ }
+
+ // This vector holds all loaded sound samples in memory
+ std::vector vecAudioSamples;
+
+ // This structure represents a sound that is currently playing. It only
+ // holds the sound ID and where this instance of it is up to for its
+ // current playback
+
+ void SOUND::SetUserSynthFunction(std::function func)
+ {
+ funcUserSynth = func;
+ }
+
+ void SOUND::SetUserFilterFunction(std::function func)
+ {
+ funcUserFilter = func;
+ }
+
+ // Load a 16-bit WAVE file @ 44100Hz ONLY into memory. A sample ID
+ // number is returned if successful, otherwise -1
+ unsigned int SOUND::LoadAudioSample(std::string sWavFile, olc::ResourcePack *pack)
+ {
+
+ olc::SOUND::AudioSample a(sWavFile, pack);
+ if (a.bSampleValid)
+ {
+ vecAudioSamples.push_back(a);
+ return vecAudioSamples.size();
+ }
+ else
+ return -1;
+ }
+
+ // Add sample 'id' to the mixers sounds to play list
+ void SOUND::PlaySample(int id, bool bLoop)
+ {
+ olc::SOUND::sCurrentlyPlayingSample a;
+ a.nAudioSampleID = id;
+ a.nSamplePosition = 0;
+ a.bFinished = false;
+ a.bFlagForStop = false;
+ a.bLoop = bLoop;
+ SOUND::listActiveSamples.push_back(a);
+ }
+
+ void SOUND::StopSample(int id)
+ {
+ // Find first occurence of sample id
+ auto s = std::find_if(listActiveSamples.begin(), listActiveSamples.end(), [&](const olc::SOUND::sCurrentlyPlayingSample &s) { return s.nAudioSampleID == id; });
+ if(s != listActiveSamples.end())
+ s->bFlagForStop = true;
+ }
+
+ void SOUND::StopAll()
+ {
+ for (auto &s : listActiveSamples)
+ {
+ s.bFlagForStop = true;
+ }
+ }
+
+ float SOUND::GetMixerOutput(int nChannel, float fGlobalTime, float fTimeStep)
+ {
+ // Accumulate sample for this channel
+ float fMixerSample = 0.0f;
+
+ for (auto &s : listActiveSamples)
+ {
+ if (m_bAudioThreadActive)
+ {
+ if (s.bFlagForStop)
+ {
+ s.bLoop = false;
+ s.bFinished = true;
+ }
+ else
+ {
+ // Calculate sample position
+ s.nSamplePosition += (long)((float)vecAudioSamples[s.nAudioSampleID - 1].wavHeader.nSamplesPerSec * fTimeStep);
+
+ // If sample position is valid add to the mix
+ if (s.nSamplePosition < vecAudioSamples[s.nAudioSampleID - 1].nSamples)
+ fMixerSample += vecAudioSamples[s.nAudioSampleID - 1].fSample[(s.nSamplePosition * vecAudioSamples[s.nAudioSampleID - 1].nChannels) + nChannel];
+ else
+ {
+ if (s.bLoop)
+ {
+ s.nSamplePosition = 0;
+ }
+ else
+ s.bFinished = true; // Else sound has completed
+ }
+ }
+ }
+ else
+ return 0.0f;
+ }
+
+ // If sounds have completed then remove them
+ listActiveSamples.remove_if([](const sCurrentlyPlayingSample &s) {return s.bFinished; });
+
+ // The users application might be generating sound, so grab that if it exists
+ if(funcUserSynth != nullptr)
+ fMixerSample += funcUserSynth(nChannel, fGlobalTime, fTimeStep);
+
+ // Return the sample via an optional user override to filter the sound
+ if (funcUserFilter != nullptr)
+ return funcUserFilter(nChannel, fGlobalTime, fMixerSample);
+ else
+ return fMixerSample;
+ }
+
+
+ unsigned int SOUND::m_nSampleRate = 0;
+ unsigned int SOUND::m_nChannels = 0;
+ unsigned int SOUND::m_nBlockCount = 0;
+ unsigned int SOUND::m_nBlockSamples = 0;
+ unsigned int SOUND::m_nBlockCurrent = 0;
+ short* SOUND::m_pBlockMemory = nullptr;
+ WAVEHDR *SOUND::m_pWaveHeaders = nullptr;
+ HWAVEOUT SOUND::m_hwDevice;
+ std::thread SOUND::m_AudioThread;
+ std::atomic SOUND::m_bAudioThreadActive = false;
+ std::atomic SOUND::m_nBlockFree = 0;
+ std::condition_variable SOUND::m_cvBlockNotZero;
+ std::mutex SOUND::m_muxBlockNotZero;
+ std::atomic SOUND::m_fGlobalTime = 0.0f;
+ std::list SOUND::listActiveSamples;
+ std::function SOUND::funcUserSynth = nullptr;
+ std::function SOUND::funcUserFilter = nullptr;
+}
+#endif
+
+// Currently no Linux implementation so just go blank :(
+
+#endif
\ No newline at end of file
diff --git a/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPixelGameEngine.h b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPixelGameEngine.h
new file mode 100644
index 0000000..283a370
--- /dev/null
+++ b/C++/Pixel-Engine/Particle-Physics/Particle-Physics/olcPixelGameEngine.h
@@ -0,0 +1,2047 @@
+/*
+ olcPixelGameEngine.h
+
+ +-------------------------------------------------------------+
+ | OneLoneCoder Pixel Game Engine v1.11 |
+ | "Like the command prompt console one, but not..." - javidx9 |
+ +-------------------------------------------------------------+
+
+ The Original & Best... :P
+
+ What is this?
+ ~~~~~~~~~~~~~
+ The olcConsoleGameEngine has been a surprsing and wonderful
+ success for me, and I'm delighted how people have reacted so
+ positively towards it, so thanks for that.
+
+ However, there are limitations that I simply cannot avoid.
+ Firstly, I need to maintain several different versions of
+ it to accommodate users on Windows7, 8, 10, Linux, Mac,
+ Visual Studio & Code::Blocks. Secondly, this year I've been
+ pushing the console to the limits of its graphical capabilities
+ and the effect is becoming underwhelming. The engine itself
+ is not slow at all, but the process that Windows uses to
+ draw the command prompt to the screen is, and worse still,
+ it's dynamic based upon the variation of character colours
+ and glyphs. Sadly I have no control over this, and recent
+ videos that are extremely graphical (for a command prompt :P )
+ have been dipping to unacceptable framerates. As the channel
+ has been popular with aspiring game developers, I'm concerned
+ that the visual appeal of the command prompt is perhaps
+ limited to us oldies, and I dont want to alienate younger
+ learners. Finally, I'd like to demonstrate many more
+ algorithms and image processing that exist in the graphical
+ domain, for which the console is insufficient.
+
+ For this reason, I have created olcPixelGameEngine! The look
+ and feel to the programmer is almost identical, so all of my
+ existing code from the videos is easily portable, and the
+ programmer uses this file in exactly the same way. But I've
+ decided that rather than just build a command prompt emulator,
+ that I would at least harness some modern(ish) portable
+ technologies.
+
+ As a result, the olcPixelGameEngine supports 32-bit colour, is
+ written in a cross-platform style, uses modern(ish) C++
+ conventions and most importantly, renders much much faster. I
+ will use this version when my applications are predominantly
+ graphics based, but use the console version when they are
+ predominantly text based - Don't worry, loads more command
+ prompt silliness to come yet, but evolution is important!!
+
+ License (OLC-3)
+ ~~~~~~~~~~~~~~~
+
+ Copyright 2018 OneLoneCoder.com
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions or derivations of source code must retain the above
+ copyright notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions or derivative works in binary form must reproduce
+ the above copyright notice. This list of conditions and the following
+ disclaimer must be reproduced in the documentation and/or other
+ materials provided with the distribution.
+
+ 3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Links
+ ~~~~~
+ YouTube: https://www.youtube.com/javidx9
+ Discord: https://discord.gg/WhwHUMV
+ Twitter: https://www.twitter.com/javidx9
+ Twitch: https://www.twitch.tv/javidx9
+ GitHub: https://www.github.com/onelonecoder
+ Homepage: https://www.onelonecoder.com
+
+ Relevant Videos
+ ~~~~~~~~~~~~~~~
+ https://youtu.be/kRH6oJLFYxY Introducing olcPixelGameEngine
+
+ Compiling in Linux
+ ~~~~~~~~~~~~~~~~~~
+ You will need a modern C++ compiler, so update yours!
+ To compile use the command:
+
+ g++ -o YourProgName YourSource.cpp -lX11 -lGL -lpthread -lpng
+
+ On some Linux configurations, the frame rate is locked to the refresh
+ rate of the monitor. This engine tries to unlock it but may not be
+ able to, in which case try launching your program like this:
+
+ vblank_mode=0 ./YourProgName
+
+
+ Compiling in Code::Blocks on Windows
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Well I wont judge you, but make sure your Code::Blocks installation
+ is really up to date - you may even consider updating your C++ toolchain
+ to use MinGW32-W64, so google this. You will also need to enable C++14
+ in your build options, and add to your linker the following libraries:
+ user32 gdi32 opengl32 gdiplus
+
+ Thanks
+ ~~~~~~
+ I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim,
+ JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice
+ & MagetzUb for advice, ideas and testing, and I'd like to extend
+ my appreciation to the 14K YouTube followers and 1K Discord server
+ members who give me the motivation to keep going with all this :D
+
+ Special thanks to those who bring gifts!
+ GnarGnarHead.......Domina
+ Gorbit99...........Bastion
+
+ Author
+ ~~~~~~
+ David Barr, aka javidx9, ©OneLoneCoder 2018
+*/
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/* Example Usage (main.cpp)
+ #define OLC_PGE_APPLICATION
+ #include "olcPixelGameEngine.h"
+ // Override base class with your custom functionality
+ class Example : public olc::PixelGameEngine
+ {
+ public:
+ Example()
+ {
+ sAppName = "Example";
+ }
+ public:
+ bool OnUserCreate() override
+ {
+ // Called once at the start, so create things here
+ return true;
+ }
+ bool OnUserUpdate(float fElapsedTime) override
+ {
+ // called once per frame, draws random coloured pixels
+ for (int x = 0; x < ScreenWidth(); x++)
+ for (int y = 0; y < ScreenHeight(); y++)
+ Draw(x, y, olc::Pixel(rand() % 255, rand() % 255, rand()% 255));
+ return true;
+ }
+ };
+ int main()
+ {
+ Example demo;
+ if (demo.Construct(256, 240, 4, 4))
+ demo.Start();
+ return 0;
+ }
+*/
+
+#ifndef OLC_PGE_DEF
+#define OLC_PGE_DEF
+
+#ifdef _WIN32
+ // Link to libraries
+#ifndef __MINGW32__
+ #pragma comment(lib, "user32.lib") // Visual Studio Only
+ #pragma comment(lib, "gdi32.lib") // For other Windows Compilers please add
+ #pragma comment(lib, "opengl32.lib") // these libs to your linker input
+ #pragma comment(lib, "gdiplus.lib")
+#else
+ // In Code::Blocks, Select C++14 in your build options, and add the
+ // following libs to your linker: user32 gdi32 opengl32 gdiplus
+#endif
+ // Include WinAPI
+ #include
+ #include
+
+ // OpenGL Extension
+ #include
+ typedef BOOL(WINAPI wglSwapInterval_t) (int interval);
+ static wglSwapInterval_t *wglSwapInterval;
+#else
+ #include
+ #include
+ #include
+ #include
+ #include
+ typedef int(glSwapInterval_t) (Display *dpy, GLXDrawable drawable, int interval);
+ static glSwapInterval_t *glSwapIntervalEXT;
+#endif
+
+
+// Standard includes
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include