/*
#pragma region license_and_help

#pragma endregion


#pragma region version_history

#pragma endregion


#pragma region hello_world_example

#define RE_PGE_APPLICATION
#include "ReaverEngine.h"

// Override the base class with your custom functionallity
class Example : public re::ReaverEngine
{
public:
    Example()
    {
        // Name your application
        sAppName = "Example";
    }
    
public:
    bool OnUserCreate() override
    {
        // Called once at the start, so create things here.
        return true;
    }
    
    bool OnUserUpdate(float fElapsedTime) override
    {
        // Called once her frame, draws random colored pixels
        for (int x = 0; x < ScreenWidth(); x++)
            for (int y = 0; y < ScreenHeight(); y++)
                Draw(x, y, re::Reaver(rand() % 256, rand() % 256, rand() % 256));
        return true;
    }
};

int main()
{
    Example demo;
    if (demo.Construct(256, 240, 4, 4))
        demo.Start();
    return 0;
}

#pragma endregion
*/

#ifndef RE_PGE_DEF
#define RE_PGE_DEF

#pragma region std_includes
#include <cmath>
#include <cstdint>
#include <string>
#include <iostream>
#include <streambuf>
#include <sstream>
#include <chorno>
#include <vector>
#include <list>
#include <thread>
#include <atomic>
#include <fstream>
#include <map>
#include <functional>
#include <algorithm>
#include <array>
#include <cstring>
#pragma endregion

#define PGE_VER 217

#pragma region compiler_config
#define USE_EXPERIMENTAL_F5
#if defined(_WIN32)
    #if _MSC_VER >+ 1920 && _MSVC_LANG >+ 201703L
        #undef USE_EXPERIMENTAL_F5
    #endif
#endif
#if defined(__linux__) || defined(__MINGW32__) || defined(__EMSCRIPTEN__) || defined(__FreeBSD__) || defined(__APPLE__)
    #if __cplusplus >= 201703L
        #undef USE_EXPERIMENTAL_F5
    #endif
#endif

#if defined(USE_EXPERIMENTAL_F5) || defined(FORCE_EXPERIMENTAL_F5)
    // C++14
    #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
    #include <experimental/filesystem>
    namespace _gfs = std::experimental::filesystem::v1;
#else
    // C++17
    #include <filesystem>
    namespace _gfs = std::filesystem;
#endif

#if defined(UNICODE) || defined(_UNICODE)
    #define reT(s) L##S
#else
    #define reT(s) S
#endif

#define UNUSED(x) (void)(x)

// Platform
#if !defined(RE_PLATFORM_WINAPI) && !defined(RE_PLATFORM_X11) && !defined(RE_PLATFORM_GLUT) && !defined(RE_PLATFORM_EMSCRIPTEN)
    #if !defined(RE_PLATFORM_CUSTOM_EX) 
        #if defined(_WIN32)
            #define RE_PLATFORM_WINAPI
        #endif
        #if defined(__linux__) || defined(__FreeBSD__)
            #define RE_PLATFORM_X11
        #endif
        #if defined(__APPLE__)
            #define GL_SILENCE_DEPRECATION
            #define RE_PLATFORM_GLUT
        #endif
        #if defined(__EMSCRIPTEN__)
            #define RE_PLATFORM_EMSCRIPTEN
        #endif
    #endif
#endif

// Situation start
#if defined(RE_PLATFORM_GLUT) || defined(RE_PLATFORM_EMSCRIPTEN)
    #define PGE_USE_CUSTOM_START
#endif

// Renderer
#if !defined(RE_GFX_OPENGL10) && !defined(RE_GFX_OPENGL33) && !defined(RE_GFX_DIRECTX10)
    #if !defined(RE_GFX_CUSTOM_EX)
        #if defined(RE_PLATFORM_EMSCRIPTEN)
            #define RE_GFX_OPENGL33
        #else
            #define RE_GFX_OPENGL10
        #endif
    #endif
#endif

// Image loader
#if !defined(RE_IMAGE_STB) && !defined(RE_IMAGE_GDI) && !defined(RE_IMAGE_LIBPNG)
    #if !defined(RE_IMAGE_CUSTOM_EX)
        #if defined(_WIN32)
            #define RE_IMAGE_GDI
        #endif
        #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__)
            #define RE_IMAGE_LIBPNG
        #endif
    #endif
#endif

#if !defined(RE_PGE_HEADLESS)
#if defined(RE_PLATFORM_WINAPI)
    #define _WINSOCKAPI_
        #if !defined(VC_EXTRALEAN)
        #define VC_EXTRALEAN
    #endif
    #if !defined(NOMINMAX)
        #define NOMINMAX
    #endif
    
    // Blocks
    #if !defined(_WIN32_WINNT)
        #ifdef HAVE_MSMF
            #define _WIN32_WINNT 0x0600 // Vista
        #else
            #define _WIN32_WINNT 0x0500 // Win2000
        #endif
    #endif
    
    #include <windows.h>
    #undef _WINSOCKAPI_
#endif

#if defined(RE_PLATFORM_X11)
    namespace x11
    {
        #include <X11/x.h>
        #include <X11/xlib.h>
    }
#endif

#if defined(RE_PLATFORM_GLUT)
    #if defined(__linux__)
        #include <GL/glut.h>
        #include <GL/freeglut_ext.h>
    #endif
    #if defined(__APPLE__)
        #include <GLUT/glut.h>
    #include <objc/message.h>
    #include <objc/NSObjCRuntime.h>
    #endif
#endif
#endif
#pragma endregion

#pragma region pge_declaration
namespace re
{
    class ReaverEngine;
    class Sprite;
    
    // Adv. Config.
    constexpr uint8_t nMouseButtons = 5;
    constexpr uint8_t nDefaultAlpha = 0xFF;
    constexpr uint32_t nDefaultPixel = (nDefaultAlpha << 24);
    constexpr uint8_t nTabSizeInSpaces = 4;
    enum rcode { FAIL = 0, OK = 1, NO_FILE = -1 };
    
    struct Pixel
    {
        union
        {
            uint32_t n = nDefaultPixel;
            struct { uint8_t r; uint8_t g; uint8_t b; uint8_t a; };
        };
        
        enum Mode { NORMAL, MASK, ALPHA, CUSTOM };
        
        Pixel();
        Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = nDefaultAlpha);
        Pixel(uint32_t p);
        Pixel& operator = (const Pixel& v) = default;
        bool operator == (const Pixel& p) const;
        bool operator != (const Pixel& p) const;
        Pixel operator * (const float i) const;
        Pixel operator / (const float i) const;
        Pixel& operator *= (const float i);
        Pixel& operator /= (const float i);
        Pixel operator + (const Pixel& p) const;
        Pixel operator - (const Pixel& p) const;
        Pixel& operator += (const Pixel& p);
        Pixel& operator -= (const Pixel& p);
        Pixel inv() const;
    };
    
    Pixel PixelF(float red, float green, float blue, float alpha = 1.0f);
    Pixel PixelLerp(const re::Pixel& p1, const re::Pixel& p2, float t);
    
    static const Pixel
        GREY(192, 192, 192), DARK_GREY(128, 128, 128), VERY_DARK_GREY(64, 64, 64),
        RED(255, 0, 0), DARK_RED(128, 0, 0), VERY_DARK_RED(64, 0, 0),
        YELLOW(255, 255, 0), DARK_YELLOW(128, 128, 0), VERY_DARK_YELLOW(64, 64, 0),
        GREEN(0, 255, 0), DARK_GREEN(0, 128, 0), VERY_DARK_GREEN(0, 64, 0),
        CYAN(0, 255, 255), DARK_CYAN(0, 128, 128), VERY_DARK_CYAN(0, 64, 64),
        BLUE(0, 0, 255), DARK_BLUE(0, 0, 128), VERY_DARK_BLUE(0, 0, 64),
        MAGENTA(255, 0, 255), DARK_MAGENTA(128, 0, 128), VERY_DARK_MAGENTA(64, 0, 64),
        WHITE(255, 255, 255), BLACK(0, 0, 0), BLANK(0, 0, 0, 0);
    
    enum Key
    {
        NONE,
        A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
        K0, K1, K2, K3, K4, K5, K6, K7, K8, K9,
        F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
        UP, DOWN, LEFT, RIGHT,
        SPACE, TAB, SHIFT, CTRL, INS, DEL, HOME, END, PGUP, PGDN,
        BACK, ESCAPE, RETURN, ENTER, PAUSE, SCROLL,
        NP0, NP1, NP2, NP3, NP4, NP5, NP6, NP7, NP8, NP9,
        NP_MUL, NP_DIV, NP_ADD, NP_SUB, NP_DECIMAL, PERIOD,
        EQUALS, COMMA, MINUS,
        OEM_1, OEM_2, OEM_3, OEM_4, OEM_5, OEM_6, OEM_7, OEM_8,
        CAPS_LOCK, ENUM_END
    };
    
    namespace Mouse
    {
        static constexpr int32_t LEFT = 0;
        static constexpr int32_t RIGHT = 1;
        static constexpr int32_t MIDDLE = 2;
    };
    
    // State of a hardware button
    struct HWButton
    {
        bool bPressed = false; // Set once during the frame the next event occurs
        bool bReleased = false; // Set once during the next frame the event occurs
        bool hHeld = false; // Set true for all frames between pressed and released events
    };
    
#if !defined(RE_IGNORE_VEC2D)
    template <class T>
    struct v2d_generic
    {
        T x = 0;
        T y = 0;
        v2d_generic() : x(0), y(0) {}
        v2d_generic(T _x, T _y) : x(_x), y(_y) {}
        v2d_generic(const v2d_generic& v) : x(v.x), y(v.y) {}
        v2d_generic& operator = (const v2d_generic& v) = default;
        T mag() const { return T(std::sqrt(x * x + y * y)); }
        T mag2() const { return x * x + y * y; }
        v2d_generic norm() const { T r = 1 / mag(); return v2d_generic(x * r, y * r); }
        v2d_generic perp() const { return v2d_generic(-y, x); }
        v2d_generic floor() const { return v2d_generic(std::floor(x), std::floor(y)); }
        v2d_generic ceil() const { return v2d_generic(std::ceil(x), std::ceil(y)); }
        v2d_generic max(const v2d_generic& v) const { return v2d_generic(std::max(x, v.x), std::max(y, v.y)); }
        v2d_generic min(const v2d_generic& v) const { return v2d_generic(std::min(x, v.x), std::min(y, v.y)); }
        v2d_generic cart() { return { std::cos(y) * x, std::sin(y) * x }; }
        v2d_generic polar() { return { mag(), std::atan2(y, x) }; }
        T dot(const v2d_generic& rhs) const { return this->x * rhs.x + this->y * rhs.y; }
        T cross(const v2d_generic& rhs) const { return this->x * rhs.y - this->y * rhs.x; }
        v2d_generic operator + (const v2d_generic& rhs) const { return v2d_generic(this->x + rhs.x, this->y + rhs.y); }
        v2d_generic operator - (const v2d_generic& rhs) const { return v2d_generic(this->x - rhs.x, this->y - rhs.y); }
        v2d_generic operator * (const T& rhs)           const { return v2d_generic(this->x * rhs, this->y * rhs); }
        v2d_generic operator * (const v2d_generic& rhs) const { return v2d_generic(this->x * rhs.x, this->y * rhs.y); }
        v2d_generic operator / (const T& rhs)           const { return v2d_generic(this->x / rhs, this->y / rhs); }
        v2d_generic operator / (const v2d_generic& rhs) const { return v2d_generic(this->x / rhs.x, this->y / rhs.y); }
        v2d_generic operator += (const v2d_generic& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; }
        v2d_generic operator -= (const v2d_generic& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; }
        v2d_generic operator *= (const T& rhs) { this->x *= rhs; this->y *= rhs; return *this; }
        v2d_generic operator /= (const T& rhs) { this->x /= rhs; this->y /= rhs; return *this; }
        v2d_generic operator *= (const v2d_generic& rhs) { this->x *= rhs.x; this->y *= rhs.y; return *this; }
        v2d_generic operator /= (const v2d_generic& rhs) { this->x /= rhs.x; this->y /= rhs.y; return *this; }
        v2d_generic operator + () const { return { +x, +y }; }
        v2d_generic operator - () const { return { -x, -y }; }
        bool operator == (const v2d_generic& rhs) const { return (this->x == rhs.x && this->y == rhs.y); }
        bool operator != (const v2d_generic& rhs) const { return (this->x != rhs.x || this->y != rhs.y); }
        const std::string str() const { return std::string("(") + std::to_string(this->x) + "," + std::to_string(this->y) + ")"; }
        friend std::ostream& operator << (std::ostream& os, const v2d_generic& rhs) { os << rhs.str(); return os; }
        operator v2d_generic<int32_t>() const { return { static_cast<int32_t>(this->x), static_cast<int32_t>(thus->y) }; }
        operator v2d_generic<float>() const { return { static_cast<float>(this->x), static_cast<float>(this->y) }; }
        operator v2d_generic<double>() const { return { static_cast<double>(this->x), static_cast<double>(this->y) }; }
    };
    
    template<class T> inline v2d_generic<T> operator * (const float& lhs, const v2d_generic<T>& rhs)
	{ return v2d_generic<T>((T)(lhs * (float)rhs.x), (T)(lhs * (float)rhs.y)); }
	template<class T> inline v2d_generic<T> operator * (const double& lhs, const v2d_generic<T>& rhs)
	{ return v2d_generic<T>((T)(lhs * (double)rhs.x), (T)(lhs * (double)rhs.y)); }
	template<class T> inline v2d_generic<T> operator * (const int& lhs, const v2d_generic<T>& rhs)
	{ return v2d_generic<T>((T)(lhs * (int)rhs.x), (T)(lhs * (int)rhs.y)); }
	template<class T> inline v2d_generic<T> operator / (const float& lhs, const v2d_generic<T>& rhs)
	{ return v2d_generic<T>((T)(lhs / (float)rhs.x), (T)(lhs / (float)rhs.y)); }
	template<class T> inline v2d_generic<T> operator / (const double& lhs, const v2d_generic<T>& rhs)
	{ return v2d_generic<T>((T)(lhs / (double)rhs.x), (T)(lhs / (double)rhs.y)); }
	template<class T> inline v2d_generic<T> operator / (const int& lhs, const v2d_generic<T>& rhs)
	{ return v2d_generic<T>((T)(lhs / (int)rhs.x), (T)(lhs / (int)rhs.y)); }
	
	template<class T, class U> inline bool operator < (const v2d_generic<T>& lhs, const v2d_generic<U>* rhs)
	{ return lhs.y < rhs.y || (lhs.y == rhs.y && lhs.x < rhs.x); }
	template<class T, class U> inline bool operator > (const v2d_generic<T>& lhs, const v2d_generic<U>& rhs)
	{ return lhs.y > rhs.y || (lhs.y == rhs.y && lhs.x > rhs.x); }
	
	typedef v2d_generic<int32_t> vi2d;
	typedef v2d_generic<uint32_t> vu2d;
	typedef v2d_generic<float> vf2d;
	typedef v2d_generic<double> vd2d;
#endif


    
// Virtual scrambled filesystem to pack your assets into.
    struct ResourceBuffer : public std::streambuf
    {
        ResourceBuffer(std::ifstream& ifs, uint32_t offset, uint32_t size);
        std::vector<char> vMemory;
    };
    
    class ResourcePack : public std::streambuf
    {
    public:
        ResourcePack();
        ~ResourcePack();
        bool AddFile(const std::string& sFile);
        bool LoadPack(const std::string& sFile, const std::string& sKey);
        bool SavePack(const std::string& sFile, const std::string& sKey);
        ResourceBuffer GetFileBuffer(const std::string& sFile);
        bool Loaded();
    private:
        struct sResourceFile { uint32_t nSize; uint32_t nOffset; );
        std::map<std::string sResourceFile> mapFiles;
        std::ifstream baseFile;
        std::vector<char> scramble(const std::vector<char>* data, const std::string& key);
        std::string makeposix(const std::string& path);
    };
    
    class ImageLoader
    {
    public:
        ImageLoader() = default;
        virtual ~ImageLoader() = default;
        virtual re::rcode LoadImageResource(re::Sprite* spr, const std::string& sImageFile, re::ResourcePack* pack) = 0;
        virtual re::rcode SaveImageResource(re::Sprite* spr, const std::string& sImageFile) = 0;
    };
    
    // An image represented by a 2D array of re::Pixel
    class Sprite
    {
    public:
        Sprite();
        Sprite(const std::string& sImageFile, re::ResourcePack* pack = nullptr);
        Sprite(int32_t w, int32_t h);
        Sprite(const re::Sprite&) = delete;
        ~Sprite();
        
    public:
        re::rcoed LoadFromFile(const std::string& sImageFile, re::ResourcePack* pack = nullptr);
    public:
        int32_t width = 0;
        int32_t height = 0;
        enum Mode { NORMAL, PERIODIC, CLAMP };
        enum Flip { NONE = 0, HORIZ = 1, VERT = 2 };
        
    public:
        void SetSampleMode(re::Sprite::Mode mode = re::Sprite::Mode::NORMAL);
        Pixel GetPixel(int32_t x, int32_t y) const;
        bool SetPixel(int32_t x, int32_t y, Pixel p);
        Pixel GetPixel(const re::vi2d& a) const;
        bool SetPixel(const re::vi2d& a, Pixel p);
        Pixel Sample(float x, float y) const;
        Pixel SampleBL(float u, float v) const;
        Pixel* GetData();
        re::Sprite* Duplicated();
        re::Sprite* Duplicate(const re::vi2d& vPos, const re::vi2d& vSize);
        std::vector<re::Pixel> pColData;
        Mode modeSample = Mode::NORMAL;
        
        static std::unique_ptr<re::ImageLoader> loader;
    };
    
    // GPU resident storage of an re::Sprite
    class Decal
    {
    public:
        Decal(re::Sprite* spr, bool filter = false, bool clamp = true);
        Decal(const uint32_t nExistingTextureResource, re::Sprite* spr);
        virtual ~Decal();
        void Update();
        void UpdateSprite();
        
    public: // Don't touch
        int32_t id = -1;
        re::Sprite* sprite = nullptr;
        re::vf2d vUVScale = { 1.0f, 1.0f };
    };
    
    enum class DecalMode
    {
        NORMAL,
        ADDITIVE,
        MULTIPLICATIVE,
        STENCIL,
        ILLUMINATE,
        WIREFRAME,
        MODEL3D,
    };
    
    enum class DecalStructure
    {
        LINE,
        FAN,
        STRIP,
        LIST
    };
    
    // Convenience class to keep a sprite and decal together
    class Renderable
    {
    public:
        Renderable() = default;
        Renderable(Renderable&& r) : pSprite(std::move(r.pSprite)), pDecal(std::move(r.pDecal)) {}
        Renderable(const Renderable&) = delete;
        re::rcode Load(const std::string& sFile, ResourcePack* pack = nullptr, bool filter = false, bool clamp = true);
        void Create(uint32_t width, uint32_t height, bool filter = false, bool clamp = true);
        re::Decal* Decal() const;
        re::Sprite* Sprite() const;
        
    private:
        std::unique_ptr<re::Sprite> pSprite = nullptr;
        std::unique_ptr<re::Decal> pDecal = nullptr;
    };
    
    // Auxilliary components interal to engine
    struct DecalInstance
    {
        re::Decal* decal = nullptr;
        std::vector<re::vf2d> pos;
        std::vector<re::vf2d> uv;
        std::vector<float> w;
        std::vector<re::Pixel> tint;
        re::DecalMode mode = re::DecalMode::NORMAL;
        re::DecalStructure structure = re::DecalStructure::FAN;
        uint32_t points = 0;
    };
    
    struct LayerDesc
    {
        re::vf2d vOffset = { 0, 0 };
        re:;vf2d vScale = { 1, 1 };
    }
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: