From 8651ee65cf5465da06e649f9bef3d5c751ee5af0 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Thu, 29 Sep 2022 23:53:14 -0500 Subject: [PATCH] Include a launch.json and tasks.json example files Co-authored-by: sigonasr2 --- C++ProjectTemplate | Bin 543576 -> 543640 bytes a.out | Bin 0 -> 543576 bytes dirtblock.png | Bin 0 -> 35629 bytes grass.png | Bin 0 -> 541 bytes main.cpp | 69 +- olcPixelGameEngine.h | 6191 ------------------------------------------ 6 files changed, 5 insertions(+), 6255 deletions(-) create mode 100755 a.out create mode 100644 dirtblock.png create mode 100644 grass.png delete mode 100644 olcPixelGameEngine.h diff --git a/C++ProjectTemplate b/C++ProjectTemplate index 29e3bbbe955517170f40d6615465688971ba7d76..3b106d22fe9b29e67ff737924508c2e3b5dd455b 100755 GIT binary patch delta 100969 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
bpTR_n)Il^==ol$oqug(PNgzate zKkmX4f!b_SMBrA6Xg?_8K8*9g#J?_$Y95!&&1Uvw;%hMMn3Epgx4x| zpFC|6xK_z_ZG8H@j=hMO0D)tFvFQqV3%<*^EfZ9%EfRWaH4GFWA51<)PMzKB2l9>N z;orL9rMhaJ3~Gle6FL?lyD~x*;cnwO$BFnG`_&(>`sUoG8?d#z#kd*pjqhkSNR ziLlO#Fi=o7AKgobwgINr7?}`Er}%vquMQk()%9~Dp3#b4`;csJ7#?;@f(!P3#X>58|CbSinu1!Qn0!>=-TL|uuk6qgwQ zbvphZGa<=h?GD9PDb~a^mR!2l*2oOiy|f3NPyS|M@Cmeb%}f$?C2DpL#xBtv(d@_g-X$M89O1Q4-8*I7)J5+C*Rsgl1AGE|JI&1?;qJ)QcAN|v z-!afwakP7dG7-r^<$kfyvzsp?YeD@(g}aG3Es3Z* zSp(gGF+Jl5?}^CvV{4s-V@WuSAx_XI+6R41Zhtt;(+e8y&B#XNyFNn-v@FJw54Y;` zCh#by8XsNP{65zk20pw3Man0V2gpq%?zNSExM1##m%8v5#r7ws%EdulF^)8P=D3J_ z!g-j{k>McuiBaHM!2|k0kGLH{TD+ft$2w^Xb1FK>2s1{2zf1%7$?dxpD))l{`-L4Z89%S= z=Ol{QS7GD7XTXQ~p;-NWfIN^*Kxc}>`a|)n;}Kpv)aB&kt($i4o4I1pTR?g+H^cUG zg+0h`@tuL{pbv$+Biq#F$mreN_|0Va8+Ty7JpE96AoK?wN43%Y-VxxY@da0=gt0v1R5#uwFTkm} zmU^|J2>3zi?VNP>8P$LY6z=4}#q$Z^K2j`onz{h3GdACQB_HivKv*rlKnA9>P@eqpXdZ zryt0t?uHYZG7$mN<+_Pp{S)}>2^AX{`wc9(MLY^%5KfVp$XI_JvHgbQ0 zd-=8^&vmylHE%i;_y6U z5p71zoYAV2NA3mJS}}m!elB1gdFmGkubb>y6=cf%Bbts!-V+4{?fXP$lK(LY z>a@^4CBJ+uXJOtZe~<5O*6GnJUZ34IPLc-^bQ<&~1Wq(hDszpi zAkdQO!U(rZf~&6beo9j<*Z_{lxM`w77`T3h#?@NR0G6h8c?G#i(!JEc9uqQCCh(6$ zT+SVzz4@j=alK!lK-&+~tVzP%3Y2#j^h7cI2J%a@zzdN7 z3trUeYwg{Xe~&fA6R-dB?vj7G%GYr?)ZX?2d2Vi&t9z@=K=^(1qUL@)`N>;Ij27Q@ z^1OU8%@8KC!uviwfzC^h5J6j0bF*TWbYyXmJ15vN1u@z*nxdt}trRyfCFlPx+-BTvukvec|raj4_9p zxwEBWj2AIhb_W^or3+A?9n2&0A=U%5b!J2Hz1#>NPsKCH?Po?-nUD`;sJKS)H=7Vm zi=>a~B;trqKJfQFa6a*i0H40R)S4>X%|`wKh^8L%pJP%!kUJ@Q&OtRDn~Vr^ky~ek za5vulIKIy!JHl$$d@d~`GDM>%Q-R!cE^b6YZ0(3 zJ=EQV%#)gXP{gjfjAc+ajp|-BokZ+STMTiJCYT~=Dk?~}L*$F8x~4CHWRVaGhi2TH@31b<(-i)B4a90w;AK zA}F6tZg(`7$$K3`cYe*td`#BVQj31M1Qzi)}S}c9pfn$<314XipLK?Qftu6ee!O+$-f$T z+qDR9AAI#AkK8*gcCknPcs zPa)oJX_DIJo$B}4{L?mXjY4@Bp_A9&@up$ByfvPgG97*Vly6>Zm$$9IUvu+qbl&>U cOkC{oNh6pza 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
58peXcKi4 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 KCaqaux&H_C80jeh diff --git a/a.out b/a.out new file mode 100755 index 0000000000000000000000000000000000000000..48a50f8d248706f3de38fcc2ae8a9b0f9c75c3d5 GIT binary patch literal 543576 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
IEsU5an*ZV^lqfT3P(FdvAV$g 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 literal 0 HcmV?d00001 diff --git a/dirtblock.png b/dirtblock.png new file mode 100644 index 0000000000000000000000000000000000000000..af8bd9194d19cb226b0ebc392c2a80044008ad90 GIT binary patch literal 35629 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 z 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 literal 0 HcmV?d00001 diff --git a/grass.png b/grass.png new file mode 100644 index 0000000000000000000000000000000000000000..32120250f6d77c8324566839524ae6688796d11e GIT binary patch literal 541 zcmV+&0^EX>4Tx04R}tkv&MmKpe$iQ;Q!|1nnTwAw%tCK~%(1t5Adrp;l;qmz@OiK+|nA zm57U(?5f!Pie7{fKoo;Avy3@ON}}WVx`&UicQKyT`P`qQU(Hzz@QK8;%rI@@4dUrd z+u*!U9AZUTB|aw}GwFiFk6c$ge&bwlS>Tx=Go6|z4iSrmHdfl06-|wJia4TbI^_!) zk5$fFoV9Y5HSft^7|iJ_%Uq`!Mgogif&>u?swklh8!=jSQY@rsKi #include "pixelGameEngine.h" // use this for drawing stuff to screen using namespace olc; -//-------------------------------------------------------------------------------------------------- -// class -//-------------------------------------------------------------------------------------------------- class BallGame : public olc::PixelGameEngine { public: BallGame() { - sAppName = "Rectangle Collision"; + sAppName = "Example"; } public: - struct Rectangle{ - vd2d pos; - vd2d size; - }; - - vd2d pos = {0,0}; - Rectangle r1 = {{64,64},{16,16}}; - Rectangle r3 = {{128,64},{16,16}}; - Rectangle r2 = {pos,{8,8}}; - -//-------------------------------------------------------------------------------------------------- -// Create stuff for game -//-------------------------------------------------------------------------------------------------- bool OnUserCreate() override { return true; } -//-------------------------------------------------------------------------------------------------- -// main game function -//-------------------------------------------------------------------------------------------------- bool OnUserUpdate(float fElapsedTime) override { - - Clear(VERY_DARK_CYAN); - - if (GetKey(A).bHeld) { - r2.pos.x-=20*fElapsedTime; - } - if (GetKey(D).bHeld) { - r2.pos.x+=20*fElapsedTime; - } - if (GetKey(W).bHeld) { - r2.pos.y-=20*fElapsedTime; - } - if (GetKey(S).bHeld) { - r2.pos.y+=20*fElapsedTime; - } - - if (Collision(r1,r2)) { - FillRect(r1.pos,r1.size,YELLOW); - } else { - FillRect(r1.pos,r1.size,RED); + for (int i=0;i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#pragma endregion - -#define PGE_VER 219 - -// O------------------------------------------------------------------------------O -// | COMPILER CONFIGURATION ODDITIES | -// O------------------------------------------------------------------------------O -#pragma region compiler_config -#define USE_EXPERIMENTAL_FS -#if defined(_WIN32) - #if _MSC_VER >= 1920 && _MSVC_LANG >= 201703L - #undef USE_EXPERIMENTAL_FS - #endif -#endif -#if defined(__linux__) || defined(__MINGW32__) || defined(__EMSCRIPTEN__) || defined(__FreeBSD__) || defined(__APPLE__) - #if __cplusplus >= 201703L - #undef USE_EXPERIMENTAL_FS - #endif -#endif - -#if !defined(OLC_KEYBOARD_UK) - #define OLC_KEYBOARD_UK -#endif - - -#if defined(USE_EXPERIMENTAL_FS) || defined(FORCE_EXPERIMENTAL_FS) - // C++14 - #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING - #include - namespace _gfs = std::experimental::filesystem::v1; -#else - // C++17 - #include - namespace _gfs = std::filesystem; -#endif - -#if defined(UNICODE) || defined(_UNICODE) - #define olcT(s) L##s -#else - #define olcT(s) s -#endif - -#define UNUSED(x) (void)(x) - -// O------------------------------------------------------------------------------O -// | PLATFORM SELECTION CODE, Thanks slavka! | -// O------------------------------------------------------------------------------O - -// Platform -#if !defined(OLC_PLATFORM_WINAPI) && !defined(OLC_PLATFORM_X11) && !defined(OLC_PLATFORM_GLUT) && !defined(OLC_PLATFORM_EMSCRIPTEN) - #if !defined(OLC_PLATFORM_CUSTOM_EX) - #if defined(_WIN32) - #define OLC_PLATFORM_WINAPI - #endif - #if defined(__linux__) || defined(__FreeBSD__) - #define OLC_PLATFORM_X11 - #endif - #if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #define OLC_PLATFORM_GLUT - #endif - #if defined(__EMSCRIPTEN__) - #define OLC_PLATFORM_EMSCRIPTEN - #endif - #endif -#endif - -// Start Situation -#if defined(OLC_PLATFORM_GLUT) || defined(OLC_PLATFORM_EMSCRIPTEN) - #define PGE_USE_CUSTOM_START -#endif - -// Renderer -#if !defined(OLC_GFX_OPENGL10) && !defined(OLC_GFX_OPENGL33) && !defined(OLC_GFX_DIRECTX10) - #if !defined(OLC_GFX_CUSTOM_EX) - #if defined(OLC_PLATFORM_EMSCRIPTEN) - #define OLC_GFX_OPENGL33 - #else - #define OLC_GFX_OPENGL10 - #endif - #endif -#endif - -// Image loader -#if !defined(OLC_IMAGE_STB) && !defined(OLC_IMAGE_GDI) && !defined(OLC_IMAGE_LIBPNG) - #if !defined(OLC_IMAGE_CUSTOM_EX) - #if defined(_WIN32) - #define OLC_IMAGE_GDI - #endif - #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) - #define OLC_IMAGE_LIBPNG - #endif - #endif -#endif - - -// O------------------------------------------------------------------------------O -// | PLATFORM-SPECIFIC DEPENDENCIES | -// O------------------------------------------------------------------------------O -#if !defined(OLC_PGE_HEADLESS) -#if defined(OLC_PLATFORM_WINAPI) - #define _WINSOCKAPI_ // Thanks Cornchipss - #if !defined(VC_EXTRALEAN) - #define VC_EXTRALEAN - #endif - #if !defined(NOMINMAX) - #define NOMINMAX - #endif - - // In Code::Blocks - #if !defined(_WIN32_WINNT) - #ifdef HAVE_MSMF - #define _WIN32_WINNT 0x0600 // Windows Vista - #else - #define _WIN32_WINNT 0x0500 // Windows 2000 - #endif - #endif - - #include - #undef _WINSOCKAPI_ -#endif - -#if defined(OLC_PLATFORM_X11) - namespace X11 - { - #include - #include - } -#endif - -#if defined(OLC_PLATFORM_GLUT) - #if defined(__linux__) - #include - #include - #endif - #if defined(__APPLE__) - #include - #include - #include - #endif -#endif -#endif -#pragma endregion - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine INTERFACE DECLARATION | -// O------------------------------------------------------------------------------O -#pragma region pge_declaration -namespace olc -{ - class PixelGameEngine; - class Sprite; - - // Pixel Game Engine Advanced Configuration - 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 }; - - // O------------------------------------------------------------------------------O - // | olc::Pixel - Represents a 32-Bit RGBA colour | - // O------------------------------------------------------------------------------O - 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 olc::Pixel& p1, const olc::Pixel& p2, float t); - - - // O------------------------------------------------------------------------------O - // | USEFUL CONSTANTS | - // O------------------------------------------------------------------------------O - 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); - - // Thanks to scripticuk and others for updating the key maps - // NOTE: The GLUT platform will need updating, open to contributions ;) - 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; - }; - - // O------------------------------------------------------------------------------O - // | olc::HWButton - Represents the state of a hardware button (mouse/key/joy) | - // O------------------------------------------------------------------------------O - struct HWButton - { - bool bPressed = false; // Set once during the frame the event occurs - bool bReleased = false; // Set once during the frame the event occurs - bool bHeld = false; // Set true for all frames between pressed and released events - }; - - - - - // O------------------------------------------------------------------------------O - // | olc::vX2d - A generic 2D vector type | - // O------------------------------------------------------------------------------O -#if !defined(OLC_IGNORE_VEC2D) - template - 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() const { return { static_cast(this->x), static_cast(this->y) }; } - operator v2d_generic() const { return { static_cast(this->x), static_cast(this->y) }; } - operator v2d_generic() const { return { static_cast(this->x), static_cast(this->y) }; } - }; - - // Note: joshinils has some good suggestions here, but they are complicated to implement at this moment, - // however they will appear in a future version of PGE - template inline v2d_generic operator * (const float& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs * (float)rhs.x), (T)(lhs * (float)rhs.y)); } - template inline v2d_generic operator * (const double& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs * (double)rhs.x), (T)(lhs * (double)rhs.y)); } - template inline v2d_generic operator * (const int& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs * (int)rhs.x), (T)(lhs * (int)rhs.y)); } - template inline v2d_generic operator / (const float& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs / (float)rhs.x), (T)(lhs / (float)rhs.y)); } - template inline v2d_generic operator / (const double& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs / (double)rhs.x), (T)(lhs / (double)rhs.y)); } - template inline v2d_generic operator / (const int& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs / (int)rhs.x), (T)(lhs / (int)rhs.y)); } - - // To stop dandistine crying... - template inline bool operator < (const v2d_generic& lhs, const v2d_generic& rhs) - { return lhs.y < rhs.y || (lhs.y == rhs.y && lhs.x < rhs.x); } - template inline bool operator > (const v2d_generic& lhs, const v2d_generic& rhs) - { return lhs.y > rhs.y || (lhs.y == rhs.y && lhs.x > rhs.x); } - - typedef v2d_generic vi2d; - typedef v2d_generic vu2d; - typedef v2d_generic vf2d; - typedef v2d_generic vd2d; -#endif - - - - - - - // O------------------------------------------------------------------------------O - // | olc::ResourcePack - A virtual scrambled filesystem to pack your assets into | - // O------------------------------------------------------------------------------O - struct ResourceBuffer : public std::streambuf - { - ResourceBuffer(std::ifstream& ifs, uint32_t offset, uint32_t size); - std::vector 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 mapFiles; - std::ifstream baseFile; - std::vector scramble(const std::vector& data, const std::string& key); - std::string makeposix(const std::string& path); - }; - - - class ImageLoader - { - public: - ImageLoader() = default; - virtual ~ImageLoader() = default; - virtual olc::rcode LoadImageResource(olc::Sprite* spr, const std::string& sImageFile, olc::ResourcePack* pack) = 0; - virtual olc::rcode SaveImageResource(olc::Sprite* spr, const std::string& sImageFile) = 0; - }; - - - // O------------------------------------------------------------------------------O - // | olc::Sprite - An image represented by a 2D array of olc::Pixel | - // O------------------------------------------------------------------------------O - class Sprite - { - public: - Sprite(); - Sprite(const std::string& sImageFile, olc::ResourcePack* pack = nullptr); - Sprite(int32_t w, int32_t h); - Sprite(const olc::Sprite&) = delete; - ~Sprite(); - - public: - olc::rcode LoadFromFile(const std::string& sImageFile, olc::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(olc::Sprite::Mode mode = olc::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 olc::vi2d& a) const; - bool SetPixel(const olc::vi2d& a, Pixel p); - Pixel Sample(float x, float y) const; - Pixel SampleBL(float u, float v) const; - Pixel* GetData(); - olc::Sprite* Duplicate(); - olc::Sprite* Duplicate(const olc::vi2d& vPos, const olc::vi2d& vSize); - std::vector pColData; - Mode modeSample = Mode::NORMAL; - - static std::unique_ptr loader; - }; - - // O------------------------------------------------------------------------------O - // | olc::Decal - A GPU resident storage of an olc::Sprite | - // O------------------------------------------------------------------------------O - class Decal - { - public: - Decal(olc::Sprite* spr, bool filter = false, bool clamp = true); - Decal(const uint32_t nExistingTextureResource, olc::Sprite* spr); - virtual ~Decal(); - void Update(); - void UpdateSprite(); - - public: // But dont touch - int32_t id = -1; - olc::Sprite* sprite = nullptr; - olc::vf2d vUVScale = { 1.0f, 1.0f }; - }; - - enum class DecalMode - { - NORMAL, - ADDITIVE, - MULTIPLICATIVE, - STENCIL, - ILLUMINATE, - WIREFRAME, - MODEL3D, - }; - - enum class DecalStructure - { - LINE, - FAN, - STRIP, - LIST - }; - - // O------------------------------------------------------------------------------O - // | olc::Renderable - Convenience class to keep a sprite and decal together | - // O------------------------------------------------------------------------------O - class Renderable - { - public: - Renderable() = default; - Renderable(Renderable&& r) : pSprite(std::move(r.pSprite)), pDecal(std::move(r.pDecal)) {} - Renderable(const Renderable&) = delete; - olc::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); - olc::Decal* Decal() const; - olc::Sprite* Sprite() const; - - private: - std::unique_ptr pSprite = nullptr; - std::unique_ptr pDecal = nullptr; - }; - - - // O------------------------------------------------------------------------------O - // | Auxilliary components internal to engine | - // O------------------------------------------------------------------------------O - - struct DecalInstance - { - olc::Decal* decal = nullptr; - std::vector pos; - std::vector uv; - std::vector w; - std::vector tint; - olc::DecalMode mode = olc::DecalMode::NORMAL; - olc::DecalStructure structure = olc::DecalStructure::FAN; - uint32_t points = 0; - }; - - struct LayerDesc - { - olc::vf2d vOffset = { 0, 0 }; - olc::vf2d vScale = { 1, 1 }; - bool bShow = false; - bool bUpdate = false; - olc::Renderable pDrawTarget; - uint32_t nResID = 0; - std::vector vecDecalInstance; - olc::Pixel tint = olc::WHITE; - std::function funcHook = nullptr; - }; - - class Renderer - { - public: - virtual ~Renderer() = default; - virtual void PrepareDevice() = 0; - virtual olc::rcode CreateDevice(std::vector params, bool bFullScreen, bool bVSYNC) = 0; - virtual olc::rcode DestroyDevice() = 0; - virtual void DisplayFrame() = 0; - virtual void PrepareDrawing() = 0; - virtual void SetDecalMode(const olc::DecalMode& mode) = 0; - virtual void DrawLayerQuad(const olc::vf2d& offset, const olc::vf2d& scale, const olc::Pixel tint) = 0; - virtual void DrawDecal(const olc::DecalInstance& decal) = 0; - virtual uint32_t CreateTexture(const uint32_t width, const uint32_t height, const bool filtered = false, const bool clamp = true) = 0; - virtual void UpdateTexture(uint32_t id, olc::Sprite* spr) = 0; - virtual void ReadTexture(uint32_t id, olc::Sprite* spr) = 0; - virtual uint32_t DeleteTexture(const uint32_t id) = 0; - virtual void ApplyTexture(uint32_t id) = 0; - virtual void UpdateViewport(const olc::vi2d& pos, const olc::vi2d& size) = 0; - virtual void ClearBuffer(olc::Pixel p, bool bDepth) = 0; - static olc::PixelGameEngine* ptrPGE; - }; - - class Platform - { - public: - virtual ~Platform() = default; - virtual olc::rcode ApplicationStartUp() = 0; - virtual olc::rcode ApplicationCleanUp() = 0; - virtual olc::rcode ThreadStartUp() = 0; - virtual olc::rcode ThreadCleanUp() = 0; - virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) = 0; - virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) = 0; - virtual olc::rcode SetWindowTitle(const std::string& s) = 0; - virtual olc::rcode StartSystemEventLoop() = 0; - virtual olc::rcode HandleSystemEvent() = 0; - static olc::PixelGameEngine* ptrPGE; - }; - - class PGEX; - - // The Static Twins (plus one) - static std::unique_ptr renderer; - static std::unique_ptr platform; - static std::map mapKeys; - - // O------------------------------------------------------------------------------O - // | olc::PixelGameEngine - The main BASE class for your application | - // O------------------------------------------------------------------------------O - class PixelGameEngine - { - public: - PixelGameEngine(); - virtual ~PixelGameEngine(); - public: - olc::rcode Construct(int32_t screen_w, int32_t screen_h, int32_t pixel_w, int32_t pixel_h, - bool full_screen = false, bool vsync = false, bool cohesion = false); - olc::rcode Start(); - - public: // User Override Interfaces - // Called once on application startup, use to load your resources - virtual bool OnUserCreate(); - // Called every frame, and provides you with a time per frame value - virtual bool OnUserUpdate(float fElapsedTime); - // Called once on application termination, so you can be one clean coder - virtual bool OnUserDestroy(); - - // Called when a text entry is confirmed with "enter" key - virtual void OnTextEntryComplete(const std::string& sText); - // Called when a console command is executed - virtual bool OnConsoleCommand(const std::string& sCommand); - - public: // Hardware Interfaces - // Returns true if window is currently in focus - bool IsFocused() const; - // Get the state of a specific keyboard button - HWButton GetKey(Key k) const; - // Get the state of a specific mouse button - HWButton GetMouse(uint32_t b) const; - // Get Mouse X coordinate in "pixel" space - int32_t GetMouseX() const; - // Get Mouse Y coordinate in "pixel" space - int32_t GetMouseY() const; - // Get Mouse Wheel Delta - int32_t GetMouseWheel() const; - // Get the mouse in window space - const olc::vi2d& GetWindowMouse() const; - // Gets the mouse as a vector to keep Tarriest happy - const olc::vi2d& GetMousePos() const; - - static const std::map& GetKeyMap() { return mapKeys; } - - public: // Utility - // Returns the width of the screen in "pixels" - int32_t ScreenWidth() const; - // Returns the height of the screen in "pixels" - int32_t ScreenHeight() const; - // Returns the width of the currently selected drawing target in "pixels" - int32_t GetDrawTargetWidth() const; - // Returns the height of the currently selected drawing target in "pixels" - int32_t GetDrawTargetHeight() const; - // Returns the currently active draw target - olc::Sprite* GetDrawTarget() const; - // Resize the primary screen sprite - void SetScreenSize(int w, int h); - // Specify which Sprite should be the target of drawing functions, use nullptr - // to specify the primary screen - void SetDrawTarget(Sprite* target); - // Gets the current Frames Per Second - uint32_t GetFPS() const; - // Gets last update of elapsed time - float GetElapsedTime() const; - // Gets Actual Window size - const olc::vi2d& GetWindowSize() const; - // Gets pixel scale - const olc::vi2d& GetPixelSize() const; - // Gets actual pixel scale - const olc::vi2d& GetScreenPixelSize() const; - - public: // CONFIGURATION ROUTINES - // Layer targeting functions - void SetDrawTarget(uint8_t layer, bool bDirty = true); - void EnableLayer(uint8_t layer, bool b); - void SetLayerOffset(uint8_t layer, const olc::vf2d& offset); - void SetLayerOffset(uint8_t layer, float x, float y); - void SetLayerScale(uint8_t layer, const olc::vf2d& scale); - void SetLayerScale(uint8_t layer, float x, float y); - void SetLayerTint(uint8_t layer, const olc::Pixel& tint); - void SetLayerCustomRenderFunction(uint8_t layer, std::function f); - - std::vector& GetLayers(); - uint32_t CreateLayer(); - - // Change the pixel mode for different optimisations - // olc::Pixel::NORMAL = No transparency - // olc::Pixel::MASK = Transparent if alpha is < 255 - // olc::Pixel::ALPHA = Full transparency - void SetPixelMode(Pixel::Mode m); - Pixel::Mode GetPixelMode(); - // Use a custom blend function - void SetPixelMode(std::function pixelMode); - // Change the blend factor from between 0.0f to 1.0f; - void SetPixelBlend(float fBlend); - - - - public: // DRAWING ROUTINES - // Draws a single Pixel - virtual bool Draw(int32_t x, int32_t y, Pixel p = olc::WHITE); - bool Draw(const olc::vi2d& pos, Pixel p = olc::WHITE); - // Draws a line from (x1,y1) to (x2,y2) - void DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p = olc::WHITE, uint32_t pattern = 0xFFFFFFFF); - void DrawLine(const olc::vi2d& pos1, const olc::vi2d& pos2, Pixel p = olc::WHITE, uint32_t pattern = 0xFFFFFFFF); - // Draws a circle located at (x,y) with radius - void DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE, uint8_t mask = 0xFF); - void DrawCircle(const olc::vi2d& pos, int32_t radius, Pixel p = olc::WHITE, uint8_t mask = 0xFF); - // Fills a circle located at (x,y) with radius - void FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE); - void FillCircle(const olc::vi2d& pos, int32_t radius, Pixel p = olc::WHITE); - // Draws a rectangle at (x,y) to (x+w,y+h) - void DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p = olc::WHITE); - void DrawRect(const olc::vi2d& pos, const olc::vi2d& size, Pixel p = olc::WHITE); - // Fills a rectangle at (x,y) to (x+w,y+h) - void FillRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p = olc::WHITE); - void FillRect(const olc::vi2d& pos, const olc::vi2d& size, Pixel p = olc::WHITE); - // Draws a triangle between points (x1,y1), (x2,y2) and (x3,y3) - void DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE); - void DrawTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p = olc::WHITE); - // Flat fills a triangle between points (x1,y1), (x2,y2) and (x3,y3) - void FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE); - void FillTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p = olc::WHITE); - // Draws an entire sprite at location (x,y) - void DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); - void DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); - // Draws an area of a sprite at location (x,y), where the - // selected area is (ox,oy) to (ox+w,oy+h) - void DrawPartialSprite(int32_t x, int32_t y, Sprite* sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); - void DrawPartialSprite(const olc::vi2d& pos, Sprite* sprite, const olc::vi2d& sourcepos, const olc::vi2d& size, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); - // Draws a single line of text - traditional monospaced - void DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); - void DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); - olc::vi2d GetTextSize(const std::string& s); - // Draws a single line of text - non-monospaced - void DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); - void DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1); - olc::vi2d GetTextSizeProp(const std::string& s); - - // Decal Quad functions - void SetDecalMode(const olc::DecalMode& mode); - void SetDecalStructure(const olc::DecalStructure& structure); - // Draws a whole decal, with optional scale and tinting - void DrawDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE); - // Draws a region of a decal, with optional scale and tinting - void DrawPartialDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE); - void DrawPartialDecal(const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE); - // Draws fully user controlled 4 vertices, pos(pixels), uv(pixels), colours - void DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements = 4); - // Draws a decal with 4 arbitrary points, warping the texture to look "correct" - void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint = olc::WHITE); - void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint = olc::WHITE); - void DrawWarpedDecal(olc::Decal* decal, const std::array& pos, const olc::Pixel& tint = olc::WHITE); - // As above, but you can specify a region of a decal source sprite - void DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE); - void DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE); - void DrawPartialWarpedDecal(olc::Decal* decal, const std::array& pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE); - // Draws a decal rotated to specified angle, wit point of rotation offset - void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE); - void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE); - // Draws a multiline string as a decal, with tiniting and scaling - void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); - void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); - // Draws a single shaded filled rectangle as a decal - void FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE); - // Draws a corner shaded rectangle as a decal - void GradientFillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel colTL, const olc::Pixel colBL, const olc::Pixel colBR, const olc::Pixel colTR); - // Draws an arbitrary convex textured polygon using GPU - void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const olc::Pixel tint = olc::WHITE); - void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const olc::Pixel tint = olc::WHITE); - void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector& tint); - - // Draws a line in Decal Space - void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE); - void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); - void DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); - // Clears entire draw target to Pixel - void Clear(Pixel p); - // Clears the rendering back buffer - void ClearBuffer(Pixel p, bool bDepth = true); - // Returns the font image - olc::Sprite* GetFontSprite(); - - // Clip a line segment to visible area - bool ClipLineToScreen(olc::vi2d& in_p1, olc::vi2d& in_p2); - - // Dont allow PGE to mark layers as dirty, so pixel graphics don't update - void EnablePixelTransfer(const bool bEnable = true); - - // Command Console Routines - void ConsoleShow(const olc::Key &keyExit, bool bSuspendTime = true); - bool IsConsoleShowing() const; - void ConsoleClear(); - std::stringstream& ConsoleOut(); - void ConsoleCaptureStdOut(const bool bCapture); - - // Text Entry Routines - void TextEntryEnable(const bool bEnable, const std::string& sText = ""); - std::string TextEntryGetString() const; - int32_t TextEntryGetCursor() const; - bool IsTextEntryEnabled() const; - - - - private: - void UpdateTextEntry(); - void UpdateConsole(); - - public: - - // Experimental Lightweight 3D Routines ================ -#ifdef OLC_ENABLE_EXPERIMENTAL - // Set Manual View Matrix - void LW3D_View(const std::array& m); - // Set Manual World Matrix - void LW3D_World(const std::array& m); - // Set Manual Projection Matrix - void LW3D_Projection(const std::array& m); - - // Draws a vector of vertices, interprted as individual triangles - void LW3D_DrawTriangles(olc::Decal* decal, const std::vector>& pos, const std::vector& tex, const std::vector& col); - - void LW3D_ModelTranslate(const float x, const float y, const float z); - - // Camera convenience functions - void LW3D_SetCameraAtTarget(const float fEyeX, const float fEyeY, const float fEyeZ, - const float fTargetX, const float fTargetY, const float fTargetZ, - const float fUpX = 0.0f, const float fUpY = 1.0f, const float fUpZ = 0.0f); - void LW3D_SetCameraAlongDirection(const float fEyeX, const float fEyeY, const float fEyeZ, - const float fDirX, const float fDirY, const float fDirZ, - const float fUpX = 0.0f, const float fUpY = 1.0f, const float fUpZ = 0.0f); - - // 3D Rendering Flags - void LW3D_EnableDepthTest(const bool bEnableDepth); - void LW3D_EnableBackfaceCulling(const bool bEnableCull); -#endif - public: // Branding - std::string sAppName; - - private: // Inner mysterious workings - olc::Sprite* pDrawTarget = nullptr; - Pixel::Mode nPixelMode = Pixel::NORMAL; - float fBlendFactor = 1.0f; - olc::vi2d vScreenSize = { 256, 240 }; - olc::vf2d vInvScreenSize = { 1.0f / 256.0f, 1.0f / 240.0f }; - olc::vi2d vPixelSize = { 4, 4 }; - olc::vi2d vScreenPixelSize = { 4, 4 }; - olc::vi2d vMousePos = { 0, 0 }; - int32_t nMouseWheelDelta = 0; - olc::vi2d vMousePosCache = { 0, 0 }; - olc::vi2d vMouseWindowPos = { 0, 0 }; - int32_t nMouseWheelDeltaCache = 0; - olc::vi2d vWindowSize = { 0, 0 }; - olc::vi2d vViewPos = { 0, 0 }; - olc::vi2d vViewSize = { 0,0 }; - bool bFullScreen = false; - olc::vf2d vPixel = { 1.0f, 1.0f }; - bool bHasInputFocus = false; - bool bHasMouseFocus = false; - bool bEnableVSYNC = false; - float fFrameTimer = 1.0f; - float fLastElapsed = 0.0f; - int nFrameCount = 0; - bool bSuspendTextureTransfer = false; - Renderable fontRenderable; - std::vector vLayers; - uint8_t nTargetLayer = 0; - uint32_t nLastFPS = 0; - bool bPixelCohesion = false; - DecalMode nDecalMode = DecalMode::NORMAL; - DecalStructure nDecalStructure = DecalStructure::FAN; - std::function funcPixelMode; - std::chrono::time_point m_tp1, m_tp2; - std::vector vFontSpacing; - - // Command Console Specific - bool bConsoleShow = false; - bool bConsoleSuspendTime = false; - olc::Key keyConsoleExit = olc::Key::F1; - std::stringstream ssConsoleOutput; - std::streambuf* sbufOldCout = nullptr; - olc::vi2d vConsoleSize; - olc::vi2d vConsoleCursor = { 0,0 }; - olc::vf2d vConsoleCharacterScale = { 1.0f, 2.0f }; - std::vector sConsoleLines; - std::list sCommandHistory; - std::list::iterator sCommandHistoryIt; - - // Text Entry Specific - bool bTextEntryEnable = false; - std::string sTextEntryString = ""; - int32_t nTextEntryCursor = 0; - std::vector> vKeyboardMap; - - - - // State of keyboard - bool pKeyNewState[256] = { 0 }; - bool pKeyOldState[256] = { 0 }; - HWButton pKeyboardState[256] = { 0 }; - - // State of mouse - bool pMouseNewState[nMouseButtons] = { 0 }; - bool pMouseOldState[nMouseButtons] = { 0 }; - HWButton pMouseState[nMouseButtons] = { 0 }; - - // The main engine thread - void EngineThread(); - - - // If anything sets this flag to false, the engine - // "should" shut down gracefully - static std::atomic bAtomActive; - - public: - // "Break In" Functions - void olc_UpdateMouse(int32_t x, int32_t y); - void olc_UpdateMouseWheel(int32_t delta); - void olc_UpdateWindowSize(int32_t x, int32_t y); - void olc_UpdateViewport(); - void olc_ConstructFontSheet(); - void olc_CoreUpdate(); - void olc_PrepareEngine(); - void olc_UpdateMouseState(int32_t button, bool state); - void olc_UpdateKeyState(int32_t key, bool state); - void olc_UpdateMouseFocus(bool state); - void olc_UpdateKeyFocus(bool state); - void olc_Terminate(); - void olc_Reanimate(); - bool olc_IsRunning(); - - // At the very end of this file, chooses which - // components to compile - virtual void olc_ConfigureSystem(); - - // NOTE: Items Here are to be deprecated, I have left them in for now - // in case you are using them, but they will be removed. - // olc::vf2d vSubPixelOffset = { 0.0f, 0.0f }; - - public: // PGEX Stuff - friend class PGEX; - void pgex_Register(olc::PGEX* pgex); - - private: - std::vector vExtensions; - }; - - - - // O------------------------------------------------------------------------------O - // | PGE EXTENSION BASE CLASS - Permits access to PGE functions from extension | - // O------------------------------------------------------------------------------O - class PGEX - { - friend class olc::PixelGameEngine; - public: - PGEX(bool bHook = false); - - protected: - virtual void OnBeforeUserCreate(); - virtual void OnAfterUserCreate(); - virtual bool OnBeforeUserUpdate(float &fElapsedTime); - virtual void OnAfterUserUpdate(float fElapsedTime); - - protected: - static PixelGameEngine* pge; - }; -} - -#pragma endregion - -#endif // OLC_PGE_DEF - - -// O------------------------------------------------------------------------------O -// | START OF OLC_PGE_APPLICATION | -// O------------------------------------------------------------------------------O -#ifdef OLC_PGE_APPLICATION -#undef OLC_PGE_APPLICATION - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine INTERFACE IMPLEMENTATION (CORE) | -// | Note: The core implementation is platform independent | -// O------------------------------------------------------------------------------O -#pragma region pge_implementation -namespace olc -{ - // O------------------------------------------------------------------------------O - // | olc::Pixel IMPLEMENTATION | - // O------------------------------------------------------------------------------O - Pixel::Pixel() - { r = 0; g = 0; b = 0; a = nDefaultAlpha; } - - Pixel::Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) - { n = red | (green << 8) | (blue << 16) | (alpha << 24); } // Thanks jarekpelczar - - Pixel::Pixel(uint32_t p) - { n = p; } - - bool Pixel::operator==(const Pixel& p) const - { return n == p.n; } - - bool Pixel::operator!=(const Pixel& p) const - { return n != p.n; } - - Pixel Pixel::operator * (const float i) const - { - float fR = std::min(255.0f, std::max(0.0f, float(r) * i)); - float fG = std::min(255.0f, std::max(0.0f, float(g) * i)); - float fB = std::min(255.0f, std::max(0.0f, float(b) * i)); - return Pixel(uint8_t(fR), uint8_t(fG), uint8_t(fB), a); - } - - Pixel Pixel::operator / (const float i) const - { - float fR = std::min(255.0f, std::max(0.0f, float(r) / i)); - float fG = std::min(255.0f, std::max(0.0f, float(g) / i)); - float fB = std::min(255.0f, std::max(0.0f, float(b) / i)); - return Pixel(uint8_t(fR), uint8_t(fG), uint8_t(fB), a); - } - - Pixel& Pixel::operator *=(const float i) - { - this->r = uint8_t(std::min(255.0f, std::max(0.0f, float(r) * i))); - this->g = uint8_t(std::min(255.0f, std::max(0.0f, float(g) * i))); - this->b = uint8_t(std::min(255.0f, std::max(0.0f, float(b) * i))); - return *this; - } - - Pixel& Pixel::operator /=(const float i) - { - this->r = uint8_t(std::min(255.0f, std::max(0.0f, float(r) / i))); - this->g = uint8_t(std::min(255.0f, std::max(0.0f, float(g) / i))); - this->b = uint8_t(std::min(255.0f, std::max(0.0f, float(b) / i))); - return *this; - } - - Pixel Pixel::operator + (const Pixel& p) const - { - uint8_t nR = uint8_t(std::min(255, std::max(0, int(r) + int(p.r)))); - uint8_t nG = uint8_t(std::min(255, std::max(0, int(g) + int(p.g)))); - uint8_t nB = uint8_t(std::min(255, std::max(0, int(b) + int(p.b)))); - return Pixel(nR, nG, nB, a); - } - - Pixel Pixel::operator - (const Pixel& p) const - { - uint8_t nR = uint8_t(std::min(255, std::max(0, int(r) - int(p.r)))); - uint8_t nG = uint8_t(std::min(255, std::max(0, int(g) - int(p.g)))); - uint8_t nB = uint8_t(std::min(255, std::max(0, int(b) - int(p.b)))); - return Pixel(nR, nG, nB, a); - } - - Pixel& Pixel::operator += (const Pixel& p) - { - this->r = uint8_t(std::min(255, std::max(0, int(r) + int(p.r)))); - this->g = uint8_t(std::min(255, std::max(0, int(g) + int(p.g)))); - this->b = uint8_t(std::min(255, std::max(0, int(b) + int(p.b)))); - return *this; - } - - Pixel& Pixel::operator -= (const Pixel& p) // Thanks Au Lit - { - this->r = uint8_t(std::min(255, std::max(0, int(r) - int(p.r)))); - this->g = uint8_t(std::min(255, std::max(0, int(g) - int(p.g)))); - this->b = uint8_t(std::min(255, std::max(0, int(b) - int(p.b)))); - return *this; - } - - Pixel Pixel::inv() const - { - uint8_t nR = uint8_t(std::min(255, std::max(0, 255 - int(r)))); - uint8_t nG = uint8_t(std::min(255, std::max(0, 255 - int(g)))); - uint8_t nB = uint8_t(std::min(255, std::max(0, 255 - int(b)))); - return Pixel(nR, nG, nB, a); - } - - Pixel PixelF(float red, float green, float blue, float alpha) - { return Pixel(uint8_t(red * 255.0f), uint8_t(green * 255.0f), uint8_t(blue * 255.0f), uint8_t(alpha * 255.0f)); } - - Pixel PixelLerp(const olc::Pixel& p1, const olc::Pixel& p2, float t) - { return (p2 * t) + p1 * (1.0f - t); } - - // O------------------------------------------------------------------------------O - // | olc::Sprite IMPLEMENTATION | - // O------------------------------------------------------------------------------O - Sprite::Sprite() - { width = 0; height = 0; } - - Sprite::Sprite(const std::string& sImageFile, olc::ResourcePack* pack) - { LoadFromFile(sImageFile, pack); } - - Sprite::Sprite(int32_t w, int32_t h) - { - width = w; height = h; - pColData.resize(width * height); - pColData.resize(width * height, nDefaultPixel); - } - - Sprite::~Sprite() - { pColData.clear(); } - - void Sprite::SetSampleMode(olc::Sprite::Mode mode) - { modeSample = mode; } - - Pixel Sprite::GetPixel(const olc::vi2d& a) const - { return GetPixel(a.x, a.y); } - - bool Sprite::SetPixel(const olc::vi2d& a, Pixel p) - { return SetPixel(a.x, a.y, p); } - - Pixel Sprite::GetPixel(int32_t x, int32_t y) const - { - if (modeSample == olc::Sprite::Mode::NORMAL) - { - if (x >= 0 && x < width && y >= 0 && y < height) - return pColData[y * width + x]; - else - return Pixel(0, 0, 0, 0); - } - else - { - if (modeSample == olc::Sprite::Mode::PERIODIC) - return pColData[abs(y % height) * width + abs(x % width)]; - else - return pColData[std::max(0, std::min(y, height-1)) * width + std::max(0, std::min(x, width-1))]; - } - } - - bool Sprite::SetPixel(int32_t x, int32_t y, Pixel p) - { - if (x >= 0 && x < width && y >= 0 && y < height) - { - pColData[y * width + x] = p; - return true; - } - else - return false; - } - - Pixel Sprite::Sample(float x, float y) const - { - int32_t sx = std::min((int32_t)((x * (float)width)), width - 1); - int32_t sy = std::min((int32_t)((y * (float)height)), height - 1); - return GetPixel(sx, sy); - } - - Pixel Sprite::SampleBL(float u, float v) const - { - u = u * width - 0.5f; - v = v * height - 0.5f; - int x = (int)floor(u); // cast to int rounds toward zero, not downward - int y = (int)floor(v); // Thanks @joshinils - float u_ratio = u - x; - float v_ratio = v - y; - float u_opposite = 1 - u_ratio; - float v_opposite = 1 - v_ratio; - - olc::Pixel p1 = GetPixel(std::max(x, 0), std::max(y, 0)); - olc::Pixel p2 = GetPixel(std::min(x + 1, (int)width - 1), std::max(y, 0)); - olc::Pixel p3 = GetPixel(std::max(x, 0), std::min(y + 1, (int)height - 1)); - olc::Pixel p4 = GetPixel(std::min(x + 1, (int)width - 1), std::min(y + 1, (int)height - 1)); - - return olc::Pixel( - (uint8_t)((p1.r * u_opposite + p2.r * u_ratio) * v_opposite + (p3.r * u_opposite + p4.r * u_ratio) * v_ratio), - (uint8_t)((p1.g * u_opposite + p2.g * u_ratio) * v_opposite + (p3.g * u_opposite + p4.g * u_ratio) * v_ratio), - (uint8_t)((p1.b * u_opposite + p2.b * u_ratio) * v_opposite + (p3.b * u_opposite + p4.b * u_ratio) * v_ratio)); - } - - Pixel* Sprite::GetData() - { return pColData.data(); } - - - olc::rcode Sprite::LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack) - { - UNUSED(pack); - return loader->LoadImageResource(this, sImageFile, pack); - } - - olc::Sprite* Sprite::Duplicate() - { - olc::Sprite* spr = new olc::Sprite(width, height); - std::memcpy(spr->GetData(), GetData(), width * height * sizeof(olc::Pixel)); - spr->modeSample = modeSample; - return spr; - } - - olc::Sprite* Sprite::Duplicate(const olc::vi2d& vPos, const olc::vi2d& vSize) - { - olc::Sprite* spr = new olc::Sprite(vSize.x, vSize.y); - for (int y = 0; y < vSize.y; y++) - for (int x = 0; x < vSize.x; x++) - spr->SetPixel(x, y, GetPixel(vPos.x + x, vPos.y + y)); - return spr; - } - - // O------------------------------------------------------------------------------O - // | olc::Decal IMPLEMENTATION | - // O------------------------------------------------------------------------------O - Decal::Decal(olc::Sprite* spr, bool filter, bool clamp) - { - id = -1; - if (spr == nullptr) return; - sprite = spr; - id = renderer->CreateTexture(sprite->width, sprite->height, filter, clamp); - Update(); - } - - Decal::Decal(const uint32_t nExistingTextureResource, olc::Sprite* spr) - { - if (spr == nullptr) return; - id = nExistingTextureResource; - } - - void Decal::Update() - { - if (sprite == nullptr) return; - vUVScale = { 1.0f / float(sprite->width), 1.0f / float(sprite->height) }; - renderer->ApplyTexture(id); - renderer->UpdateTexture(id, sprite); - } - - void Decal::UpdateSprite() - { - if (sprite == nullptr) return; - renderer->ApplyTexture(id); - renderer->ReadTexture(id, sprite); - } - - Decal::~Decal() - { - if (id != -1) - { - renderer->DeleteTexture(id); - id = -1; - } - } - - void Renderable::Create(uint32_t width, uint32_t height, bool filter, bool clamp) - { - pSprite = std::make_unique(width, height); - pDecal = std::make_unique(pSprite.get(), filter, clamp); - } - - olc::rcode Renderable::Load(const std::string& sFile, ResourcePack* pack, bool filter, bool clamp) - { - pSprite = std::make_unique(); - if (pSprite->LoadFromFile(sFile, pack) == olc::rcode::OK) - { - pDecal = std::make_unique(pSprite.get(), filter, clamp); - return olc::rcode::OK; - } - else - { - pSprite.release(); - pSprite = nullptr; - return olc::rcode::NO_FILE; - } - } - - olc::Decal* Renderable::Decal() const - { return pDecal.get(); } - - olc::Sprite* Renderable::Sprite() const - { return pSprite.get(); } - - // O------------------------------------------------------------------------------O - // | olc::ResourcePack IMPLEMENTATION | - // O------------------------------------------------------------------------------O - - - //============================================================= - // Resource Packs - Allows you to store files in one large - // scrambled file - Thanks MaGetzUb for debugging a null char in std::stringstream bug - ResourceBuffer::ResourceBuffer(std::ifstream& ifs, uint32_t offset, uint32_t size) - { - vMemory.resize(size); - ifs.seekg(offset); ifs.read(vMemory.data(), vMemory.size()); - setg(vMemory.data(), vMemory.data(), vMemory.data() + size); - } - - ResourcePack::ResourcePack() { } - ResourcePack::~ResourcePack() { baseFile.close(); } - - bool ResourcePack::AddFile(const std::string& sFile) - { - const std::string file = makeposix(sFile); - - if (_gfs::exists(file)) - { - sResourceFile e; - e.nSize = (uint32_t)_gfs::file_size(file); - e.nOffset = 0; // Unknown at this stage - mapFiles[file] = e; - return true; - } - return false; - } - - bool ResourcePack::LoadPack(const std::string& sFile, const std::string& sKey) - { - // Open the resource file - baseFile.open(sFile, std::ifstream::binary); - if (!baseFile.is_open()) return false; - - // 1) Read Scrambled index - uint32_t nIndexSize = 0; - baseFile.read((char*)&nIndexSize, sizeof(uint32_t)); - - std::vector buffer(nIndexSize); - for (uint32_t j = 0; j < nIndexSize; j++) - buffer[j] = baseFile.get(); - - std::vector decoded = scramble(buffer, sKey); - size_t pos = 0; - auto read = [&decoded, &pos](char* dst, size_t size) { - memcpy((void*)dst, (const void*)(decoded.data() + pos), size); - pos += size; - }; - - auto get = [&read]() -> int { char c; read(&c, 1); return c; }; - - // 2) Read Map - uint32_t nMapEntries = 0; - read((char*)&nMapEntries, sizeof(uint32_t)); - for (uint32_t i = 0; i < nMapEntries; i++) - { - uint32_t nFilePathSize = 0; - read((char*)&nFilePathSize, sizeof(uint32_t)); - - std::string sFileName(nFilePathSize, ' '); - for (uint32_t j = 0; j < nFilePathSize; j++) - sFileName[j] = get(); - - sResourceFile e; - read((char*)&e.nSize, sizeof(uint32_t)); - read((char*)&e.nOffset, sizeof(uint32_t)); - mapFiles[sFileName] = e; - } - - // Don't close base file! we will provide a stream - // pointer when the file is requested - return true; - } - - bool ResourcePack::SavePack(const std::string& sFile, const std::string& sKey) - { - // Create/Overwrite the resource file - std::ofstream ofs(sFile, std::ofstream::binary); - if (!ofs.is_open()) return false; - - // Iterate through map - uint32_t nIndexSize = 0; // Unknown for now - ofs.write((char*)&nIndexSize, sizeof(uint32_t)); - uint32_t nMapSize = uint32_t(mapFiles.size()); - ofs.write((char*)&nMapSize, sizeof(uint32_t)); - for (auto& e : mapFiles) - { - // Write the path of the file - size_t nPathSize = e.first.size(); - ofs.write((char*)&nPathSize, sizeof(uint32_t)); - ofs.write(e.first.c_str(), nPathSize); - - // Write the file entry properties - ofs.write((char*)&e.second.nSize, sizeof(uint32_t)); - ofs.write((char*)&e.second.nOffset, sizeof(uint32_t)); - } - - // 2) Write the individual Data - std::streampos offset = ofs.tellp(); - nIndexSize = (uint32_t)offset; - for (auto& e : mapFiles) - { - // Store beginning of file offset within resource pack file - e.second.nOffset = (uint32_t)offset; - - // Load the file to be added - std::vector vBuffer(e.second.nSize); - std::ifstream i(e.first, std::ifstream::binary); - i.read((char*)vBuffer.data(), e.second.nSize); - i.close(); - - // Write the loaded file into resource pack file - ofs.write((char*)vBuffer.data(), e.second.nSize); - offset += e.second.nSize; - } - - // 3) Scramble Index - std::vector stream; - auto write = [&stream](const char* data, size_t size) { - size_t sizeNow = stream.size(); - stream.resize(sizeNow + size); - memcpy(stream.data() + sizeNow, data, size); - }; - - // Iterate through map - write((char*)&nMapSize, sizeof(uint32_t)); - for (auto& e : mapFiles) - { - // Write the path of the file - size_t nPathSize = e.first.size(); - write((char*)&nPathSize, sizeof(uint32_t)); - write(e.first.c_str(), nPathSize); - - // Write the file entry properties - write((char*)&e.second.nSize, sizeof(uint32_t)); - write((char*)&e.second.nOffset, sizeof(uint32_t)); - } - std::vector sIndexString = scramble(stream, sKey); - uint32_t nIndexStringLen = uint32_t(sIndexString.size()); - // 4) Rewrite Map (it has been updated with offsets now) - // at start of file - ofs.seekp(0, std::ios::beg); - ofs.write((char*)&nIndexStringLen, sizeof(uint32_t)); - ofs.write(sIndexString.data(), nIndexStringLen); - ofs.close(); - return true; - } - - ResourceBuffer ResourcePack::GetFileBuffer(const std::string& sFile) - { return ResourceBuffer(baseFile, mapFiles[sFile].nOffset, mapFiles[sFile].nSize); } - - bool ResourcePack::Loaded() - { return baseFile.is_open(); } - - std::vector ResourcePack::scramble(const std::vector& data, const std::string& key) - { - if (key.empty()) return data; - std::vector o; - size_t c = 0; - for (auto s : data) o.push_back(s ^ key[(c++) % key.size()]); - return o; - }; - - std::string ResourcePack::makeposix(const std::string& path) - { - std::string o; - for (auto s : path) o += std::string(1, s == '\\' ? '/' : s); - return o; - }; - - // O------------------------------------------------------------------------------O - // | olc::PixelGameEngine IMPLEMENTATION | - // O------------------------------------------------------------------------------O - PixelGameEngine::PixelGameEngine() - { - sAppName = "Undefined"; - olc::PGEX::pge = this; - - // Bring in relevant Platform & Rendering systems depending - // on compiler parameters - olc_ConfigureSystem(); - } - - PixelGameEngine::~PixelGameEngine() - {} - - - olc::rcode PixelGameEngine::Construct(int32_t screen_w, int32_t screen_h, int32_t pixel_w, int32_t pixel_h, bool full_screen, bool vsync, bool cohesion) - { - bPixelCohesion = cohesion; - vScreenSize = { screen_w, screen_h }; - vInvScreenSize = { 1.0f / float(screen_w), 1.0f / float(screen_h) }; - vPixelSize = { pixel_w, pixel_h }; - vWindowSize = vScreenSize * vPixelSize; - bFullScreen = full_screen; - bEnableVSYNC = vsync; - vPixel = 2.0f / vScreenSize; - - if (vPixelSize.x <= 0 || vPixelSize.y <= 0 || vScreenSize.x <= 0 || vScreenSize.y <= 0) - return olc::FAIL; - return olc::OK; - } - - - void PixelGameEngine::SetScreenSize(int w, int h) - { - vScreenSize = { w, h }; - vInvScreenSize = { 1.0f / float(w), 1.0f / float(h) }; - for (auto& layer : vLayers) - { - layer.pDrawTarget.Create(vScreenSize.x, vScreenSize.y); - layer.bUpdate = true; - } - SetDrawTarget(nullptr); - renderer->ClearBuffer(olc::BLACK, true); - renderer->DisplayFrame(); - renderer->ClearBuffer(olc::BLACK, true); - renderer->UpdateViewport(vViewPos, vViewSize); - } - -#if !defined(PGE_USE_CUSTOM_START) - olc::rcode PixelGameEngine::Start() - { - if (platform->ApplicationStartUp() != olc::OK) return olc::FAIL; - - // Construct the window - if (platform->CreateWindowPane({ 30,30 }, vWindowSize, bFullScreen) != olc::OK) return olc::FAIL; - olc_UpdateWindowSize(vWindowSize.x, vWindowSize.y); - - // Start the thread - bAtomActive = true; - std::thread t = std::thread(&PixelGameEngine::EngineThread, this); - - // Some implementations may form an event loop here - platform->StartSystemEventLoop(); - - // Wait for thread to be exited - t.join(); - - if (platform->ApplicationCleanUp() != olc::OK) return olc::FAIL; - - return olc::OK; - } -#endif - - void PixelGameEngine::SetDrawTarget(Sprite* target) - { - if (target) - { - pDrawTarget = target; - } - else - { - nTargetLayer = 0; - pDrawTarget = vLayers[0].pDrawTarget.Sprite(); - } - } - - void PixelGameEngine::SetDrawTarget(uint8_t layer, bool bDirty) - { - if (layer < vLayers.size()) - { - pDrawTarget = vLayers[layer].pDrawTarget.Sprite(); - vLayers[layer].bUpdate = bDirty; - nTargetLayer = layer; - } - } - - void PixelGameEngine::EnableLayer(uint8_t layer, bool b) - { if (layer < vLayers.size()) vLayers[layer].bShow = b; } - - void PixelGameEngine::SetLayerOffset(uint8_t layer, const olc::vf2d& offset) - { SetLayerOffset(layer, offset.x, offset.y); } - - void PixelGameEngine::SetLayerOffset(uint8_t layer, float x, float y) - { if (layer < vLayers.size()) vLayers[layer].vOffset = { x, y }; } - - void PixelGameEngine::SetLayerScale(uint8_t layer, const olc::vf2d& scale) - { SetLayerScale(layer, scale.x, scale.y); } - - void PixelGameEngine::SetLayerScale(uint8_t layer, float x, float y) - { if (layer < vLayers.size()) vLayers[layer].vScale = { x, y }; } - - void PixelGameEngine::SetLayerTint(uint8_t layer, const olc::Pixel& tint) - { if (layer < vLayers.size()) vLayers[layer].tint = tint; } - - void PixelGameEngine::SetLayerCustomRenderFunction(uint8_t layer, std::function f) - { if (layer < vLayers.size()) vLayers[layer].funcHook = f; } - - std::vector& PixelGameEngine::GetLayers() - { return vLayers; } - - uint32_t PixelGameEngine::CreateLayer() - { - LayerDesc ld; - ld.pDrawTarget.Create(vScreenSize.x, vScreenSize.y); - vLayers.push_back(std::move(ld)); - return uint32_t(vLayers.size()) - 1; - } - - Sprite* PixelGameEngine::GetDrawTarget() const - { return pDrawTarget; } - - int32_t PixelGameEngine::GetDrawTargetWidth() const - { - if (pDrawTarget) - return pDrawTarget->width; - else - return 0; - } - - int32_t PixelGameEngine::GetDrawTargetHeight() const - { - if (pDrawTarget) - return pDrawTarget->height; - else - return 0; - } - - uint32_t PixelGameEngine::GetFPS() const - { return nLastFPS; } - - bool PixelGameEngine::IsFocused() const - { return bHasInputFocus; } - - HWButton PixelGameEngine::GetKey(Key k) const - { return pKeyboardState[k]; } - - HWButton PixelGameEngine::GetMouse(uint32_t b) const - { return pMouseState[b]; } - - int32_t PixelGameEngine::GetMouseX() const - { return vMousePos.x; } - - int32_t PixelGameEngine::GetMouseY() const - { return vMousePos.y; } - - const olc::vi2d& PixelGameEngine::GetMousePos() const - { return vMousePos; } - - int32_t PixelGameEngine::GetMouseWheel() const - { return nMouseWheelDelta; } - - int32_t PixelGameEngine::ScreenWidth() const - { return vScreenSize.x; } - - int32_t PixelGameEngine::ScreenHeight() const - { return vScreenSize.y; } - - float PixelGameEngine::GetElapsedTime() const - { return fLastElapsed; } - - const olc::vi2d& PixelGameEngine::GetWindowSize() const - { return vWindowSize; } - - const olc::vi2d& PixelGameEngine::GetPixelSize() const - { return vPixelSize; } - - const olc::vi2d& PixelGameEngine::GetScreenPixelSize() const - { return vScreenPixelSize; } - - const olc::vi2d& PixelGameEngine::GetWindowMouse() const - { return vMouseWindowPos; } - - bool PixelGameEngine::Draw(const olc::vi2d& pos, Pixel p) - { return Draw(pos.x, pos.y, p); } - - // This is it, the critical function that plots a pixel - bool PixelGameEngine::Draw(int32_t x, int32_t y, Pixel p) - { - if (!pDrawTarget) return false; - - if (nPixelMode == Pixel::NORMAL) - { - return pDrawTarget->SetPixel(x, y, p); - } - - if (nPixelMode == Pixel::MASK) - { - if (p.a == 255) - return pDrawTarget->SetPixel(x, y, p); - } - - if (nPixelMode == Pixel::ALPHA) - { - Pixel d = pDrawTarget->GetPixel(x, y); - float a = (float)(p.a / 255.0f) * fBlendFactor; - float c = 1.0f - a; - float r = a * (float)p.r + c * (float)d.r; - float g = a * (float)p.g + c * (float)d.g; - float b = a * (float)p.b + c * (float)d.b; - return pDrawTarget->SetPixel(x, y, Pixel((uint8_t)r, (uint8_t)g, (uint8_t)b/*, (uint8_t)(p.a * fBlendFactor)*/)); - } - - if (nPixelMode == Pixel::CUSTOM) - { - return pDrawTarget->SetPixel(x, y, funcPixelMode(x, y, p, pDrawTarget->GetPixel(x, y))); - } - - return false; - } - - - void PixelGameEngine::DrawLine(const olc::vi2d& pos1, const olc::vi2d& pos2, Pixel p, uint32_t pattern) - { DrawLine(pos1.x, pos1.y, pos2.x, pos2.y, p, pattern); } - - void PixelGameEngine::DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p, uint32_t pattern) - { - int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i; - dx = x2 - x1; dy = y2 - y1; - - auto rol = [&](void) { pattern = (pattern << 1) | (pattern >> 31); return pattern & 1; }; - - olc::vi2d p1(x1, y1), p2(x2, y2); - //if (!ClipLineToScreen(p1, p2)) - // return; - x1 = p1.x; y1 = p1.y; - x2 = p2.x; y2 = p2.y; - - // straight lines idea by gurkanctn - if (dx == 0) // Line is vertical - { - if (y2 < y1) std::swap(y1, y2); - for (y = y1; y <= y2; y++) if (rol()) Draw(x1, y, p); - return; - } - - if (dy == 0) // Line is horizontal - { - if (x2 < x1) std::swap(x1, x2); - for (x = x1; x <= x2; x++) if (rol()) Draw(x, y1, p); - return; - } - - // Line is Funk-aye - dx1 = abs(dx); dy1 = abs(dy); - px = 2 * dy1 - dx1; py = 2 * dx1 - dy1; - if (dy1 <= dx1) - { - if (dx >= 0) - { - x = x1; y = y1; xe = x2; - } - else - { - x = x2; y = y2; xe = x1; - } - - if (rol()) Draw(x, y, p); - - for (i = 0; x < xe; i++) - { - x = x + 1; - if (px < 0) - px = px + 2 * dy1; - else - { - if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) y = y + 1; else y = y - 1; - px = px + 2 * (dy1 - dx1); - } - if (rol()) Draw(x, y, p); - } - } - else - { - if (dy >= 0) - { - x = x1; y = y1; ye = y2; - } - else - { - x = x2; y = y2; ye = y1; - } - - if (rol()) Draw(x, y, p); - - for (i = 0; y < ye; i++) - { - y = y + 1; - if (py <= 0) - py = py + 2 * dx1; - else - { - if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) x = x + 1; else x = x - 1; - py = py + 2 * (dx1 - dy1); - } - if (rol()) Draw(x, y, p); - } - } - } - - void PixelGameEngine::DrawCircle(const olc::vi2d& pos, int32_t radius, Pixel p, uint8_t mask) - { DrawCircle(pos.x, pos.y, radius, p, mask); } - - void PixelGameEngine::DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p, uint8_t mask) - { // Thanks to IanM-Matrix1 #PR121 - if (radius < 0 || x < -radius || y < -radius || x - GetDrawTargetWidth() > radius || y - GetDrawTargetHeight() > radius) - return; - - if (radius > 0) - { - int x0 = 0; - int y0 = radius; - int d = 3 - 2 * radius; - - while (y0 >= x0) // only formulate 1/8 of circle - { - // Draw even octants - if (mask & 0x01) Draw(x + x0, y - y0, p);// Q6 - upper right right - if (mask & 0x04) Draw(x + y0, y + x0, p);// Q4 - lower lower right - if (mask & 0x10) Draw(x - x0, y + y0, p);// Q2 - lower left left - if (mask & 0x40) Draw(x - y0, y - x0, p);// Q0 - upper upper left - if (x0 != 0 && x0 != y0) - { - if (mask & 0x02) Draw(x + y0, y - x0, p);// Q7 - upper upper right - if (mask & 0x08) Draw(x + x0, y + y0, p);// Q5 - lower right right - if (mask & 0x20) Draw(x - y0, y + x0, p);// Q3 - lower lower left - if (mask & 0x80) Draw(x - x0, y - y0, p);// Q1 - upper left left - } - - if (d < 0) - d += 4 * x0++ + 6; - else - d += 4 * (x0++ - y0--) + 10; - } - } - else - Draw(x, y, p); - } - - void PixelGameEngine::FillCircle(const olc::vi2d& pos, int32_t radius, Pixel p) - { FillCircle(pos.x, pos.y, radius, p); } - - void PixelGameEngine::FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p) - { // Thanks to IanM-Matrix1 #PR121 - if (radius < 0 || x < -radius || y < -radius || x - GetDrawTargetWidth() > radius || y - GetDrawTargetHeight() > radius) - return; - - if (radius > 0) - { - int x0 = 0; - int y0 = radius; - int d = 3 - 2 * radius; - - auto drawline = [&](int sx, int ex, int y) - { - for (int x = sx; x <= ex; x++) - Draw(x, y, p); - }; - - while (y0 >= x0) - { - drawline(x - y0, x + y0, y - x0); - if (x0 > 0) drawline(x - y0, x + y0, y + x0); - - if (d < 0) - d += 4 * x0++ + 6; - else - { - if (x0 != y0) - { - drawline(x - x0, x + x0, y - y0); - drawline(x - x0, x + x0, y + y0); - } - d += 4 * (x0++ - y0--) + 10; - } - } - } - else - Draw(x, y, p); - } - - void PixelGameEngine::DrawRect(const olc::vi2d& pos, const olc::vi2d& size, Pixel p) - { DrawRect(pos.x, pos.y, size.x, size.y, p); } - - void PixelGameEngine::DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p) - { - DrawLine(x, y, x + w, y, p); - DrawLine(x + w, y, x + w, y + h, p); - DrawLine(x + w, y + h, x, y + h, p); - DrawLine(x, y + h, x, y, p); - } - - void PixelGameEngine::Clear(Pixel p) - { - int pixels = GetDrawTargetWidth() * GetDrawTargetHeight(); - Pixel* m = GetDrawTarget()->GetData(); - for (int i = 0; i < pixels; i++) m[i] = p; - } - - void PixelGameEngine::ClearBuffer(Pixel p, bool bDepth) - { renderer->ClearBuffer(p, bDepth); } - - olc::Sprite* PixelGameEngine::GetFontSprite() - { return fontRenderable.Sprite(); } - - bool PixelGameEngine::ClipLineToScreen(olc::vi2d& in_p1, olc::vi2d& in_p2) - { - // https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm - static constexpr int SEG_I = 0b0000, SEG_L = 0b0001, SEG_R = 0b0010, SEG_B = 0b0100, SEG_T = 0b1000; - auto Segment = [&vScreenSize = vScreenSize](const olc::vi2d& v) - { - int i = SEG_I; - if (v.x < 0) i |= SEG_L; else if (v.x > vScreenSize.x) i |= SEG_R; - if (v.y < 0) i |= SEG_B; else if (v.y > vScreenSize.y) i |= SEG_T; - return i; - }; - - int s1 = Segment(in_p1), s2 = Segment(in_p2); - - while (true) - { - if (!(s1 | s2)) return true; - else if (s1 & s2) return false; - else - { - int s3 = s2 > s1 ? s2 : s1; - olc::vi2d n; - if (s3 & SEG_T) { n.x = in_p1.x + (in_p2.x - in_p1.x) * (vScreenSize.y - in_p1.y) / (in_p2.y - in_p1.y); n.y = vScreenSize.y; } - else if (s3 & SEG_B) { n.x = in_p1.x + (in_p2.x - in_p1.x) * (0 - in_p1.y) / (in_p2.y - in_p1.y); n.y = 0; } - else if (s3 & SEG_R) { n.x = vScreenSize.x; n.y = in_p1.y + (in_p2.y - in_p1.y) * (vScreenSize.x - in_p1.x) / (in_p2.x - in_p1.x); } - else if (s3 & SEG_L) { n.x = 0; n.y = in_p1.y + (in_p2.y - in_p1.y) * (0 - in_p1.x) / (in_p2.x - in_p1.x); } - if (s3 == s1) { in_p1 = n; s1 = Segment(in_p1); } - else { in_p2 = n; s2 = Segment(in_p2); } - } - } - return true; - } - - void PixelGameEngine::EnablePixelTransfer(const bool bEnable) - { - bSuspendTextureTransfer = !bEnable; - } - - - void PixelGameEngine::FillRect(const olc::vi2d& pos, const olc::vi2d& size, Pixel p) - { FillRect(pos.x, pos.y, size.x, size.y, p); } - - void PixelGameEngine::FillRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p) - { - int32_t x2 = x + w; - int32_t y2 = y + h; - - if (x < 0) x = 0; - if (x >= (int32_t)GetDrawTargetWidth()) x = (int32_t)GetDrawTargetWidth(); - if (y < 0) y = 0; - if (y >= (int32_t)GetDrawTargetHeight()) y = (int32_t)GetDrawTargetHeight(); - - if (x2 < 0) x2 = 0; - if (x2 >= (int32_t)GetDrawTargetWidth()) x2 = (int32_t)GetDrawTargetWidth(); - if (y2 < 0) y2 = 0; - if (y2 >= (int32_t)GetDrawTargetHeight()) y2 = (int32_t)GetDrawTargetHeight(); - - for (int i = x; i < x2; i++) - for (int j = y; j < y2; j++) - Draw(i, j, p); - } - - void PixelGameEngine::DrawTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p) - { DrawTriangle(pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y, p); } - - void PixelGameEngine::DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p) - { - DrawLine(x1, y1, x2, y2, p); - DrawLine(x2, y2, x3, y3, p); - DrawLine(x3, y3, x1, y1, p); - } - - void PixelGameEngine::FillTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p) - { FillTriangle(pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y, p); } - - // https://www.avrfreaks.net/sites/default/files/triangles.c - void PixelGameEngine::FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p) - { - auto drawline = [&](int sx, int ex, int ny) { for (int i = sx; i <= ex; i++) Draw(i, ny, p); }; - - int t1x, t2x, y, minx, maxx, t1xp, t2xp; - bool changed1 = false; - bool changed2 = false; - int signx1, signx2, dx1, dy1, dx2, dy2; - int e1, e2; - // Sort vertices - if (y1 > y2) { std::swap(y1, y2); std::swap(x1, x2); } - if (y1 > y3) { std::swap(y1, y3); std::swap(x1, x3); } - if (y2 > y3) { std::swap(y2, y3); std::swap(x2, x3); } - - t1x = t2x = x1; y = y1; // Starting points - dx1 = (int)(x2 - x1); - if (dx1 < 0) { dx1 = -dx1; signx1 = -1; } - else signx1 = 1; - dy1 = (int)(y2 - y1); - - dx2 = (int)(x3 - x1); - if (dx2 < 0) { dx2 = -dx2; signx2 = -1; } - else signx2 = 1; - dy2 = (int)(y3 - y1); - - if (dy1 > dx1) { std::swap(dx1, dy1); changed1 = true; } - if (dy2 > dx2) { std::swap(dy2, dx2); changed2 = true; } - - e2 = (int)(dx2 >> 1); - // Flat top, just process the second half - if (y1 == y2) goto next; - e1 = (int)(dx1 >> 1); - - for (int i = 0; i < dx1;) { - t1xp = 0; t2xp = 0; - if (t1x < t2x) { minx = t1x; maxx = t2x; } - else { minx = t2x; maxx = t1x; } - // process first line until y value is about to change - while (i < dx1) { - i++; - e1 += dy1; - while (e1 >= dx1) { - e1 -= dx1; - if (changed1) t1xp = signx1;//t1x += signx1; - else goto next1; - } - if (changed1) break; - else t1x += signx1; - } - // Move line - next1: - // process second line until y value is about to change - while (1) { - e2 += dy2; - while (e2 >= dx2) { - e2 -= dx2; - if (changed2) t2xp = signx2;//t2x += signx2; - else goto next2; - } - if (changed2) break; - else t2x += signx2; - } - next2: - if (minx > t1x) minx = t1x; - if (minx > t2x) minx = t2x; - if (maxx < t1x) maxx = t1x; - if (maxx < t2x) maxx = t2x; - drawline(minx, maxx, y); // Draw line from min to max points found on the y - // Now increase y - if (!changed1) t1x += signx1; - t1x += t1xp; - if (!changed2) t2x += signx2; - t2x += t2xp; - y += 1; - if (y == y2) break; - } - next: - // Second half - dx1 = (int)(x3 - x2); if (dx1 < 0) { dx1 = -dx1; signx1 = -1; } - else signx1 = 1; - dy1 = (int)(y3 - y2); - t1x = x2; - - if (dy1 > dx1) { // swap values - std::swap(dy1, dx1); - changed1 = true; - } - else changed1 = false; - - e1 = (int)(dx1 >> 1); - - for (int i = 0; i <= dx1; i++) { - t1xp = 0; t2xp = 0; - if (t1x < t2x) { minx = t1x; maxx = t2x; } - else { minx = t2x; maxx = t1x; } - // process first line until y value is about to change - while (i < dx1) { - e1 += dy1; - while (e1 >= dx1) { - e1 -= dx1; - if (changed1) { t1xp = signx1; break; }//t1x += signx1; - else goto next3; - } - if (changed1) break; - else t1x += signx1; - if (i < dx1) i++; - } - next3: - // process second line until y value is about to change - while (t2x != x3) { - e2 += dy2; - while (e2 >= dx2) { - e2 -= dx2; - if (changed2) t2xp = signx2; - else goto next4; - } - if (changed2) break; - else t2x += signx2; - } - next4: - - if (minx > t1x) minx = t1x; - if (minx > t2x) minx = t2x; - if (maxx < t1x) maxx = t1x; - if (maxx < t2x) maxx = t2x; - drawline(minx, maxx, y); - if (!changed1) t1x += signx1; - t1x += t1xp; - if (!changed2) t2x += signx2; - t2x += t2xp; - y += 1; - if (y > y3) return; - } - } - - void PixelGameEngine::DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale, uint8_t flip) - { DrawSprite(pos.x, pos.y, sprite, scale, flip); } - - void PixelGameEngine::DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale, uint8_t flip) - { - if (sprite == nullptr) - return; - - int32_t fxs = 0, fxm = 1, fx = 0; - int32_t fys = 0, fym = 1, fy = 0; - if (flip & olc::Sprite::Flip::HORIZ) { fxs = sprite->width - 1; fxm = -1; } - if (flip & olc::Sprite::Flip::VERT) { fys = sprite->height - 1; fym = -1; } - - if (scale > 1) - { - fx = fxs; - for (int32_t i = 0; i < sprite->width; i++, fx += fxm) - { - fy = fys; - for (int32_t j = 0; j < sprite->height; j++, fy += fym) - for (uint32_t is = 0; is < scale; is++) - for (uint32_t js = 0; js < scale; js++) - Draw(x + (i * scale) + is, y + (j * scale) + js, sprite->GetPixel(fx, fy)); - } - } - else - { - fx = fxs; - for (int32_t i = 0; i < sprite->width; i++, fx += fxm) - { - fy = fys; - for (int32_t j = 0; j < sprite->height; j++, fy += fym) - Draw(x + i, y + j, sprite->GetPixel(fx, fy)); - } - } - } - - void PixelGameEngine::DrawPartialSprite(const olc::vi2d& pos, Sprite* sprite, const olc::vi2d& sourcepos, const olc::vi2d& size, uint32_t scale, uint8_t flip) - { DrawPartialSprite(pos.x, pos.y, sprite, sourcepos.x, sourcepos.y, size.x, size.y, scale, flip); } - - void PixelGameEngine::DrawPartialSprite(int32_t x, int32_t y, Sprite* sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale, uint8_t flip) - { - if (sprite == nullptr) - return; - - int32_t fxs = 0, fxm = 1, fx = 0; - int32_t fys = 0, fym = 1, fy = 0; - if (flip & olc::Sprite::Flip::HORIZ) { fxs = w - 1; fxm = -1; } - if (flip & olc::Sprite::Flip::VERT) { fys = h - 1; fym = -1; } - - if (scale > 1) - { - fx = fxs; - for (int32_t i = 0; i < w; i++, fx += fxm) - { - fy = fys; - for (int32_t j = 0; j < h; j++, fy += fym) - for (uint32_t is = 0; is < scale; is++) - for (uint32_t js = 0; js < scale; js++) - Draw(x + (i * scale) + is, y + (j * scale) + js, sprite->GetPixel(fx + ox, fy + oy)); - } - } - else - { - fx = fxs; - for (int32_t i = 0; i < w; i++, fx += fxm) - { - fy = fys; - for (int32_t j = 0; j < h; j++, fy += fym) - Draw(x + i, y + j, sprite->GetPixel(fx + ox, fy + oy)); - } - } - } - - void PixelGameEngine::SetDecalMode(const olc::DecalMode& mode) - { nDecalMode = mode; } - - void PixelGameEngine::SetDecalStructure(const olc::DecalStructure& structure) - { nDecalStructure = structure; } - - void PixelGameEngine::DrawPartialDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale, const olc::Pixel& tint) - { - olc::vf2d vScreenSpacePos = - { - (pos.x * vInvScreenSize.x) * 2.0f - 1.0f, - -((pos.y * vInvScreenSize.y) * 2.0f - 1.0f) - }; - - - olc::vf2d vScreenSpaceDim = - { - ((pos.x + source_size.x * scale.x) * vInvScreenSize.x) * 2.0f - 1.0f, - -(((pos.y + source_size.y * scale.y) * vInvScreenSize.y) * 2.0f - 1.0f) - }; - - olc::vf2d vWindow = olc::vf2d(vViewSize); - olc::vf2d vQuantisedPos = ((vScreenSpacePos * vWindow) + olc::vf2d(0.5f, 0.5f)).floor() / vWindow; - olc::vf2d vQuantisedDim = ((vScreenSpaceDim * vWindow) + olc::vf2d(0.5f, -0.5f)).ceil() / vWindow; - - DecalInstance di; - di.points = 4; - di.decal = decal; - di.tint = { tint, tint, tint, tint }; - di.pos = { { vQuantisedPos.x, vQuantisedPos.y }, { vQuantisedPos.x, vQuantisedDim.y }, { vQuantisedDim.x, vQuantisedDim.y }, { vQuantisedDim.x, vQuantisedPos.y } }; - olc::vf2d uvtl = (source_pos + olc::vf2d(0.0001f, 0.0001f)) * decal->vUVScale; - olc::vf2d uvbr = (source_pos + source_size - olc::vf2d(0.0001f, 0.0001f)) * decal->vUVScale; - di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } }; - di.w = { 1,1,1,1 }; - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawPartialDecal(const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) - { - olc::vf2d vScreenSpacePos = - { - (pos.x * vInvScreenSize.x) * 2.0f - 1.0f, - ((pos.y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f - }; - - olc::vf2d vScreenSpaceDim = - { - vScreenSpacePos.x + (2.0f * size.x * vInvScreenSize.x), - vScreenSpacePos.y - (2.0f * size.y * vInvScreenSize.y) - }; - - DecalInstance di; - di.points = 4; - di.decal = decal; - di.tint = { tint, tint, tint, tint }; - di.pos = { { vScreenSpacePos.x, vScreenSpacePos.y }, { vScreenSpacePos.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpacePos.y } }; - olc::vf2d uvtl = (source_pos) * decal->vUVScale; - olc::vf2d uvbr = uvtl + ((source_size) * decal->vUVScale); - di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } }; - di.w = { 1,1,1,1 }; - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - - void PixelGameEngine::DrawDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& scale, const olc::Pixel& tint) - { - olc::vf2d vScreenSpacePos = - { - (pos.x * vInvScreenSize.x) * 2.0f - 1.0f, - ((pos.y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f - }; - - olc::vf2d vScreenSpaceDim = - { - vScreenSpacePos.x + (2.0f * (float(decal->sprite->width) * vInvScreenSize.x)) * scale.x, - vScreenSpacePos.y - (2.0f * (float(decal->sprite->height) * vInvScreenSize.y)) * scale.y - }; - - DecalInstance di; - di.decal = decal; - di.points = 4; - di.tint = { tint, tint, tint, tint }; - di.pos = { { vScreenSpacePos.x, vScreenSpacePos.y }, { vScreenSpacePos.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpacePos.y } }; - di.uv = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; - di.w = { 1, 1, 1, 1 }; - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements) - { - DecalInstance di; - di.decal = decal; - di.pos.resize(elements); - di.uv.resize(elements); - di.w.resize(elements); - di.tint.resize(elements); - di.points = elements; - for (uint32_t i = 0; i < elements; i++) - { - di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[i] = uv[i]; - di.tint[i] = col[i]; - di.w[i] = 1.0f; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const olc::Pixel tint) - { - DecalInstance di; - di.decal = decal; - di.points = uint32_t(pos.size()); - di.pos.resize(di.points); - di.uv.resize(di.points); - di.w.resize(di.points); - di.tint.resize(di.points); - for (uint32_t i = 0; i < di.points; i++) - { - di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[i] = uv[i]; - di.tint[i] = tint; - di.w[i] = 1.0f; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector &tint) - { - DecalInstance di; - di.decal = decal; - di.points = uint32_t(pos.size()); - di.pos.resize(di.points); - di.uv.resize(di.points); - di.w.resize(di.points); - di.tint.resize(di.points); - for (uint32_t i = 0; i < di.points; i++) - { - di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[i] = uv[i]; - di.tint[i] = tint[i]; - di.w[i] = 1.0f; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const olc::Pixel tint) - { - DecalInstance di; - di.decal = decal; - di.points = uint32_t(pos.size()); - di.pos.resize(di.points); - di.uv.resize(di.points); - di.w.resize(di.points); - di.tint.resize(di.points); - for (uint32_t i = 0; i < di.points; i++) - { - di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[i] = uv[i]; - di.tint[i] = tint; - di.w[i] = 1.0f; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - -#ifdef OLC_ENABLE_EXPERIMENTAL - // Lightweight 3D - void PixelGameEngine::LW3D_DrawTriangles(olc::Decal* decal, const std::vector>& pos, const std::vector& tex, const std::vector& col) - { - DecalInstance di; - di.decal = decal; - di.points = uint32_t(pos.size()); - di.pos.resize(di.points); - di.uv.resize(di.points); - di.w.resize(di.points); - di.tint.resize(di.points); - for (uint32_t i = 0; i < di.points; i++) - { - di.pos[i] = { pos[i][0], pos[i][1] }; - di.w[i] = pos[i][2]; - di.uv[i] = tex[i]; - di.tint[i] = col[i]; - } - di.mode = DecalMode::MODEL3D; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } -#endif - - void PixelGameEngine::DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p) - { - DecalInstance di; - di.decal = nullptr; - di.points = uint32_t(2); - di.pos.resize(di.points); - di.uv.resize(di.points); - di.w.resize(di.points); - di.tint.resize(di.points); - di.pos[0] = { (pos1.x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos1.y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[0] = { 0.0f, 0.0f }; - di.tint[0] = p; - di.w[0] = 1.0f; - di.pos[1] = { (pos2.x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos2.y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[1] = { 0.0f, 0.0f }; - di.tint[1] = p; - di.w[1] = 1.0f; - di.mode = olc::DecalMode::WIREFRAME; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col) - { - olc::vf2d vNewSize = (size - olc::vf2d(0.375f, 0.375f)).ceil(); - std::array points = { { {pos}, {pos.x, pos.y + vNewSize.y}, {pos + vNewSize}, {pos.x + vNewSize.x, pos.y} } }; - std::array uvs = { {{0,0},{0,0},{0,0},{0,0}} }; - std::array cols = { {col, col, col, col} }; - DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4); - } - - void PixelGameEngine::GradientFillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel colTL, const olc::Pixel colBL, const olc::Pixel colBR, const olc::Pixel colTR) - { - std::array points = { { {pos}, {pos.x, pos.y + size.y}, {pos + size}, {pos.x + size.x, pos.y} } }; - std::array uvs = { {{0,0},{0,0},{0,0},{0,0}} }; - std::array cols = { {colTL, colBL, colBR, colTR} }; - DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data(), 4); - } - - void PixelGameEngine::DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& scale, const olc::Pixel& tint) - { - DecalInstance di; - di.decal = decal; - di.pos.resize(4); - di.uv = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; - di.w = { 1, 1, 1, 1 }; - di.tint = { tint, tint, tint, tint }; - di.points = 4; - di.pos[0] = (olc::vf2d(0.0f, 0.0f) - center) * scale; - di.pos[1] = (olc::vf2d(0.0f, float(decal->sprite->height)) - center) * scale; - di.pos[2] = (olc::vf2d(float(decal->sprite->width), float(decal->sprite->height)) - center) * scale; - di.pos[3] = (olc::vf2d(float(decal->sprite->width), 0.0f) - center) * scale; - float c = cos(fAngle), s = sin(fAngle); - for (int i = 0; i < 4; i++) - { - di.pos[i] = pos + olc::vf2d(di.pos[i].x * c - di.pos[i].y * s, di.pos[i].x * s + di.pos[i].y * c); - di.pos[i] = di.pos[i] * vInvScreenSize * 2.0f - olc::vf2d(1.0f, 1.0f); - di.pos[i].y *= -1.0f; - di.w[i] = 1; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - - void PixelGameEngine::DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale, const olc::Pixel& tint) - { - DecalInstance di; - di.decal = decal; - di.points = 4; - di.tint = { tint, tint, tint, tint }; - di.w = { 1, 1, 1, 1 }; - di.pos.resize(4); - di.pos[0] = (olc::vf2d(0.0f, 0.0f) - center) * scale; - di.pos[1] = (olc::vf2d(0.0f, source_size.y) - center) * scale; - di.pos[2] = (olc::vf2d(source_size.x, source_size.y) - center) * scale; - di.pos[3] = (olc::vf2d(source_size.x, 0.0f) - center) * scale; - float c = cos(fAngle), s = sin(fAngle); - for (int i = 0; i < 4; i++) - { - di.pos[i] = pos + olc::vf2d(di.pos[i].x * c - di.pos[i].y * s, di.pos[i].x * s + di.pos[i].y * c); - di.pos[i] = di.pos[i] * vInvScreenSize * 2.0f - olc::vf2d(1.0f, 1.0f); - di.pos[i].y *= -1.0f; - } - - olc::vf2d uvtl = source_pos * decal->vUVScale; - olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale); - di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } }; - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) - { - DecalInstance di; - di.points = 4; - di.decal = decal; - di.tint = { tint, tint, tint, tint }; - di.w = { 1, 1, 1, 1 }; - di.pos.resize(4); - di.uv = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; - olc::vf2d center; - float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y)); - if (rd != 0) - { - olc::vf2d uvtl = source_pos * decal->vUVScale; - olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale); - di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } }; - - rd = 1.0f / rd; - float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd; - float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd; - if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]); - float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag(); - for (int i = 0; i < 4; i++) - { - float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3]; - di.uv[i] *= q; di.w[i] *= q; - di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - } - - void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint) - { - // Thanks Nathan Reed, a brilliant article explaining whats going on here - // http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/ - DecalInstance di; - di.points = 4; - di.decal = decal; - di.tint = { tint, tint, tint, tint }; - di.w = { 1, 1, 1, 1 }; - di.pos.resize(4); - di.uv = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; - olc::vf2d center; - float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y)); - if (rd != 0) - { - rd = 1.0f / rd; - float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd; - float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd; - if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]); - float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag(); - for (int i = 0; i < 4; i++) - { - float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3]; - di.uv[i] *= q; di.w[i] *= q; - di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - } - di.mode = nDecalMode; - di.structure = nDecalStructure; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - } - - void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const std::array& pos, const olc::Pixel& tint) - { DrawWarpedDecal(decal, pos.data(), tint); } - - void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint) - { DrawWarpedDecal(decal, &pos[0], tint); } - - void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const std::array& pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) - { DrawPartialWarpedDecal(decal, pos.data(), source_pos, source_size, tint); } - - void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) - { DrawPartialWarpedDecal(decal, &pos[0], source_pos, source_size, tint); } - - void PixelGameEngine::DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale) - { - olc::vf2d spos = { 0.0f, 0.0f }; - for (auto c : sText) - { - if (c == '\n') - { - spos.x = 0; spos.y += 8.0f * scale.y; - } - else if (c == '\t') - { - spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialDecal(pos + spos, fontRenderable.Decal(), {float(ox) * 8.0f, float(oy) * 8.0f}, {8.0f, 8.0f}, scale, col); - spos.x += 8.0f * scale.x; - } - } - } - - void PixelGameEngine::DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale) - { - olc::vf2d spos = { 0.0f, 0.0f }; - for (auto c : sText) - { - if (c == '\n') - { - spos.x = 0; spos.y += 8.0f * scale.y; - } - else if (c == '\t') - { - spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialDecal(pos + spos, fontRenderable.Decal(), { float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(vFontSpacing[c - 32].y), 8.0f }, scale, col); - spos.x += float(vFontSpacing[c - 32].y) * scale.x; - } - } - } - // Thanks Oso-Grande/Sopadeoso For these awesom and stupidly clever Text Rotation routines... duh XD - void PixelGameEngine::DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const olc::vf2d& scale) - { - olc::vf2d spos = center; - for (auto c : sText) - { - if (c == '\n') - { - spos.x = center.x; spos.y -= 8.0f; - } - else if (c == '\t') - { - spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialRotatedDecal(pos, fontRenderable.Decal(), fAngle, spos, { float(ox) * 8.0f, float(oy) * 8.0f }, { 8.0f, 8.0f }, scale, col); - spos.x -= 8.0f; - } - } - } - - void PixelGameEngine::DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const olc::vf2d& scale) - { - olc::vf2d spos = center; - for (auto c : sText) - { - if (c == '\n') - { - spos.x = center.x; spos.y -= 8.0f; - } - else if (c == '\t') - { - spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialRotatedDecal(pos, fontRenderable.Decal(), fAngle, spos, { float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(vFontSpacing[c - 32].y), 8.0f }, scale, col); - spos.x -= float(vFontSpacing[c - 32].y); - } - } - } - - olc::vi2d PixelGameEngine::GetTextSize(const std::string& s) - { - olc::vi2d size = { 0,1 }; - olc::vi2d pos = { 0,1 }; - for (auto c : s) - { - if (c == '\n') { pos.y++; pos.x = 0; } - else if (c == '\t') { pos.x += nTabSizeInSpaces; } - else pos.x++; - size.x = std::max(size.x, pos.x); - size.y = std::max(size.y, pos.y); - } - return size * 8; - } - - void PixelGameEngine::DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) - { DrawString(pos.x, pos.y, sText, col, scale); } - - void PixelGameEngine::DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col, uint32_t scale) - { - int32_t sx = 0; - int32_t sy = 0; - Pixel::Mode m = nPixelMode; - // Thanks @tucna, spotted bug with col.ALPHA :P - if (m != Pixel::CUSTOM) // Thanks @Megarev, required for "shaders" - { - if (col.a != 255) SetPixelMode(Pixel::ALPHA); - else SetPixelMode(Pixel::MASK); - } - for (auto c : sText) - { - if (c == '\n') - { - sx = 0; sy += 8 * scale; - } - else if (c == '\t') - { - sx += 8 * nTabSizeInSpaces * scale; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - - if (scale > 1) - { - for (uint32_t i = 0; i < 8; i++) - for (uint32_t j = 0; j < 8; j++) - if (fontRenderable.Sprite()->GetPixel(i + ox * 8, j + oy * 8).r > 0) - for (uint32_t is = 0; is < scale; is++) - for (uint32_t js = 0; js < scale; js++) - Draw(x + sx + (i * scale) + is, y + sy + (j * scale) + js, col); - } - else - { - for (uint32_t i = 0; i < 8; i++) - for (uint32_t j = 0; j < 8; j++) - if (fontRenderable.Sprite()->GetPixel(i + ox * 8, j + oy * 8).r > 0) - Draw(x + sx + i, y + sy + j, col); - } - sx += 8 * scale; - } - } - SetPixelMode(m); - } - - olc::vi2d PixelGameEngine::GetTextSizeProp(const std::string& s) - { - olc::vi2d size = { 0,1 }; - olc::vi2d pos = { 0,1 }; - for (auto c : s) - { - if (c == '\n') { pos.y += 1; pos.x = 0; } - else if (c == '\t') { pos.x += nTabSizeInSpaces * 8; } - else pos.x += vFontSpacing[c - 32].y; - size.x = std::max(size.x, pos.x); - size.y = std::max(size.y, pos.y); - } - - size.y *= 8; - return size; - } - - void PixelGameEngine::DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) - { DrawStringProp(pos.x, pos.y, sText, col, scale); } - - void PixelGameEngine::DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col, uint32_t scale) - { - int32_t sx = 0; - int32_t sy = 0; - Pixel::Mode m = nPixelMode; - - if (m != Pixel::CUSTOM) - { - if (col.a != 255) SetPixelMode(Pixel::ALPHA); - else SetPixelMode(Pixel::MASK); - } - for (auto c : sText) - { - if (c == '\n') - { - sx = 0; sy += 8 * scale; - } - else if (c == '\t') - { - sx += 8 * nTabSizeInSpaces * scale; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - - if (scale > 1) - { - for (int32_t i = 0; i < vFontSpacing[c - 32].y; i++) - for (int32_t j = 0; j < 8; j++) - if (fontRenderable.Sprite()->GetPixel(i + ox * 8 + vFontSpacing[c - 32].x, j + oy * 8).r > 0) - for (int32_t is = 0; is < int(scale); is++) - for (int32_t js = 0; js < int(scale); js++) - Draw(x + sx + (i * scale) + is, y + sy + (j * scale) + js, col); - } - else - { - for (int32_t i = 0; i < vFontSpacing[c - 32].y; i++) - for (int32_t j = 0; j < 8; j++) - if (fontRenderable.Sprite()->GetPixel(i + ox * 8 + vFontSpacing[c - 32].x, j + oy * 8).r > 0) - Draw(x + sx + i, y + sy + j, col); - } - sx += vFontSpacing[c - 32].y * scale; - } - } - SetPixelMode(m); - } - - void PixelGameEngine::SetPixelMode(Pixel::Mode m) - { nPixelMode = m; } - - Pixel::Mode PixelGameEngine::GetPixelMode() - { return nPixelMode; } - - void PixelGameEngine::SetPixelMode(std::function pixelMode) - { - funcPixelMode = pixelMode; - nPixelMode = Pixel::Mode::CUSTOM; - } - - void PixelGameEngine::SetPixelBlend(float fBlend) - { - fBlendFactor = fBlend; - if (fBlendFactor < 0.0f) fBlendFactor = 0.0f; - if (fBlendFactor > 1.0f) fBlendFactor = 1.0f; - } - - std::stringstream& PixelGameEngine::ConsoleOut() - { return ssConsoleOutput; } - - bool PixelGameEngine::IsConsoleShowing() const - { return bConsoleShow; } - - void PixelGameEngine::ConsoleShow(const olc::Key& keyExit, bool bSuspendTime) - { - if (bConsoleShow) - return; - - bConsoleShow = true; - bConsoleSuspendTime = bSuspendTime; - TextEntryEnable(true); - keyConsoleExit = keyExit; - pKeyboardState[keyConsoleExit].bHeld = false; - pKeyboardState[keyConsoleExit].bPressed = false; - pKeyboardState[keyConsoleExit].bReleased = true; - } - - void PixelGameEngine::ConsoleClear() - { sConsoleLines.clear(); } - - void PixelGameEngine::ConsoleCaptureStdOut(const bool bCapture) - { - if(bCapture) - sbufOldCout = std::cout.rdbuf(ssConsoleOutput.rdbuf()); - else - std::cout.rdbuf(sbufOldCout); - } - - void PixelGameEngine::UpdateConsole() - { - if (GetKey(keyConsoleExit).bPressed) - { - TextEntryEnable(false); - bConsoleSuspendTime = false; - bConsoleShow = false; - return; - } - - // Keep Console sizes based in real screen dimensions - vConsoleCharacterScale = olc::vf2d(1.0f, 2.0f) / (olc::vf2d(vViewSize) * vInvScreenSize); - vConsoleSize = (vViewSize / olc::vi2d(8, 16)) - olc::vi2d(2, 4); - - // If console has changed size, simply reset it - if (vConsoleSize.y != sConsoleLines.size()) - { - vConsoleCursor = { 0,0 }; - sConsoleLines.clear(); - sConsoleLines.resize(vConsoleSize.y); - } - - auto TypeCharacter = [&](const char c) - { - if (c >= 32 && c < 127) - { - sConsoleLines[vConsoleCursor.y].append(1, c); - vConsoleCursor.x++; - } - - if( c == '\n' || vConsoleCursor.x >= vConsoleSize.x) - { - vConsoleCursor.y++; vConsoleCursor.x = 0; - } - - if (vConsoleCursor.y >= vConsoleSize.y) - { - vConsoleCursor.y = vConsoleSize.y - 1; - for (size_t i = 1; i < vConsoleSize.y; i++) - sConsoleLines[i - 1] = sConsoleLines[i]; - sConsoleLines[vConsoleCursor.y].clear(); - } - }; - - // Empty out "std::cout", parsing as we go - while (ssConsoleOutput.rdbuf()->sgetc() != -1) - { - char c = ssConsoleOutput.rdbuf()->sbumpc(); - TypeCharacter(c); - } - - // Draw Shadow - GradientFillRectDecal({ 0,0 }, olc::vf2d(vScreenSize), olc::PixelF(0, 0, 0.5f, 0.5f), olc::PixelF(0, 0, 0.25f, 0.5f), olc::PixelF(0, 0, 0.25f, 0.5f), olc::PixelF(0, 0, 0.25f, 0.5f)); - - // Draw the console buffer - SetDecalMode(olc::DecalMode::NORMAL); - for (int32_t nLine = 0; nLine < vConsoleSize.y; nLine++) - DrawStringDecal(olc::vf2d( 1, 1 + float(nLine) ) * vConsoleCharacterScale * 8.0f, sConsoleLines[nLine], olc::WHITE, vConsoleCharacterScale); - - // Draw Input State - FillRectDecal(olc::vf2d(1 + float((TextEntryGetCursor() + 1)), 1 + float((vConsoleSize.y - 1))) * vConsoleCharacterScale * 8.0f, olc::vf2d(8, 8) * vConsoleCharacterScale, olc::DARK_CYAN); - DrawStringDecal(olc::vf2d(1, 1 + float((vConsoleSize.y - 1))) * vConsoleCharacterScale * 8.0f, std::string(">") + TextEntryGetString(), olc::YELLOW, vConsoleCharacterScale); - } - - - - void PixelGameEngine::TextEntryEnable(const bool bEnable, const std::string& sText) - { - if (bEnable) - { - nTextEntryCursor = int32_t(sText.size()); - sTextEntryString = sText; - bTextEntryEnable = true; - } - else - { - bTextEntryEnable = false; - } - } - - std::string PixelGameEngine::TextEntryGetString() const - { return sTextEntryString; } - - int32_t PixelGameEngine::TextEntryGetCursor() const - { return nTextEntryCursor; } - - bool PixelGameEngine::IsTextEntryEnabled() const - { return bTextEntryEnable; } - - - void PixelGameEngine::UpdateTextEntry() - { - // Check for typed characters - for (const auto& key : vKeyboardMap) - if (GetKey(std::get<0>(key)).bPressed) - { - sTextEntryString.insert(nTextEntryCursor, GetKey(olc::Key::SHIFT).bHeld ? std::get<2>(key) : std::get<1>(key)); - nTextEntryCursor++; - } - - // Check for command characters - if (GetKey(olc::Key::LEFT).bPressed) - nTextEntryCursor = std::max(0, nTextEntryCursor - 1); - if (GetKey(olc::Key::RIGHT).bPressed) - nTextEntryCursor = std::min(int32_t(sTextEntryString.size()), nTextEntryCursor + 1); - if (GetKey(olc::Key::BACK).bPressed && nTextEntryCursor > 0) - { - sTextEntryString.erase(nTextEntryCursor-1, 1); - nTextEntryCursor = std::max(0, nTextEntryCursor - 1); - } - if (GetKey(olc::Key::DEL).bPressed && nTextEntryCursor < sTextEntryString.size()) - sTextEntryString.erase(nTextEntryCursor, 1); - - if (GetKey(olc::Key::UP).bPressed) - { - if (!sCommandHistory.empty()) - { - if (sCommandHistoryIt != sCommandHistory.begin()) - sCommandHistoryIt--; - - nTextEntryCursor = int32_t(sCommandHistoryIt->size()); - sTextEntryString = *sCommandHistoryIt; - } - } - - if (GetKey(olc::Key::DOWN).bPressed) - { - if (!sCommandHistory.empty()) - { - if (sCommandHistoryIt != sCommandHistory.end()) - { - sCommandHistoryIt++; - if (sCommandHistoryIt != sCommandHistory.end()) - { - nTextEntryCursor = int32_t(sCommandHistoryIt->size()); - sTextEntryString = *sCommandHistoryIt; - } - else - { - nTextEntryCursor = 0; - sTextEntryString = ""; - } - } - } - } - - if (GetKey(olc::Key::ENTER).bPressed) - { - if (bConsoleShow) - { - std::cout << ">" + sTextEntryString + "\n"; - if (OnConsoleCommand(sTextEntryString)) - { - sCommandHistory.push_back(sTextEntryString); - sCommandHistoryIt = sCommandHistory.end(); - } - sTextEntryString.clear(); - nTextEntryCursor = 0; - } - else - { - OnTextEntryComplete(sTextEntryString); - TextEntryEnable(false); - } - } - } - - // User must override these functions as required. I have not made - // them abstract because I do need a default behaviour to occur if - // they are not overwritten - - bool PixelGameEngine::OnUserCreate() - { return false; } - - bool PixelGameEngine::OnUserUpdate(float fElapsedTime) - { UNUSED(fElapsedTime); return false; } - - bool PixelGameEngine::OnUserDestroy() - { return true; } - - void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); } - bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; } - - - // Externalised API - void PixelGameEngine::olc_UpdateViewport() - { - int32_t ww = vScreenSize.x * vPixelSize.x; - int32_t wh = vScreenSize.y * vPixelSize.y; - float wasp = (float)ww / (float)wh; - - if (bPixelCohesion) - { - vScreenPixelSize = (vWindowSize / vScreenSize); - vViewSize = (vWindowSize / vScreenSize) * vScreenSize; - } - else - { - vViewSize.x = (int32_t)vWindowSize.x; - vViewSize.y = (int32_t)((float)vViewSize.x / wasp); - - if (vViewSize.y > vWindowSize.y) - { - vViewSize.y = vWindowSize.y; - vViewSize.x = (int32_t)((float)vViewSize.y * wasp); - } - } - - vViewPos = (vWindowSize - vViewSize) / 2; - } - - void PixelGameEngine::olc_UpdateWindowSize(int32_t x, int32_t y) - { - vWindowSize = { x, y }; - olc_UpdateViewport(); - } - - void PixelGameEngine::olc_UpdateMouseWheel(int32_t delta) - { nMouseWheelDeltaCache += delta; } - - void PixelGameEngine::olc_UpdateMouse(int32_t x, int32_t y) - { - // Mouse coords come in screen space - // But leave in pixel space - bHasMouseFocus = true; - vMouseWindowPos = { x, y }; - // Full Screen mode may have a weird viewport we must clamp to - x -= vViewPos.x; - y -= vViewPos.y; - vMousePosCache.x = (int32_t)(((float)x / (float)(vWindowSize.x - (vViewPos.x * 2)) * (float)vScreenSize.x)); - vMousePosCache.y = (int32_t)(((float)y / (float)(vWindowSize.y - (vViewPos.y * 2)) * (float)vScreenSize.y)); - if (vMousePosCache.x >= (int32_t)vScreenSize.x) vMousePosCache.x = vScreenSize.x - 1; - if (vMousePosCache.y >= (int32_t)vScreenSize.y) vMousePosCache.y = vScreenSize.y - 1; - if (vMousePosCache.x < 0) vMousePosCache.x = 0; - if (vMousePosCache.y < 0) vMousePosCache.y = 0; - } - - void PixelGameEngine::olc_UpdateMouseState(int32_t button, bool state) - { pMouseNewState[button] = state; } - - void PixelGameEngine::olc_UpdateKeyState(int32_t key, bool state) - { pKeyNewState[key] = state; } - - void PixelGameEngine::olc_UpdateMouseFocus(bool state) - { bHasMouseFocus = state; } - - void PixelGameEngine::olc_UpdateKeyFocus(bool state) - { bHasInputFocus = state; } - - void PixelGameEngine::olc_Reanimate() - { bAtomActive = true; } - - bool PixelGameEngine::olc_IsRunning() - { return bAtomActive; } - - void PixelGameEngine::olc_Terminate() - { bAtomActive = false; } - - void PixelGameEngine::EngineThread() - { - // Allow platform to do stuff here if needed, since its now in the - // context of this thread - if (platform->ThreadStartUp() == olc::FAIL) return; - - // Do engine context specific initialisation - olc_PrepareEngine(); - - // Create user resources as part of this thread - for (auto& ext : vExtensions) ext->OnBeforeUserCreate(); - if (!OnUserCreate()) bAtomActive = false; - for (auto& ext : vExtensions) ext->OnAfterUserCreate(); - - while (bAtomActive) - { - // Run as fast as possible - while (bAtomActive) { olc_CoreUpdate(); } - - // Allow the user to free resources if they have overrided the destroy function - if (!OnUserDestroy()) - { - // User denied destroy for some reason, so continue running - bAtomActive = true; - } - } - - platform->ThreadCleanUp(); - } - - void PixelGameEngine::olc_PrepareEngine() - { - // Start OpenGL, the context is owned by the game thread - if (platform->CreateGraphics(bFullScreen, bEnableVSYNC, vViewPos, vViewSize) == olc::FAIL) return; - - // Construct default font sheet - olc_ConstructFontSheet(); - - // Create Primary Layer "0" - CreateLayer(); - vLayers[0].bUpdate = true; - vLayers[0].bShow = true; - SetDrawTarget(nullptr); - - m_tp1 = std::chrono::system_clock::now(); - m_tp2 = std::chrono::system_clock::now(); - } - - - void PixelGameEngine::olc_CoreUpdate() - { - // Handle Timing - m_tp2 = std::chrono::system_clock::now(); - std::chrono::duration elapsedTime = m_tp2 - m_tp1; - m_tp1 = m_tp2; - - // Our time per frame coefficient - float fElapsedTime = elapsedTime.count(); - fLastElapsed = fElapsedTime; - - if (bConsoleSuspendTime) - fElapsedTime = 0.0f; - - // Some platforms will need to check for events - platform->HandleSystemEvent(); - - // Compare hardware input states from previous frame - auto ScanHardware = [&](HWButton* pKeys, bool* pStateOld, bool* pStateNew, uint32_t nKeyCount) - { - for (uint32_t i = 0; i < nKeyCount; i++) - { - pKeys[i].bPressed = false; - pKeys[i].bReleased = false; - if (pStateNew[i] != pStateOld[i]) - { - if (pStateNew[i]) - { - pKeys[i].bPressed = !pKeys[i].bHeld; - pKeys[i].bHeld = true; - } - else - { - pKeys[i].bReleased = true; - pKeys[i].bHeld = false; - } - } - pStateOld[i] = pStateNew[i]; - } - }; - - ScanHardware(pKeyboardState, pKeyOldState, pKeyNewState, 256); - ScanHardware(pMouseState, pMouseOldState, pMouseNewState, nMouseButtons); - - // Cache mouse coordinates so they remain consistent during frame - vMousePos = vMousePosCache; - nMouseWheelDelta = nMouseWheelDeltaCache; - nMouseWheelDeltaCache = 0; - - if (bTextEntryEnable) - { - UpdateTextEntry(); - } - - // Handle Frame Update - bool bExtensionBlockFrame = false; - for (auto& ext : vExtensions) bExtensionBlockFrame |= ext->OnBeforeUserUpdate(fElapsedTime); - if (!bExtensionBlockFrame) - { - if (!OnUserUpdate(fElapsedTime)) bAtomActive = false; - } - for (auto& ext : vExtensions) ext->OnAfterUserUpdate(fElapsedTime); - - if (bConsoleShow) - { - SetDrawTarget((uint8_t)0); - UpdateConsole(); - } - - // Display Frame - renderer->UpdateViewport(vViewPos, vViewSize); - renderer->ClearBuffer(olc::BLACK, true); - - // Layer 0 must always exist - vLayers[0].bUpdate = true; - vLayers[0].bShow = true; - SetDecalMode(DecalMode::NORMAL); - renderer->PrepareDrawing(); - - for (auto layer = vLayers.rbegin(); layer != vLayers.rend(); ++layer) - { - if (layer->bShow) - { - if (layer->funcHook == nullptr) - { - renderer->ApplyTexture(layer->pDrawTarget.Decal()->id); - if (!bSuspendTextureTransfer && layer->bUpdate) - { - layer->pDrawTarget.Decal()->Update(); - layer->bUpdate = false; - } - - renderer->DrawLayerQuad(layer->vOffset, layer->vScale, layer->tint); - - // Display Decals in order for this layer - for (auto& decal : layer->vecDecalInstance) - renderer->DrawDecal(decal); - layer->vecDecalInstance.clear(); - } - else - { - // Mwa ha ha.... Have Fun!!! - layer->funcHook(); - } - } - } - - - - // Present Graphics to screen - renderer->DisplayFrame(); - - // Update Title Bar - fFrameTimer += fElapsedTime; - nFrameCount++; - if (fFrameTimer >= 1.0f) - { - nLastFPS = nFrameCount; - fFrameTimer -= 1.0f; - std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName + " - FPS: " + std::to_string(nFrameCount); - platform->SetWindowTitle(sTitle); - nFrameCount = 0; - } - } - - void PixelGameEngine::olc_ConstructFontSheet() - { - std::string data; - data += "?Q`0001oOch0o01o@F40o000000000"; - data += "O000000nOT0063Qo4d8>?7a14Gno94AA4gno94AaOT0>o3`oO400o7QN00000400"; - data += "Of80001oOg<7O7moBGT7O7lABET024@aBEd714AiOdl717a_=TH013Q>00000000"; - data += "720D000V?V5oB3Q_HdUoE7a9@DdDE4A9@DmoE4A;Hg]oM4Aj8S4D84@`00000000"; - data += "OaPT1000Oa`^13P1@AI[?g`1@A=[OdAoHgljA4Ao?WlBA7l1710007l100000000"; - data += "ObM6000oOfMV?3QoBDD`O7a0BDDH@5A0BDD<@5A0BGeVO5ao@CQR?5Po00000000"; - data += "Oc``000?Ogij70PO2D]??0Ph2DUM@7i`2DTg@7lh2GUj?0TO0C1870T?00000000"; - data += "70<4001o?P<7?1QoHg43O;`h@GT0@:@LB@d0>:@hN@L0@?aoN@<0O7ao0000?000"; - data += "OcH0001SOglLA7mg24TnK7ln24US>0PL24U140PnOgl0>7QgOcH0K71S0000A000"; - data += "00H00000@Dm1S007@DUSg00?OdTnH7YhOfTL<7Yh@Cl0700?@Ah0300700000000"; - data += "<008001QL00ZA41a@6HnI<1i@FHLM81M@@0LG81?O`0nC?Y7?`0ZA7Y300080000"; - data += "O`082000Oh0827mo6>Hn?Wmo?6HnMb11MP08@C11H`08@FP0@@0004@000000000"; - data += "00P00001Oab00003OcKP0006@6=PMgl<@440MglH@000000`@000001P00000000"; - data += "Ob@8@@00Ob@8@Ga13R@8Mga172@8?PAo3R@827QoOb@820@0O`0007`0000007P0"; - data += "O`000P08Od400g`<3V=P0G`673IP0`@3>1`00P@6O`P00g`SetPixel(px, py, olc::Pixel(k, k, k, k)); - if (++py == 48) { px++; py = 0; } - } - } - - fontRenderable.Decal()->Update(); - - constexpr std::array vSpacing = { { - 0x03,0x25,0x16,0x08,0x07,0x08,0x08,0x04,0x15,0x15,0x08,0x07,0x15,0x07,0x24,0x08, - 0x08,0x17,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x24,0x15,0x06,0x07,0x16,0x17, - 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x17,0x08,0x08,0x17,0x08,0x08,0x08, - 0x08,0x08,0x08,0x08,0x17,0x08,0x08,0x08,0x08,0x17,0x08,0x15,0x08,0x15,0x08,0x08, - 0x24,0x18,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x33,0x17,0x17,0x33,0x18,0x17,0x17, - 0x17,0x17,0x17,0x17,0x07,0x17,0x17,0x18,0x18,0x17,0x17,0x07,0x33,0x07,0x08,0x00, } }; - - for (auto c : vSpacing) vFontSpacing.push_back({ c >> 4, c & 15 }); - - // UK Standard Layout -#ifdef OLC_KEYBOARD_UK - vKeyboardMap = - { - {olc::Key::A, "a", "A"}, {olc::Key::B, "b", "B"}, {olc::Key::C, "c", "C"}, {olc::Key::D, "d", "D"}, {olc::Key::E, "e", "E"}, - {olc::Key::F, "f", "F"}, {olc::Key::G, "g", "G"}, {olc::Key::H, "h", "H"}, {olc::Key::I, "i", "I"}, {olc::Key::J, "j", "J"}, - {olc::Key::K, "k", "K"}, {olc::Key::L, "l", "L"}, {olc::Key::M, "m", "M"}, {olc::Key::N, "n", "N"}, {olc::Key::O, "o", "O"}, - {olc::Key::P, "p", "P"}, {olc::Key::Q, "q", "Q"}, {olc::Key::R, "r", "R"}, {olc::Key::S, "s", "S"}, {olc::Key::T, "t", "T"}, - {olc::Key::U, "u", "U"}, {olc::Key::V, "v", "V"}, {olc::Key::W, "w", "W"}, {olc::Key::X, "x", "X"}, {olc::Key::Y, "y", "Y"}, - {olc::Key::Z, "z", "Z"}, - - {olc::Key::K0, "0", ")"}, {olc::Key::K1, "1", "!"}, {olc::Key::K2, "2", "\""}, {olc::Key::K3, "3", "#"}, {olc::Key::K4, "4", "$"}, - {olc::Key::K5, "5", "%"}, {olc::Key::K6, "6", "^"}, {olc::Key::K7, "7", "&"}, {olc::Key::K8, "8", "*"}, {olc::Key::K9, "9", "("}, - - {olc::Key::NP0, "0", "0"}, {olc::Key::NP1, "1", "1"}, {olc::Key::NP2, "2", "2"}, {olc::Key::NP3, "3", "3"}, {olc::Key::NP4, "4", "4"}, - {olc::Key::NP5, "5", "5"}, {olc::Key::NP6, "6", "6"}, {olc::Key::NP7, "7", "7"}, {olc::Key::NP8, "8", "8"}, {olc::Key::NP9, "9", "9"}, - {olc::Key::NP_MUL, "*", "*"}, {olc::Key::NP_DIV, "/", "/"}, {olc::Key::NP_ADD, "+", "+"}, {olc::Key::NP_SUB, "-", "-"}, {olc::Key::NP_DECIMAL, ".", "."}, - - {olc::Key::PERIOD, ".", ">"}, {olc::Key::EQUALS, "=", "+"}, {olc::Key::COMMA, ",", "<"}, {olc::Key::MINUS, "-", "_"}, {olc::Key::SPACE, " ", " "}, - - {olc::Key::OEM_1, ";", ":"}, {olc::Key::OEM_2, "/", "?"}, {olc::Key::OEM_3, "\'", "@"}, {olc::Key::OEM_4, "[", "{"}, - {olc::Key::OEM_5, "\\", "|"}, {olc::Key::OEM_6, "]", "}"}, {olc::Key::OEM_7, "#", "~"}, - - // {olc::Key::TAB, "\t", "\t"} - }; -#endif - } - - void PixelGameEngine::pgex_Register(olc::PGEX* pgex) - { - if (std::find(vExtensions.begin(), vExtensions.end(), pgex) == vExtensions.end()) - vExtensions.push_back(pgex); - } - - - PGEX::PGEX(bool bHook) { if(bHook) pge->pgex_Register(this); } - void PGEX::OnBeforeUserCreate() {} - void PGEX::OnAfterUserCreate() {} - bool PGEX::OnBeforeUserUpdate(float& fElapsedTime) { return false; } - void PGEX::OnAfterUserUpdate(float fElapsedTime) {} - - // Need a couple of statics as these are singleton instances - // read from multiple locations - std::atomic PixelGameEngine::bAtomActive{ false }; - olc::PixelGameEngine* olc::PGEX::pge = nullptr; - olc::PixelGameEngine* olc::Platform::ptrPGE = nullptr; - olc::PixelGameEngine* olc::Renderer::ptrPGE = nullptr; - std::unique_ptr olc::Sprite::loader = nullptr; -}; -#pragma endregion - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine Renderers - the draw-y bits | -// O------------------------------------------------------------------------------O - -#if !defined(OLC_PGE_HEADLESS) - -#pragma region renderer_ogl10 -// O------------------------------------------------------------------------------O -// | START RENDERER: OpenGL 1.0 (the original, the best...) | -// O------------------------------------------------------------------------------O -#if defined(OLC_GFX_OPENGL10) - -#if defined(OLC_PLATFORM_WINAPI) - #include - #include - #if !defined(__MINGW32__) - #pragma comment(lib, "Dwmapi.lib") - #endif - typedef BOOL(WINAPI wglSwapInterval_t) (int interval); - static wglSwapInterval_t* wglSwapInterval = nullptr; - typedef HDC glDeviceContext_t; - typedef HGLRC glRenderContext_t; -#endif - -#if defined(__linux__) || defined(__FreeBSD__) - #include -#endif - -#if defined(OLC_PLATFORM_X11) - namespace X11 - { - #include - } - typedef int(glSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); - static glSwapInterval_t* glSwapIntervalEXT; - typedef X11::GLXContext glDeviceContext_t; - typedef X11::GLXContext glRenderContext_t; -#endif - -#if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #include - #include - #include -#endif - -namespace olc -{ - class Renderer_OGL10 : public olc::Renderer - { - private: -#if defined(OLC_PLATFORM_GLUT) - bool mFullScreen = false; -#else - glDeviceContext_t glDeviceContext = 0; - glRenderContext_t glRenderContext = 0; -#endif - - bool bSync = false; - olc::DecalMode nDecalMode = olc::DecalMode(-1); // Thanks Gusgo & Bispoo - olc::DecalStructure nDecalStructure = olc::DecalStructure(-1); -#if defined(OLC_PLATFORM_X11) - X11::Display* olc_Display = nullptr; - X11::Window* olc_Window = nullptr; - X11::XVisualInfo* olc_VisualInfo = nullptr; -#endif - - public: - void PrepareDevice() override - { -#if defined(OLC_PLATFORM_GLUT) - //glutInit has to be called with main() arguments, make fake ones - int argc = 0; - char* argv[1] = { (char*)"" }; - glutInit(&argc, argv); - glutInitWindowPosition(0, 0); - glutInitWindowSize(512, 512); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA); - // Creates the window and the OpenGL context for it - glutCreateWindow("OneLoneCoder.com - Pixel Game Engine"); - glEnable(GL_TEXTURE_2D); // Turn on texturing - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); -#endif - } - - olc::rcode CreateDevice(std::vector params, bool bFullScreen, bool bVSYNC) override - { -#if defined(OLC_PLATFORM_WINAPI) - // Create Device Context - glDeviceContext = GetDC((HWND)(params[0])); - PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - PFD_MAIN_PLANE, 0, 0, 0, 0 - }; - - int pf = 0; - if (!(pf = ChoosePixelFormat(glDeviceContext, &pfd))) return olc::FAIL; - SetPixelFormat(glDeviceContext, pf, &pfd); - - if (!(glRenderContext = wglCreateContext(glDeviceContext))) return olc::FAIL; - wglMakeCurrent(glDeviceContext, glRenderContext); - - // Remove Frame cap - wglSwapInterval = (wglSwapInterval_t*)wglGetProcAddress("wglSwapIntervalEXT"); - if (wglSwapInterval && !bVSYNC) wglSwapInterval(0); - bSync = bVSYNC; -#endif - -#if defined(OLC_PLATFORM_X11) - using namespace X11; - // Linux has tighter coupling between OpenGL and X11, so we store - // various "platform" handles in the renderer - olc_Display = (X11::Display*)(params[0]); - olc_Window = (X11::Window*)(params[1]); - olc_VisualInfo = (X11::XVisualInfo*)(params[2]); - - glDeviceContext = glXCreateContext(olc_Display, olc_VisualInfo, nullptr, GL_TRUE); - glXMakeCurrent(olc_Display, *olc_Window, glDeviceContext); - - XWindowAttributes gwa; - XGetWindowAttributes(olc_Display, *olc_Window, &gwa); - glViewport(0, 0, gwa.width, gwa.height); - - glSwapIntervalEXT = nullptr; - glSwapIntervalEXT = (glSwapInterval_t*)glXGetProcAddress((unsigned char*)"glXSwapIntervalEXT"); - - if (glSwapIntervalEXT == nullptr && !bVSYNC) - { - printf("NOTE: Could not disable VSYNC, glXSwapIntervalEXT() was not found!\n"); - printf(" Don't worry though, things will still work, it's just the\n"); - printf(" frame rate will be capped to your monitors refresh rate - javidx9\n"); - } - - if (glSwapIntervalEXT != nullptr && !bVSYNC) - glSwapIntervalEXT(olc_Display, *olc_Window, 0); -#endif - -#if defined(OLC_PLATFORM_GLUT) - mFullScreen = bFullScreen; - if (!bVSYNC) - { -#if defined(__APPLE__) - GLint sync = 0; - CGLContextObj ctx = CGLGetCurrentContext(); - if (ctx) CGLSetParameter(ctx, kCGLCPSwapInterval, &sync); -#endif - } -#else - glEnable(GL_TEXTURE_2D); // Turn on texturing - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); -#endif - return olc::rcode::OK; - } - - olc::rcode DestroyDevice() override - { -#if defined(OLC_PLATFORM_WINAPI) - wglDeleteContext(glRenderContext); -#endif - -#if defined(OLC_PLATFORM_X11) - glXMakeCurrent(olc_Display, None, NULL); - glXDestroyContext(olc_Display, glDeviceContext); -#endif - -#if defined(OLC_PLATFORM_GLUT) - glutDestroyWindow(glutGetWindow()); -#endif - return olc::rcode::OK; - } - - void DisplayFrame() override - { -#if defined(OLC_PLATFORM_WINAPI) - SwapBuffers(glDeviceContext); - if (bSync) DwmFlush(); // Woooohooooooo!!!! SMOOOOOOOTH! -#endif - -#if defined(OLC_PLATFORM_X11) - X11::glXSwapBuffers(olc_Display, *olc_Window); -#endif - -#if defined(OLC_PLATFORM_GLUT) - glutSwapBuffers(); -#endif - } - - void PrepareDrawing() override - { - - //ClearBuffer(olc::GREEN, true); - glEnable(GL_BLEND); - nDecalMode = DecalMode::NORMAL; - nDecalStructure = DecalStructure::FAN; - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - void SetDecalMode(const olc::DecalMode& mode) - { - if (mode != nDecalMode) - { - switch (mode) - { - case olc::DecalMode::NORMAL: - case olc::DecalMode::MODEL3D: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case olc::DecalMode::ADDITIVE: - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - break; - case olc::DecalMode::MULTIPLICATIVE: - glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); - break; - case olc::DecalMode::STENCIL: - glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - break; - case olc::DecalMode::ILLUMINATE: - glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); - break; - case olc::DecalMode::WIREFRAME: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - } - - nDecalMode = mode; - } - } - - void DrawLayerQuad(const olc::vf2d& offset, const olc::vf2d& scale, const olc::Pixel tint) override - { - glBegin(GL_QUADS); - glColor4ub(tint.r, tint.g, tint.b, tint.a); - glTexCoord2f(0.0f * scale.x + offset.x, 1.0f * scale.y + offset.y); - glVertex3f(-1.0f /*+ vSubPixelOffset.x*/, -1.0f /*+ vSubPixelOffset.y*/, 0.0f); - glTexCoord2f(0.0f * scale.x + offset.x, 0.0f * scale.y + offset.y); - glVertex3f(-1.0f /*+ vSubPixelOffset.x*/, 1.0f /*+ vSubPixelOffset.y*/, 0.0f); - glTexCoord2f(1.0f * scale.x + offset.x, 0.0f * scale.y + offset.y); - glVertex3f(1.0f /*+ vSubPixelOffset.x*/, 1.0f /*+ vSubPixelOffset.y*/, 0.0f); - glTexCoord2f(1.0f * scale.x + offset.x, 1.0f * scale.y + offset.y); - glVertex3f(1.0f /*+ vSubPixelOffset.x*/, -1.0f /*+ vSubPixelOffset.y*/, 0.0f); - glEnd(); - } - - void DrawDecal(const olc::DecalInstance& decal) override - { - SetDecalMode(decal.mode); - - if (decal.decal == nullptr) - glBindTexture(GL_TEXTURE_2D, 0); - else - glBindTexture(GL_TEXTURE_2D, decal.decal->id); - - if (nDecalMode == DecalMode::MODEL3D) - { -#ifdef OLC_ENABLE_EXPERIMENTAL - glMatrixMode(GL_PROJECTION); glPushMatrix(); - glMatrixMode(GL_MODELVIEW); glPushMatrix(); - - glEnable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-1.0f, 1.0f, -1.0f, 1.0f, 1, 1000); - - #pragma comment (lib, "winmm.lib") - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0, -40, -200); - glRotatef(float(clock()) * 0.1f, 1, 0, 0); - glRotatef(float(clock()) * 0.1f * 2, 0, 1, 0); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glBegin(GL_TRIANGLES); - - - // Render as 3D Spatial Entity - for (uint32_t n = 0; n < decal.points; n++) - { - glColor4ub(decal.tint[n].r, decal.tint[n].g, decal.tint[n].b, decal.tint[n].a); - glTexCoord2f(decal.uv[n].x, decal.uv[n].y); - glVertex3f(decal.pos[n].x, decal.pos[n].y, decal.w[n]); - } - - glEnd(); - - glMatrixMode(GL_PROJECTION); glPopMatrix(); - glMatrixMode(GL_MODELVIEW); glPopMatrix(); - glDisable(GL_DEPTH_TEST); -#endif - } - else - { - if (nDecalMode == DecalMode::WIREFRAME) - glBegin(GL_LINE_LOOP); - else - { - if(decal.structure == olc::DecalStructure::FAN) - glBegin(GL_TRIANGLE_FAN); - else if(decal.structure == olc::DecalStructure::STRIP) - glBegin(GL_TRIANGLE_STRIP); - else if(decal.structure == olc::DecalStructure::LIST) - glBegin(GL_TRIANGLES); - } - - // Render as 2D Spatial entity - for (uint32_t n = 0; n < decal.points; n++) - { - glColor4ub(decal.tint[n].r, decal.tint[n].g, decal.tint[n].b, decal.tint[n].a); - glTexCoord4f(decal.uv[n].x, decal.uv[n].y, 0.0f, decal.w[n]); - glVertex2f(decal.pos[n].x, decal.pos[n].y); - } - - glEnd(); - } - - - //glDisable(GL_DEPTH_TEST); - } - - uint32_t CreateTexture(const uint32_t width, const uint32_t height, const bool filtered, const bool clamp) override - { - UNUSED(width); - UNUSED(height); - uint32_t id = 0; - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); - if (filtered) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - - if (clamp) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - return id; - } - - uint32_t DeleteTexture(const uint32_t id) override - { - glDeleteTextures(1, &id); - return id; - } - - void UpdateTexture(uint32_t id, olc::Sprite* spr) override - { - UNUSED(id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, spr->width, spr->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spr->GetData()); - } - - void ReadTexture(uint32_t id, olc::Sprite* spr) override - { - glReadPixels(0, 0, spr->width, spr->height, GL_RGBA, GL_UNSIGNED_BYTE, spr->GetData()); - } - - void ApplyTexture(uint32_t id) override - { - glBindTexture(GL_TEXTURE_2D, id); - } - - void ClearBuffer(olc::Pixel p, bool bDepth) override - { - glClearColor(float(p.r) / 255.0f, float(p.g) / 255.0f, float(p.b) / 255.0f, float(p.a) / 255.0f); - glClear(GL_COLOR_BUFFER_BIT); - if (bDepth) glClear(GL_DEPTH_BUFFER_BIT); - } - - void UpdateViewport(const olc::vi2d& pos, const olc::vi2d& size) override - { - glViewport(pos.x, pos.y, size.x, size.y); - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | END RENDERER: OpenGL 1.0 (the original, the best...) | -// O------------------------------------------------------------------------------O -#pragma endregion - -#pragma region renderer_ogl33 -// O------------------------------------------------------------------------------O -// | START RENDERER: OpenGL 3.3 (3.0 es) (sh-sh-sh-shaders....) | -// O------------------------------------------------------------------------------O -#if defined(OLC_GFX_OPENGL33) - -#if defined(OLC_PLATFORM_WINAPI) - #include - #include - #if !defined(__MINGW32__) - #pragma comment(lib, "Dwmapi.lib") - #endif - typedef void __stdcall locSwapInterval_t(GLsizei n); - typedef HDC glDeviceContext_t; - typedef HGLRC glRenderContext_t; - #define CALLSTYLE __stdcall - #define OGL_LOAD(t, n) (t*)wglGetProcAddress(#n) -#endif - -#if defined(__linux__) || defined(__FreeBSD__) - #include -#endif - -#if defined(OLC_PLATFORM_X11) - namespace X11 - { - #include - } - typedef int(locSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); - typedef X11::GLXContext glDeviceContext_t; - typedef X11::GLXContext glRenderContext_t; - #define CALLSTYLE - #define OGL_LOAD(t, n) (t*)glXGetProcAddress((unsigned char*)#n); -#endif - -#if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #include - #include - #include -#endif - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - #include - #include - #define GL_GLEXT_PROTOTYPES - #include - #include - #define CALLSTYLE - typedef EGLBoolean(locSwapInterval_t)(EGLDisplay display, EGLint interval); - #define GL_CLAMP GL_CLAMP_TO_EDGE - #define OGL_LOAD(t, n) n; -#endif - -namespace olc -{ - typedef char GLchar; - typedef ptrdiff_t GLsizeiptr; - typedef GLuint CALLSTYLE locCreateShader_t(GLenum type); - typedef GLuint CALLSTYLE locCreateProgram_t(void); - typedef void CALLSTYLE locDeleteShader_t(GLuint shader); -#if defined(OLC_PLATFORM_EMSCRIPTEN) - typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); -#else - typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar** string, const GLint* length); -#endif - typedef void CALLSTYLE locCompileShader_t(GLuint shader); - typedef void CALLSTYLE locLinkProgram_t(GLuint program); - typedef void CALLSTYLE locDeleteProgram_t(GLuint program); - typedef void CALLSTYLE locAttachShader_t(GLuint program, GLuint shader); - typedef void CALLSTYLE locBindBuffer_t(GLenum target, GLuint buffer); - typedef void CALLSTYLE locBufferData_t(GLenum target, GLsizeiptr size, const void* data, GLenum usage); - typedef void CALLSTYLE locGenBuffers_t(GLsizei n, GLuint* buffers); - typedef void CALLSTYLE locVertexAttribPointer_t(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); - typedef void CALLSTYLE locEnableVertexAttribArray_t(GLuint index); - typedef void CALLSTYLE locUseProgram_t(GLuint program); - typedef void CALLSTYLE locBindVertexArray_t(GLuint array); - typedef void CALLSTYLE locGenVertexArrays_t(GLsizei n, GLuint* arrays); - typedef void CALLSTYLE locGetShaderInfoLog_t(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); - - constexpr size_t OLC_MAX_VERTS = 128; - - class Renderer_OGL33 : public olc::Renderer - { - private: -#if defined(OLC_PLATFORM_EMSCRIPTEN) - EGLDisplay olc_Display; - EGLConfig olc_Config; - EGLContext olc_Context; - EGLSurface olc_Surface; -#endif - -#if defined(OLC_PLATFORM_GLUT) - bool mFullScreen = false; -#else - #if !defined(OLC_PLATFORM_EMSCRIPTEN) - glDeviceContext_t glDeviceContext = 0; - glRenderContext_t glRenderContext = 0; - #endif -#endif - bool bSync = false; - olc::DecalMode nDecalMode = olc::DecalMode(-1); // Thanks Gusgo & Bispoo -#if defined(OLC_PLATFORM_X11) - X11::Display* olc_Display = nullptr; - X11::Window* olc_Window = nullptr; - X11::XVisualInfo* olc_VisualInfo = nullptr; -#endif - - private: - locCreateShader_t* locCreateShader = nullptr; - locShaderSource_t* locShaderSource = nullptr; - locCompileShader_t* locCompileShader = nullptr; - locDeleteShader_t* locDeleteShader = nullptr; - locCreateProgram_t* locCreateProgram = nullptr; - locDeleteProgram_t* locDeleteProgram = nullptr; - locLinkProgram_t* locLinkProgram = nullptr; - locAttachShader_t* locAttachShader = nullptr; - locBindBuffer_t* locBindBuffer = nullptr; - locBufferData_t* locBufferData = nullptr; - locGenBuffers_t* locGenBuffers = nullptr; - locVertexAttribPointer_t* locVertexAttribPointer = nullptr; - locEnableVertexAttribArray_t* locEnableVertexAttribArray = nullptr; - locUseProgram_t* locUseProgram = nullptr; - locBindVertexArray_t* locBindVertexArray = nullptr; - locGenVertexArrays_t* locGenVertexArrays = nullptr; - locSwapInterval_t* locSwapInterval = nullptr; - locGetShaderInfoLog_t* locGetShaderInfoLog = nullptr; - - uint32_t m_nFS = 0; - uint32_t m_nVS = 0; - uint32_t m_nQuadShader = 0; - uint32_t m_vbQuad = 0; - uint32_t m_vaQuad = 0; - - struct locVertex - { - float pos[3]; - olc::vf2d tex; - olc::Pixel col; - }; - - locVertex pVertexMem[OLC_MAX_VERTS]; - - olc::Renderable rendBlankQuad; - - public: - void PrepareDevice() override - { -#if defined(OLC_PLATFORM_GLUT) - //glutInit has to be called with main() arguments, make fake ones - int argc = 0; - char* argv[1] = { (char*)"" }; - glutInit(&argc, argv); - glutInitWindowPosition(0, 0); - glutInitWindowSize(512, 512); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA); - // Creates the window and the OpenGL context for it - glutCreateWindow("OneLoneCoder.com - Pixel Game Engine"); - glEnable(GL_TEXTURE_2D); // Turn on texturing - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); -#endif - } - - olc::rcode CreateDevice(std::vector params, bool bFullScreen, bool bVSYNC) override - { - // Create OpenGL Context -#if defined(OLC_PLATFORM_WINAPI) - // Create Device Context - glDeviceContext = GetDC((HWND)(params[0])); - PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - PFD_MAIN_PLANE, 0, 0, 0, 0 - }; - - int pf = 0; - if (!(pf = ChoosePixelFormat(glDeviceContext, &pfd))) return olc::FAIL; - SetPixelFormat(glDeviceContext, pf, &pfd); - - if (!(glRenderContext = wglCreateContext(glDeviceContext))) return olc::FAIL; - wglMakeCurrent(glDeviceContext, glRenderContext); - - // Set Vertical Sync - locSwapInterval = OGL_LOAD(locSwapInterval_t, "wglSwapIntervalEXT"); - if (locSwapInterval && !bVSYNC) locSwapInterval(0); - bSync = bVSYNC; -#endif - -#if defined(OLC_PLATFORM_X11) - using namespace X11; - // Linux has tighter coupling between OpenGL and X11, so we store - // various "platform" handles in the renderer - olc_Display = (X11::Display*)(params[0]); - olc_Window = (X11::Window*)(params[1]); - olc_VisualInfo = (X11::XVisualInfo*)(params[2]); - - glDeviceContext = glXCreateContext(olc_Display, olc_VisualInfo, nullptr, GL_TRUE); - glXMakeCurrent(olc_Display, *olc_Window, glDeviceContext); - - XWindowAttributes gwa; - XGetWindowAttributes(olc_Display, *olc_Window, &gwa); - glViewport(0, 0, gwa.width, gwa.height); - - locSwapInterval = OGL_LOAD(locSwapInterval_t, "glXSwapIntervalEXT"); - - if (locSwapInterval == nullptr && !bVSYNC) - { - printf("NOTE: Could not disable VSYNC, glXSwapIntervalEXT() was not found!\n"); - printf(" Don't worry though, things will still work, it's just the\n"); - printf(" frame rate will be capped to your monitors refresh rate - javidx9\n"); - } - - if (locSwapInterval != nullptr && !bVSYNC) - locSwapInterval(olc_Display, *olc_Window, 0); -#endif - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - EGLint const attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; - EGLint const context_config[] = { EGL_CONTEXT_CLIENT_VERSION , 2, EGL_NONE }; - EGLint num_config; - - olc_Display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(olc_Display, nullptr, nullptr); - eglChooseConfig(olc_Display, attribute_list, &olc_Config, 1, &num_config); - - /* create an EGL rendering context */ - olc_Context = eglCreateContext(olc_Display, olc_Config, EGL_NO_CONTEXT, context_config); - olc_Surface = eglCreateWindowSurface(olc_Display, olc_Config, NULL, nullptr); - eglMakeCurrent(olc_Display, olc_Surface, olc_Surface, olc_Context); - //eglSwapInterval is currently a NOP, plement anyways in case it becomes supported - locSwapInterval = &eglSwapInterval; - locSwapInterval(olc_Display, bVSYNC ? 1 : 0); -#endif - -#if defined(OLC_PLATFORM_GLUT) - mFullScreen = bFullScreen; - if (!bVSYNC) - { -#if defined(__APPLE__) - GLint sync = 0; - CGLContextObj ctx = CGLGetCurrentContext(); - if (ctx) CGLSetParameter(ctx, kCGLCPSwapInterval, &sync); -#endif - } -#else - #if !defined(OLC_PLATFORM_EMSCRIPTEN) - glEnable(GL_TEXTURE_2D); // Turn on texturing - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - #endif -#endif - // Load External OpenGL Functions - locCreateShader = OGL_LOAD(locCreateShader_t, glCreateShader); - locCompileShader = OGL_LOAD(locCompileShader_t, glCompileShader); - locShaderSource = OGL_LOAD(locShaderSource_t, glShaderSource); - locDeleteShader = OGL_LOAD(locDeleteShader_t, glDeleteShader); - locCreateProgram = OGL_LOAD(locCreateProgram_t, glCreateProgram); - locDeleteProgram = OGL_LOAD(locDeleteProgram_t, glDeleteProgram); - locLinkProgram = OGL_LOAD(locLinkProgram_t, glLinkProgram); - locAttachShader = OGL_LOAD(locAttachShader_t, glAttachShader); - locBindBuffer = OGL_LOAD(locBindBuffer_t, glBindBuffer); - locBufferData = OGL_LOAD(locBufferData_t, glBufferData); - locGenBuffers = OGL_LOAD(locGenBuffers_t, glGenBuffers); - locVertexAttribPointer = OGL_LOAD(locVertexAttribPointer_t, glVertexAttribPointer); - locEnableVertexAttribArray = OGL_LOAD(locEnableVertexAttribArray_t, glEnableVertexAttribArray); - locUseProgram = OGL_LOAD(locUseProgram_t, glUseProgram); - locGetShaderInfoLog = OGL_LOAD(locGetShaderInfoLog_t, glGetShaderInfoLog); -#if !defined(OLC_PLATFORM_EMSCRIPTEN) - locBindVertexArray = OGL_LOAD(locBindVertexArray_t, glBindVertexArray); - locGenVertexArrays = OGL_LOAD(locGenVertexArrays_t, glGenVertexArrays); -#else - locBindVertexArray = glBindVertexArrayOES; - locGenVertexArrays = glGenVertexArraysOES; -#endif - - // Load & Compile Quad Shader - assumes no errors - m_nFS = locCreateShader(0x8B30); - const GLchar* strFS = -#if defined(__arm__) || defined(OLC_PLATFORM_EMSCRIPTEN) - "#version 300 es\n" - "precision mediump float;" -#else - "#version 330 core\n" -#endif - "out vec4 pixel;\n""in vec2 oTex;\n" - "in vec4 oCol;\n""uniform sampler2D sprTex;\n""void main(){pixel = texture(sprTex, oTex) * oCol;}"; - locShaderSource(m_nFS, 1, &strFS, NULL); - locCompileShader(m_nFS); - - m_nVS = locCreateShader(0x8B31); - const GLchar* strVS = -#if defined(__arm__) || defined(OLC_PLATFORM_EMSCRIPTEN) - "#version 300 es\n" - "precision mediump float;" -#else - "#version 330 core\n" -#endif - "layout(location = 0) in vec3 aPos;\n""layout(location = 1) in vec2 aTex;\n" - "layout(location = 2) in vec4 aCol;\n""out vec2 oTex;\n""out vec4 oCol;\n" - "void main(){ float p = 1.0 / aPos.z; gl_Position = p * vec4(aPos.x, aPos.y, 0.0, 1.0); oTex = p * aTex; oCol = aCol;}"; - locShaderSource(m_nVS, 1, &strVS, NULL); - locCompileShader(m_nVS); - - m_nQuadShader = locCreateProgram(); - locAttachShader(m_nQuadShader, m_nFS); - locAttachShader(m_nQuadShader, m_nVS); - locLinkProgram(m_nQuadShader); - - // Create Quad - locGenBuffers(1, &m_vbQuad); - locGenVertexArrays(1, &m_vaQuad); - locBindVertexArray(m_vaQuad); - locBindBuffer(0x8892, m_vbQuad); - - locVertex verts[OLC_MAX_VERTS]; - locBufferData(0x8892, sizeof(locVertex) * OLC_MAX_VERTS, verts, 0x88E0); - locVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(locVertex), 0); locEnableVertexAttribArray(0); - locVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(locVertex), (void*)(3 * sizeof(float))); locEnableVertexAttribArray(1); - locVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(locVertex), (void*)(5 * sizeof(float))); locEnableVertexAttribArray(2); - locBindBuffer(0x8892, 0); - locBindVertexArray(0); - - // Create blank texture for spriteless decals - rendBlankQuad.Create(1, 1); - rendBlankQuad.Sprite()->GetData()[0] = olc::WHITE; - rendBlankQuad.Decal()->Update(); - return olc::rcode::OK; - } - - olc::rcode DestroyDevice() override - { -#if defined(OLC_PLATFORM_WINAPI) - wglDeleteContext(glRenderContext); -#endif - -#if defined(OLC_PLATFORM_X11) - glXMakeCurrent(olc_Display, None, NULL); - glXDestroyContext(olc_Display, glDeviceContext); -#endif - -#if defined(OLC_PLATFORM_GLUT) - glutDestroyWindow(glutGetWindow()); -#endif - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - eglMakeCurrent(olc_Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(olc_Display, olc_Context); - eglDestroySurface(olc_Display, olc_Surface); - eglTerminate(olc_Display); - olc_Display = EGL_NO_DISPLAY; - olc_Surface = EGL_NO_SURFACE; - olc_Context = EGL_NO_CONTEXT; -#endif - return olc::rcode::OK; - } - - void DisplayFrame() override - { -#if defined(OLC_PLATFORM_WINAPI) - SwapBuffers(glDeviceContext); - if (bSync) DwmFlush(); // Woooohooooooo!!!! SMOOOOOOOTH! -#endif - -#if defined(OLC_PLATFORM_X11) - X11::glXSwapBuffers(olc_Display, *olc_Window); -#endif - -#if defined(OLC_PLATFORM_GLUT) - glutSwapBuffers(); -#endif - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - eglSwapBuffers(olc_Display, olc_Surface); -#endif - } - - void PrepareDrawing() override - { - glEnable(GL_BLEND); - nDecalMode = DecalMode::NORMAL; - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - locUseProgram(m_nQuadShader); - locBindVertexArray(m_vaQuad); - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - locVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(locVertex), 0); locEnableVertexAttribArray(0); - locVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(locVertex), (void*)(3 * sizeof(float))); locEnableVertexAttribArray(1); - locVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(locVertex), (void*)(5 * sizeof(float))); locEnableVertexAttribArray(2); -#endif - } - - void SetDecalMode(const olc::DecalMode& mode) override - { - if (mode != nDecalMode) - { - switch (mode) - { - case olc::DecalMode::NORMAL: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; - case olc::DecalMode::ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; - case olc::DecalMode::MULTIPLICATIVE: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; - case olc::DecalMode::STENCIL: glBlendFunc(GL_ZERO, GL_SRC_ALPHA); break; - case olc::DecalMode::ILLUMINATE: glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); break; - case olc::DecalMode::WIREFRAME: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; - } - - nDecalMode = mode; - } - } - - void DrawLayerQuad(const olc::vf2d& offset, const olc::vf2d& scale, const olc::Pixel tint) override - { - locBindBuffer(0x8892, m_vbQuad); - locVertex verts[4] = { - {{-1.0f, -1.0f, 1.0}, {0.0f * scale.x + offset.x, 1.0f * scale.y + offset.y}, tint}, - {{+1.0f, -1.0f, 1.0}, {1.0f * scale.x + offset.x, 1.0f * scale.y + offset.y}, tint}, - {{-1.0f, +1.0f, 1.0}, {0.0f * scale.x + offset.x, 0.0f * scale.y + offset.y}, tint}, - {{+1.0f, +1.0f, 1.0}, {1.0f * scale.x + offset.x, 0.0f * scale.y + offset.y}, tint}, - }; - - locBufferData(0x8892, sizeof(locVertex) * 4, verts, 0x88E0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } - - void DrawDecal(const olc::DecalInstance& decal) override - { - SetDecalMode(decal.mode); - if (decal.decal == nullptr) - glBindTexture(GL_TEXTURE_2D, rendBlankQuad.Decal()->id); - else - glBindTexture(GL_TEXTURE_2D, decal.decal->id); - - locBindBuffer(0x8892, m_vbQuad); - - for (uint32_t i = 0; i < decal.points; i++) - pVertexMem[i] = { { decal.pos[i].x, decal.pos[i].y, decal.w[i] }, { decal.uv[i].x, decal.uv[i].y }, decal.tint[i] }; - - locBufferData(0x8892, sizeof(locVertex) * decal.points, pVertexMem, 0x88E0); - - if (nDecalMode == DecalMode::WIREFRAME) - glDrawArrays(GL_LINE_LOOP, 0, decal.points); - else - glDrawArrays(GL_TRIANGLE_FAN, 0, decal.points); - } - - uint32_t CreateTexture(const uint32_t width, const uint32_t height, const bool filtered, const bool clamp) override - { - UNUSED(width); - UNUSED(height); - uint32_t id = 0; - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); - - if (filtered) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - - if (clamp) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - } - else - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } -#if !defined(OLC_PLATFORM_EMSCRIPTEN) - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -#endif - return id; - } - - uint32_t DeleteTexture(const uint32_t id) override - { - glDeleteTextures(1, &id); - return id; - } - - void UpdateTexture(uint32_t id, olc::Sprite* spr) override - { - UNUSED(id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, spr->width, spr->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spr->GetData()); - } - - void ReadTexture(uint32_t id, olc::Sprite* spr) override - { - glReadPixels(0, 0, spr->width, spr->height, GL_RGBA, GL_UNSIGNED_BYTE, spr->GetData()); - } - - void ApplyTexture(uint32_t id) override - { - glBindTexture(GL_TEXTURE_2D, id); - } - - void ClearBuffer(olc::Pixel p, bool bDepth) override - { - glClearColor(float(p.r) / 255.0f, float(p.g) / 255.0f, float(p.b) / 255.0f, float(p.a) / 255.0f); - glClear(GL_COLOR_BUFFER_BIT); - if (bDepth) glClear(GL_DEPTH_BUFFER_BIT); - } - - void UpdateViewport(const olc::vi2d& pos, const olc::vi2d& size) override - { - glViewport(pos.x, pos.y, size.x, size.y); - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | END RENDERER: OpenGL 3.3 (3.0 es) (sh-sh-sh-shaders....) | -// O------------------------------------------------------------------------------O -#pragma endregion - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine Image loaders | -// O------------------------------------------------------------------------------O - -#pragma region image_gdi -// O------------------------------------------------------------------------------O -// | START IMAGE LOADER: GDI+, Windows Only, always exists, a little slow | -// O------------------------------------------------------------------------------O -#if defined(OLC_IMAGE_GDI) - -#define min(a, b) ((a < b) ? a : b) -#define max(a, b) ((a > b) ? a : b) -#include -#include -#if defined(__MINGW32__) // Thanks Gusgo & Dandistine, but c'mon mingw!! wtf?! - #include -#else - #include -#endif -#include -#undef min -#undef max - -#if !defined(__MINGW32__) - #pragma comment(lib, "gdiplus.lib") - #pragma comment(lib, "Shlwapi.lib") -#endif - -namespace olc -{ - // Thanks @MaGetzUb for this, which allows sprites to be defined - // at construction, by initialising the GDI subsystem - static class GDIPlusStartup - { - public: - GDIPlusStartup() - { - Gdiplus::GdiplusStartupInput startupInput; - GdiplusStartup(&token, &startupInput, NULL); - } - - ULONG_PTR token; - - ~GDIPlusStartup() - { - // Well, MarcusTU thought this was important :D - Gdiplus::GdiplusShutdown(token); - } - } gdistartup; - - class ImageLoader_GDIPlus : public olc::ImageLoader - { - private: - std::wstring ConvertS2W(std::string s) - { -#ifdef __MINGW32__ - wchar_t* buffer = new wchar_t[s.length() + 1]; - mbstowcs(buffer, s.c_str(), s.length()); - buffer[s.length()] = L'\0'; -#else - int count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); - wchar_t* buffer = new wchar_t[count]; - MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, buffer, count); -#endif - std::wstring w(buffer); - delete[] buffer; - return w; - } - - public: - ImageLoader_GDIPlus() : ImageLoader() - {} - - olc::rcode LoadImageResource(olc::Sprite* spr, const std::string& sImageFile, olc::ResourcePack* pack) override - { - // clear out existing sprite - spr->pColData.clear(); - - // Open file - UNUSED(pack); - Gdiplus::Bitmap* bmp = nullptr; - if (pack != nullptr) - { - // Load sprite from input stream - ResourceBuffer rb = pack->GetFileBuffer(sImageFile); - bmp = Gdiplus::Bitmap::FromStream(SHCreateMemStream((BYTE*)rb.vMemory.data(), UINT(rb.vMemory.size()))); - } - else - { - // Check file exists - if (!_gfs::exists(sImageFile)) return olc::rcode::NO_FILE; - - // Load sprite from file - bmp = Gdiplus::Bitmap::FromFile(ConvertS2W(sImageFile).c_str()); - } - - if (bmp->GetLastStatus() != Gdiplus::Ok) return olc::rcode::FAIL; - spr->width = bmp->GetWidth(); - spr->height = bmp->GetHeight(); - - spr->pColData.resize(spr->width * spr->height); - - for (int y = 0; y < spr->height; y++) - for (int x = 0; x < spr->width; x++) - { - Gdiplus::Color c; - bmp->GetPixel(x, y, &c); - spr->SetPixel(x, y, olc::Pixel(c.GetRed(), c.GetGreen(), c.GetBlue(), c.GetAlpha())); - } - delete bmp; - return olc::rcode::OK; - } - - olc::rcode SaveImageResource(olc::Sprite* spr, const std::string& sImageFile) override - { - return olc::rcode::OK; - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | END IMAGE LOADER: GDI+ | -// O------------------------------------------------------------------------------O -#pragma endregion - -#pragma region image_libpng -// O------------------------------------------------------------------------------O -// | START IMAGE LOADER: libpng, default on linux, requires -lpng (libpng-dev) | -// O------------------------------------------------------------------------------O -#if defined(OLC_IMAGE_LIBPNG) -#include -namespace olc -{ - void pngReadStream(png_structp pngPtr, png_bytep data, png_size_t length) - { - png_voidp a = png_get_io_ptr(pngPtr); - ((std::istream*)a)->read((char*)data, length); - } - - class ImageLoader_LibPNG : public olc::ImageLoader - { - public: - ImageLoader_LibPNG() : ImageLoader() - {} - - olc::rcode LoadImageResource(olc::Sprite* spr, const std::string& sImageFile, olc::ResourcePack* pack) override - { - UNUSED(pack); - - // clear out existing sprite - spr->pColData.clear(); - - //////////////////////////////////////////////////////////////////////////// - // Use libpng, Thanks to Guillaume Cottenceau - // https://gist.github.com/niw/5963798 - // Also reading png from streams - // http://www.piko3d.net/tutorials/libpng-tutorial-loading-png-files-from-streams/ - png_structp png; - png_infop info; - - auto loadPNG = [&]() - { - png_read_info(png, info); - png_byte color_type; - png_byte bit_depth; - png_bytep* row_pointers; - spr->width = png_get_image_width(png, info); - spr->height = png_get_image_height(png, info); - color_type = png_get_color_type(png, info); - bit_depth = png_get_bit_depth(png, info); - if (bit_depth == 16) png_set_strip_16(png); - if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png); - if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); - if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) - png_set_filler(png, 0xFF, PNG_FILLER_AFTER); - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png); - png_read_update_info(png, info); - row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * spr->height); - for (int y = 0; y < spr->height; y++) { - row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info)); - } - png_read_image(png, row_pointers); - //////////////////////////////////////////////////////////////////////////// - // Create sprite array - spr->pColData.resize(spr->width * spr->height); - // Iterate through image rows, converting into sprite format - for (int y = 0; y < spr->height; y++) - { - png_bytep row = row_pointers[y]; - for (int x = 0; x < spr->width; x++) - { - png_bytep px = &(row[x * 4]); - spr->SetPixel(x, y, Pixel(px[0], px[1], px[2], px[3])); - } - } - - for (int y = 0; y < spr->height; y++) // Thanks maksym33 - free(row_pointers[y]); - free(row_pointers); - png_destroy_read_struct(&png, &info, nullptr); - }; - - png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png) goto fail_load; - - info = png_create_info_struct(png); - if (!info) goto fail_load; - - if (setjmp(png_jmpbuf(png))) goto fail_load; - - if (pack == nullptr) - { - FILE* f = fopen(sImageFile.c_str(), "rb"); - if (!f) return olc::rcode::NO_FILE; - png_init_io(png, f); - loadPNG(); - fclose(f); - } - else - { - ResourceBuffer rb = pack->GetFileBuffer(sImageFile); - std::istream is(&rb); - png_set_read_fn(png, (png_voidp)&is, pngReadStream); - loadPNG(); - } - - return olc::rcode::OK; - - fail_load: - spr->width = 0; - spr->height = 0; - spr->pColData.clear(); - return olc::rcode::FAIL; - } - - olc::rcode SaveImageResource(olc::Sprite* spr, const std::string& sImageFile) override - { - return olc::rcode::OK; - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | END IMAGE LOADER: | -// O------------------------------------------------------------------------------O -#pragma endregion - -#pragma region image_stb -// O------------------------------------------------------------------------------O -// | START IMAGE LOADER: stb_image.h, all systems, very fast | -// O------------------------------------------------------------------------------O -// Thanks to Sean Barrett - https://github.com/nothings/stb/blob/master/stb_image.h -// MIT License - Copyright(c) 2017 Sean Barrett - -// Note you need to download the above file into your project folder, and -// #define OLC_IMAGE_STB -// #define OLC_PGE_APPLICATION -// #include "olcPixelGameEngine.h" - -#if defined(OLC_IMAGE_STB) -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -namespace olc -{ - class ImageLoader_STB : public olc::ImageLoader - { - public: - ImageLoader_STB() : ImageLoader() - {} - - olc::rcode LoadImageResource(olc::Sprite* spr, const std::string& sImageFile, olc::ResourcePack* pack) override - { - UNUSED(pack); - // clear out existing sprite - spr->pColData.clear(); - // Open file - stbi_uc* bytes = nullptr; - int w = 0, h = 0, cmp = 0; - if (pack != nullptr) - { - ResourceBuffer rb = pack->GetFileBuffer(sImageFile); - bytes = stbi_load_from_memory((unsigned char*)rb.vMemory.data(), rb.vMemory.size(), &w, &h, &cmp, 4); - } - else - { - // Check file exists - if (!_gfs::exists(sImageFile)) return olc::rcode::NO_FILE; - bytes = stbi_load(sImageFile.c_str(), &w, &h, &cmp, 4); - } - - if (!bytes) return olc::rcode::FAIL; - spr->width = w; spr->height = h; - spr->pColData.resize(spr->width * spr->height); - std::memcpy(spr->pColData.data(), bytes, spr->width * spr->height * 4); - delete[] bytes; - return olc::rcode::OK; - } - - olc::rcode SaveImageResource(olc::Sprite* spr, const std::string& sImageFile) override - { - return olc::rcode::OK; - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | START IMAGE LOADER: stb_image.h | -// O------------------------------------------------------------------------------O -#pragma endregion - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine Platforms | -// O------------------------------------------------------------------------------O - -#pragma region platform_windows -// O------------------------------------------------------------------------------O -// | START PLATFORM: MICROSOFT WINDOWS XP, VISTA, 7, 8, 10 | -// O------------------------------------------------------------------------------O -#if defined(OLC_PLATFORM_WINAPI) - -#if defined(_WIN32) && !defined(__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 -#endif - -namespace olc -{ - class Platform_Windows : public olc::Platform - { - private: - HWND olc_hWnd = nullptr; - std::wstring wsAppName; - - std::wstring ConvertS2W(std::string s) - { -#ifdef __MINGW32__ - wchar_t* buffer = new wchar_t[s.length() + 1]; - mbstowcs(buffer, s.c_str(), s.length()); - buffer[s.length()] = L'\0'; -#else - int count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); - wchar_t* buffer = new wchar_t[count]; - MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, buffer, count); -#endif - std::wstring w(buffer); - delete[] buffer; - return w; - } - - public: - virtual olc::rcode ApplicationStartUp() override { return olc::rcode::OK; } - virtual olc::rcode ApplicationCleanUp() override { return olc::rcode::OK; } - virtual olc::rcode ThreadStartUp() override { return olc::rcode::OK; } - - virtual olc::rcode ThreadCleanUp() override - { - renderer->DestroyDevice(); - PostMessage(olc_hWnd, WM_DESTROY, 0, 0); - return olc::OK; - } - - virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) override - { - if (renderer->CreateDevice({ olc_hWnd }, bFullScreen, bEnableVSYNC) == olc::rcode::OK) - { - renderer->UpdateViewport(vViewPos, vViewSize); - return olc::rcode::OK; - } - else - return olc::rcode::FAIL; - } - - virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) override - { - WNDCLASS wc; - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wc.hInstance = GetModuleHandle(nullptr); - wc.lpfnWndProc = olc_WindowEvent; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.lpszMenuName = nullptr; - wc.hbrBackground = nullptr; - wc.lpszClassName = olcT("OLC_PIXEL_GAME_ENGINE"); - RegisterClass(&wc); - - // Define window furniture - DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; - DWORD dwStyle = WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_THICKFRAME; - - olc::vi2d vTopLeft = vWindowPos; - - // Handle Fullscreen - if (bFullScreen) - { - dwExStyle = 0; - dwStyle = WS_VISIBLE | WS_POPUP; - HMONITOR hmon = MonitorFromWindow(olc_hWnd, MONITOR_DEFAULTTONEAREST); - MONITORINFO mi = { sizeof(mi) }; - if (!GetMonitorInfo(hmon, &mi)) return olc::rcode::FAIL; - vWindowSize = { mi.rcMonitor.right, mi.rcMonitor.bottom }; - vTopLeft.x = 0; - vTopLeft.y = 0; - } - - // Keep client size as requested - RECT rWndRect = { 0, 0, vWindowSize.x, vWindowSize.y }; - AdjustWindowRectEx(&rWndRect, dwStyle, FALSE, dwExStyle); - int width = rWndRect.right - rWndRect.left; - int height = rWndRect.bottom - rWndRect.top; - - olc_hWnd = CreateWindowEx(dwExStyle, olcT("OLC_PIXEL_GAME_ENGINE"), olcT(""), dwStyle, - vTopLeft.x, vTopLeft.y, width, height, NULL, NULL, GetModuleHandle(nullptr), this); - - // Create Keyboard Mapping - mapKeys[0x00] = Key::NONE; - mapKeys[0x41] = Key::A; mapKeys[0x42] = Key::B; mapKeys[0x43] = Key::C; mapKeys[0x44] = Key::D; mapKeys[0x45] = Key::E; - mapKeys[0x46] = Key::F; mapKeys[0x47] = Key::G; mapKeys[0x48] = Key::H; mapKeys[0x49] = Key::I; mapKeys[0x4A] = Key::J; - mapKeys[0x4B] = Key::K; mapKeys[0x4C] = Key::L; mapKeys[0x4D] = Key::M; mapKeys[0x4E] = Key::N; mapKeys[0x4F] = Key::O; - mapKeys[0x50] = Key::P; mapKeys[0x51] = Key::Q; mapKeys[0x52] = Key::R; mapKeys[0x53] = Key::S; mapKeys[0x54] = Key::T; - mapKeys[0x55] = Key::U; mapKeys[0x56] = Key::V; mapKeys[0x57] = Key::W; mapKeys[0x58] = Key::X; mapKeys[0x59] = Key::Y; - mapKeys[0x5A] = Key::Z; - - mapKeys[VK_F1] = Key::F1; mapKeys[VK_F2] = Key::F2; mapKeys[VK_F3] = Key::F3; mapKeys[VK_F4] = Key::F4; - mapKeys[VK_F5] = Key::F5; mapKeys[VK_F6] = Key::F6; mapKeys[VK_F7] = Key::F7; mapKeys[VK_F8] = Key::F8; - mapKeys[VK_F9] = Key::F9; mapKeys[VK_F10] = Key::F10; mapKeys[VK_F11] = Key::F11; mapKeys[VK_F12] = Key::F12; - - mapKeys[VK_DOWN] = Key::DOWN; mapKeys[VK_LEFT] = Key::LEFT; mapKeys[VK_RIGHT] = Key::RIGHT; mapKeys[VK_UP] = Key::UP; - //mapKeys[VK_RETURN] = Key::ENTER;// mapKeys[VK_RETURN] = Key::RETURN; - - mapKeys[VK_BACK] = Key::BACK; mapKeys[VK_ESCAPE] = Key::ESCAPE; mapKeys[VK_RETURN] = Key::ENTER; mapKeys[VK_PAUSE] = Key::PAUSE; - mapKeys[VK_SCROLL] = Key::SCROLL; mapKeys[VK_TAB] = Key::TAB; mapKeys[VK_DELETE] = Key::DEL; mapKeys[VK_HOME] = Key::HOME; - mapKeys[VK_END] = Key::END; mapKeys[VK_PRIOR] = Key::PGUP; mapKeys[VK_NEXT] = Key::PGDN; mapKeys[VK_INSERT] = Key::INS; - mapKeys[VK_SHIFT] = Key::SHIFT; mapKeys[VK_CONTROL] = Key::CTRL; - mapKeys[VK_SPACE] = Key::SPACE; - - mapKeys[0x30] = Key::K0; mapKeys[0x31] = Key::K1; mapKeys[0x32] = Key::K2; mapKeys[0x33] = Key::K3; mapKeys[0x34] = Key::K4; - mapKeys[0x35] = Key::K5; mapKeys[0x36] = Key::K6; mapKeys[0x37] = Key::K7; mapKeys[0x38] = Key::K8; mapKeys[0x39] = Key::K9; - - mapKeys[VK_NUMPAD0] = Key::NP0; mapKeys[VK_NUMPAD1] = Key::NP1; mapKeys[VK_NUMPAD2] = Key::NP2; mapKeys[VK_NUMPAD3] = Key::NP3; mapKeys[VK_NUMPAD4] = Key::NP4; - mapKeys[VK_NUMPAD5] = Key::NP5; mapKeys[VK_NUMPAD6] = Key::NP6; mapKeys[VK_NUMPAD7] = Key::NP7; mapKeys[VK_NUMPAD8] = Key::NP8; mapKeys[VK_NUMPAD9] = Key::NP9; - mapKeys[VK_MULTIPLY] = Key::NP_MUL; mapKeys[VK_ADD] = Key::NP_ADD; mapKeys[VK_DIVIDE] = Key::NP_DIV; mapKeys[VK_SUBTRACT] = Key::NP_SUB; mapKeys[VK_DECIMAL] = Key::NP_DECIMAL; - - // Thanks scripticuk - mapKeys[VK_OEM_1] = Key::OEM_1; // On US and UK keyboards this is the ';:' key - mapKeys[VK_OEM_2] = Key::OEM_2; // On US and UK keyboards this is the '/?' key - mapKeys[VK_OEM_3] = Key::OEM_3; // On US keyboard this is the '~' key - mapKeys[VK_OEM_4] = Key::OEM_4; // On US and UK keyboards this is the '[{' key - mapKeys[VK_OEM_5] = Key::OEM_5; // On US keyboard this is '\|' key. - mapKeys[VK_OEM_6] = Key::OEM_6; // On US and UK keyboards this is the ']}' key - mapKeys[VK_OEM_7] = Key::OEM_7; // On US keyboard this is the single/double quote key. On UK, this is the single quote/@ symbol key - mapKeys[VK_OEM_8] = Key::OEM_8; // miscellaneous characters. Varies by keyboard - mapKeys[VK_OEM_PLUS] = Key::EQUALS; // the '+' key on any keyboard - mapKeys[VK_OEM_COMMA] = Key::COMMA; // the comma key on any keyboard - mapKeys[VK_OEM_MINUS] = Key::MINUS; // the minus key on any keyboard - mapKeys[VK_OEM_PERIOD] = Key::PERIOD; // the period key on any keyboard - mapKeys[VK_CAPITAL] = Key::CAPS_LOCK; - return olc::OK; - } - - virtual olc::rcode SetWindowTitle(const std::string& s) override - { -#ifdef UNICODE - SetWindowText(olc_hWnd, ConvertS2W(s).c_str()); -#else - SetWindowText(olc_hWnd, s.c_str()); -#endif - return olc::OK; - } - - virtual olc::rcode StartSystemEventLoop() override - { - MSG msg; - while (GetMessage(&msg, NULL, 0, 0) > 0) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return olc::OK; - } - - virtual olc::rcode HandleSystemEvent() override { return olc::rcode::FAIL; } - - // Windows Event Handler - this is statically connected to the windows event system - static LRESULT CALLBACK olc_WindowEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - switch (uMsg) - { - case WM_MOUSEMOVE: - { - // Thanks @ForAbby (Discord) - uint16_t x = lParam & 0xFFFF; uint16_t y = (lParam >> 16) & 0xFFFF; - int16_t ix = *(int16_t*)&x; int16_t iy = *(int16_t*)&y; - ptrPGE->olc_UpdateMouse(ix, iy); - return 0; - } - case WM_SIZE: ptrPGE->olc_UpdateWindowSize(lParam & 0xFFFF, (lParam >> 16) & 0xFFFF); return 0; - case WM_MOUSEWHEEL: ptrPGE->olc_UpdateMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam)); return 0; - case WM_MOUSELEAVE: ptrPGE->olc_UpdateMouseFocus(false); return 0; - case WM_SETFOCUS: ptrPGE->olc_UpdateKeyFocus(true); return 0; - case WM_KILLFOCUS: ptrPGE->olc_UpdateKeyFocus(false); return 0; - case WM_KEYDOWN: ptrPGE->olc_UpdateKeyState(mapKeys[wParam], true); return 0; - case WM_KEYUP: ptrPGE->olc_UpdateKeyState(mapKeys[wParam], false); return 0; - case WM_SYSKEYDOWN: ptrPGE->olc_UpdateKeyState(mapKeys[wParam], true); return 0; - case WM_SYSKEYUP: ptrPGE->olc_UpdateKeyState(mapKeys[wParam], false); return 0; - case WM_LBUTTONDOWN:ptrPGE->olc_UpdateMouseState(0, true); return 0; - case WM_LBUTTONUP: ptrPGE->olc_UpdateMouseState(0, false); return 0; - case WM_RBUTTONDOWN:ptrPGE->olc_UpdateMouseState(1, true); return 0; - case WM_RBUTTONUP: ptrPGE->olc_UpdateMouseState(1, false); return 0; - case WM_MBUTTONDOWN:ptrPGE->olc_UpdateMouseState(2, true); return 0; - case WM_MBUTTONUP: ptrPGE->olc_UpdateMouseState(2, false); return 0; - case WM_CLOSE: ptrPGE->olc_Terminate(); return 0; - case WM_DESTROY: PostQuitMessage(0); DestroyWindow(hWnd); return 0; - } - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | END PLATFORM: MICROSOFT WINDOWS XP, VISTA, 7, 8, 10 | -// O------------------------------------------------------------------------------O -#pragma endregion - -#pragma region platform_linux -// O------------------------------------------------------------------------------O -// | START PLATFORM: LINUX | -// O------------------------------------------------------------------------------O -#if defined(OLC_PLATFORM_X11) -namespace olc -{ - class Platform_Linux : public olc::Platform - { - private: - X11::Display* olc_Display = nullptr; - X11::Window olc_WindowRoot; - X11::Window olc_Window; - X11::XVisualInfo* olc_VisualInfo; - X11::Colormap olc_ColourMap; - X11::XSetWindowAttributes olc_SetWindowAttribs; - - public: - virtual olc::rcode ApplicationStartUp() override - { - return olc::rcode::OK; - } - - virtual olc::rcode ApplicationCleanUp() override - { - XDestroyWindow(olc_Display, olc_Window); - return olc::rcode::OK; - } - - virtual olc::rcode ThreadStartUp() override - { - return olc::rcode::OK; - } - - virtual olc::rcode ThreadCleanUp() override - { - renderer->DestroyDevice(); - return olc::OK; - } - - virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) override - { - if (renderer->CreateDevice({ olc_Display, &olc_Window, olc_VisualInfo }, bFullScreen, bEnableVSYNC) == olc::rcode::OK) - { - renderer->UpdateViewport(vViewPos, vViewSize); - return olc::rcode::OK; - } - else - return olc::rcode::FAIL; - } - - virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) override - { - using namespace X11; - XInitThreads(); - - // Grab the deafult display and window - olc_Display = XOpenDisplay(NULL); - olc_WindowRoot = DefaultRootWindow(olc_Display); - - // Based on the display capabilities, configure the appearance of the window - GLint olc_GLAttribs[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; - olc_VisualInfo = glXChooseVisual(olc_Display, 0, olc_GLAttribs); - olc_ColourMap = XCreateColormap(olc_Display, olc_WindowRoot, olc_VisualInfo->visual, AllocNone); - olc_SetWindowAttribs.colormap = olc_ColourMap; - - // Register which events we are interested in receiving - olc_SetWindowAttribs.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | StructureNotifyMask; - - // Create the window - olc_Window = XCreateWindow(olc_Display, olc_WindowRoot, vWindowPos.x, vWindowPos.y, - vWindowSize.x, vWindowSize.y, - 0, olc_VisualInfo->depth, InputOutput, olc_VisualInfo->visual, - CWColormap | CWEventMask, &olc_SetWindowAttribs); - - Atom wmDelete = XInternAtom(olc_Display, "WM_DELETE_WINDOW", true); - XSetWMProtocols(olc_Display, olc_Window, &wmDelete, 1); - - XMapWindow(olc_Display, olc_Window); - XStoreName(olc_Display, olc_Window, "OneLoneCoder.com - Pixel Game Engine"); - - if (bFullScreen) // Thanks DragonEye, again :D - { - Atom wm_state; - Atom fullscreen; - wm_state = XInternAtom(olc_Display, "_NET_WM_STATE", False); - fullscreen = XInternAtom(olc_Display, "_NET_WM_STATE_FULLSCREEN", False); - XEvent xev{ 0 }; - xev.type = ClientMessage; - xev.xclient.window = olc_Window; - xev.xclient.message_type = wm_state; - xev.xclient.format = 32; - xev.xclient.data.l[0] = (bFullScreen ? 1 : 0); // the action (0: off, 1: on, 2: toggle) - xev.xclient.data.l[1] = fullscreen; // first property to alter - xev.xclient.data.l[2] = 0; // second property to alter - xev.xclient.data.l[3] = 0; // source indication - XMapWindow(olc_Display, olc_Window); - XSendEvent(olc_Display, DefaultRootWindow(olc_Display), False, - SubstructureRedirectMask | SubstructureNotifyMask, &xev); - XFlush(olc_Display); - XWindowAttributes gwa; - XGetWindowAttributes(olc_Display, olc_Window, &gwa); - vWindowSize.x = gwa.width; - vWindowSize.y = gwa.height; - } - - // Create Keyboard Mapping - mapKeys[0x00] = Key::NONE; - mapKeys[0x61] = Key::A; mapKeys[0x62] = Key::B; mapKeys[0x63] = Key::C; mapKeys[0x64] = Key::D; mapKeys[0x65] = Key::E; - mapKeys[0x66] = Key::F; mapKeys[0x67] = Key::G; mapKeys[0x68] = Key::H; mapKeys[0x69] = Key::I; mapKeys[0x6A] = Key::J; - mapKeys[0x6B] = Key::K; mapKeys[0x6C] = Key::L; mapKeys[0x6D] = Key::M; mapKeys[0x6E] = Key::N; mapKeys[0x6F] = Key::O; - mapKeys[0x70] = Key::P; mapKeys[0x71] = Key::Q; mapKeys[0x72] = Key::R; mapKeys[0x73] = Key::S; mapKeys[0x74] = Key::T; - mapKeys[0x75] = Key::U; mapKeys[0x76] = Key::V; mapKeys[0x77] = Key::W; mapKeys[0x78] = Key::X; mapKeys[0x79] = Key::Y; - mapKeys[0x7A] = Key::Z; - - mapKeys[XK_F1] = Key::F1; mapKeys[XK_F2] = Key::F2; mapKeys[XK_F3] = Key::F3; mapKeys[XK_F4] = Key::F4; - mapKeys[XK_F5] = Key::F5; mapKeys[XK_F6] = Key::F6; mapKeys[XK_F7] = Key::F7; mapKeys[XK_F8] = Key::F8; - mapKeys[XK_F9] = Key::F9; mapKeys[XK_F10] = Key::F10; mapKeys[XK_F11] = Key::F11; mapKeys[XK_F12] = Key::F12; - - mapKeys[XK_Down] = Key::DOWN; mapKeys[XK_Left] = Key::LEFT; mapKeys[XK_Right] = Key::RIGHT; mapKeys[XK_Up] = Key::UP; - mapKeys[XK_KP_Enter] = Key::ENTER; mapKeys[XK_Return] = Key::ENTER; - - mapKeys[XK_BackSpace] = Key::BACK; mapKeys[XK_Escape] = Key::ESCAPE; mapKeys[XK_Linefeed] = Key::ENTER; mapKeys[XK_Pause] = Key::PAUSE; - mapKeys[XK_Scroll_Lock] = Key::SCROLL; mapKeys[XK_Tab] = Key::TAB; mapKeys[XK_Delete] = Key::DEL; mapKeys[XK_Home] = Key::HOME; - mapKeys[XK_End] = Key::END; mapKeys[XK_Page_Up] = Key::PGUP; mapKeys[XK_Page_Down] = Key::PGDN; mapKeys[XK_Insert] = Key::INS; - mapKeys[XK_Shift_L] = Key::SHIFT; mapKeys[XK_Shift_R] = Key::SHIFT; mapKeys[XK_Control_L] = Key::CTRL; mapKeys[XK_Control_R] = Key::CTRL; - mapKeys[XK_space] = Key::SPACE; mapKeys[XK_period] = Key::PERIOD; - - mapKeys[XK_0] = Key::K0; mapKeys[XK_1] = Key::K1; mapKeys[XK_2] = Key::K2; mapKeys[XK_3] = Key::K3; mapKeys[XK_4] = Key::K4; - mapKeys[XK_5] = Key::K5; mapKeys[XK_6] = Key::K6; mapKeys[XK_7] = Key::K7; mapKeys[XK_8] = Key::K8; mapKeys[XK_9] = Key::K9; - - mapKeys[XK_KP_0] = Key::NP0; mapKeys[XK_KP_1] = Key::NP1; mapKeys[XK_KP_2] = Key::NP2; mapKeys[XK_KP_3] = Key::NP3; mapKeys[XK_KP_4] = Key::NP4; - mapKeys[XK_KP_5] = Key::NP5; mapKeys[XK_KP_6] = Key::NP6; mapKeys[XK_KP_7] = Key::NP7; mapKeys[XK_KP_8] = Key::NP8; mapKeys[XK_KP_9] = Key::NP9; - mapKeys[XK_KP_Multiply] = Key::NP_MUL; mapKeys[XK_KP_Add] = Key::NP_ADD; mapKeys[XK_KP_Divide] = Key::NP_DIV; mapKeys[XK_KP_Subtract] = Key::NP_SUB; mapKeys[XK_KP_Decimal] = Key::NP_DECIMAL; - - // These keys vary depending on the keyboard. I've included comments for US and UK keyboard layouts - mapKeys[XK_semicolon] = Key::OEM_1; // On US and UK keyboards this is the ';:' key - mapKeys[XK_slash] = Key::OEM_2; // On US and UK keyboards this is the '/?' key - mapKeys[XK_asciitilde] = Key::OEM_3; // On US keyboard this is the '~' key - mapKeys[XK_bracketleft] = Key::OEM_4; // On US and UK keyboards this is the '[{' key - mapKeys[XK_backslash] = Key::OEM_5; // On US keyboard this is '\|' key. - mapKeys[XK_bracketright] = Key::OEM_6; // On US and UK keyboards this is the ']}' key - mapKeys[XK_apostrophe] = Key::OEM_7; // On US keyboard this is the single/double quote key. On UK, this is the single quote/@ symbol key - mapKeys[XK_numbersign] = Key::OEM_8; // miscellaneous characters. Varies by keyboard. I believe this to be the '#~' key on UK keyboards - mapKeys[XK_equal] = Key::EQUALS; // the '+' key on any keyboard - mapKeys[XK_comma] = Key::COMMA; // the comma key on any keyboard - mapKeys[XK_minus] = Key::MINUS; // the minus key on any keyboard - - mapKeys[XK_Caps_Lock] = Key::CAPS_LOCK; - - return olc::OK; - } - - virtual olc::rcode SetWindowTitle(const std::string& s) override - { - X11::XStoreName(olc_Display, olc_Window, s.c_str()); - return olc::OK; - } - - virtual olc::rcode StartSystemEventLoop() override - { - return olc::OK; - } - - virtual olc::rcode HandleSystemEvent() override - { - using namespace X11; - // Handle Xlib Message Loop - we do this in the - // same thread that OpenGL was created so we dont - // need to worry too much about multithreading with X11 - XEvent xev; - while (XPending(olc_Display)) - { - XNextEvent(olc_Display, &xev); - if (xev.type == Expose) - { - XWindowAttributes gwa; - XGetWindowAttributes(olc_Display, olc_Window, &gwa); - ptrPGE->olc_UpdateWindowSize(gwa.width, gwa.height); - } - else if (xev.type == ConfigureNotify) - { - XConfigureEvent xce = xev.xconfigure; - ptrPGE->olc_UpdateWindowSize(xce.width, xce.height); - } - else if (xev.type == KeyPress) - { - KeySym sym = XLookupKeysym(&xev.xkey, 0); - ptrPGE->olc_UpdateKeyState(mapKeys[sym], true); - XKeyEvent* e = (XKeyEvent*)&xev; // Because DragonEye loves numpads - XLookupString(e, NULL, 0, &sym, NULL); - ptrPGE->olc_UpdateKeyState(mapKeys[sym], true); - } - else if (xev.type == KeyRelease) - { - KeySym sym = XLookupKeysym(&xev.xkey, 0); - ptrPGE->olc_UpdateKeyState(mapKeys[sym], false); - XKeyEvent* e = (XKeyEvent*)&xev; - XLookupString(e, NULL, 0, &sym, NULL); - ptrPGE->olc_UpdateKeyState(mapKeys[sym], false); - } - else if (xev.type == ButtonPress) - { - switch (xev.xbutton.button) - { - case 1: ptrPGE->olc_UpdateMouseState(0, true); break; - case 2: ptrPGE->olc_UpdateMouseState(2, true); break; - case 3: ptrPGE->olc_UpdateMouseState(1, true); break; - case 4: ptrPGE->olc_UpdateMouseWheel(120); break; - case 5: ptrPGE->olc_UpdateMouseWheel(-120); break; - default: break; - } - } - else if (xev.type == ButtonRelease) - { - switch (xev.xbutton.button) - { - case 1: ptrPGE->olc_UpdateMouseState(0, false); break; - case 2: ptrPGE->olc_UpdateMouseState(2, false); break; - case 3: ptrPGE->olc_UpdateMouseState(1, false); break; - default: break; - } - } - else if (xev.type == MotionNotify) - { - ptrPGE->olc_UpdateMouse(xev.xmotion.x, xev.xmotion.y); - } - else if (xev.type == FocusIn) - { - ptrPGE->olc_UpdateKeyFocus(true); - } - else if (xev.type == FocusOut) - { - ptrPGE->olc_UpdateKeyFocus(false); - } - else if (xev.type == ClientMessage) - { - ptrPGE->olc_Terminate(); - } - } - return olc::OK; - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | END PLATFORM: LINUX | -// O------------------------------------------------------------------------------O -#pragma endregion - -#pragma region platform_glut -// O------------------------------------------------------------------------------O -// | START PLATFORM: GLUT (used to make it simple for Apple) | -// O------------------------------------------------------------------------------O -// -// VERY IMPORTANT!!! The Apple port was originally created by @Mumflr (discord) -// and the repo for the development of this project can be found here: -// https://github.com/MumflrFumperdink/olcPGEMac which contains maccy goodness -// and support on how to setup your build environment. -// -// "MASSIVE MASSIVE THANKS TO MUMFLR" - Javidx9 -#if defined(OLC_PLATFORM_GLUT) -namespace olc { - - class Platform_GLUT : public olc::Platform - { - public: - static std::atomic* bActiveRef; - - virtual olc::rcode ApplicationStartUp() override { - return olc::rcode::OK; - } - - virtual olc::rcode ApplicationCleanUp() override - { - return olc::rcode::OK; - } - - virtual olc::rcode ThreadStartUp() override - { - return olc::rcode::OK; - } - - virtual olc::rcode ThreadCleanUp() override - { - renderer->DestroyDevice(); - return olc::OK; - } - - virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) override - { - if (renderer->CreateDevice({}, bFullScreen, bEnableVSYNC) == olc::rcode::OK) - { - renderer->UpdateViewport(vViewPos, vViewSize); - return olc::rcode::OK; - } - else - return olc::rcode::FAIL; - } - - static void ExitMainLoop() { - if (!ptrPGE->OnUserDestroy()) { - *bActiveRef = true; - return; - } - platform->ThreadCleanUp(); - platform->ApplicationCleanUp(); - exit(0); - } - -#if defined(__APPLE__) - static void scrollWheelUpdate(id selff, SEL _sel, id theEvent) { - static const SEL deltaYSel = sel_registerName("deltaY"); - -#if defined(__aarch64__) // Thanks ruarq! - double deltaY = ((double (*)(id, SEL))objc_msgSend)(theEvent, deltaYSel); -#else - double deltaY = ((double (*)(id, SEL))objc_msgSend_fpret)(theEvent, deltaYSel); -#endif - - for (int i = 0; i < abs(deltaY); i++) { - if (deltaY > 0) { - ptrPGE->olc_UpdateMouseWheel(-1); - } - else if (deltaY < 0) { - ptrPGE->olc_UpdateMouseWheel(1); - } - } - } -#endif - static void ThreadFunct() { -#if defined(__APPLE__) - static bool hasEnabledCocoa = false; - if (!hasEnabledCocoa) { - // Objective-C Wizardry - Class NSApplicationClass = objc_getClass("NSApplication"); - - // NSApp = [NSApplication sharedApplication] - SEL sharedApplicationSel = sel_registerName("sharedApplication"); - id NSApp = ((id(*)(Class, SEL))objc_msgSend)(NSApplicationClass, sharedApplicationSel); - // window = [NSApp mainWindow] - SEL mainWindowSel = sel_registerName("mainWindow"); - id window = ((id(*)(id, SEL))objc_msgSend)(NSApp, mainWindowSel); - - // [window setStyleMask: NSWindowStyleMaskClosable | ~NSWindowStyleMaskResizable] - SEL setStyleMaskSel = sel_registerName("setStyleMask:"); - ((void (*)(id, SEL, NSUInteger))objc_msgSend)(window, setStyleMaskSel, 7); - - hasEnabledCocoa = true; - } -#endif - if (!*bActiveRef) { - ExitMainLoop(); - return; - } - glutPostRedisplay(); - } - - static void DrawFunct() { - ptrPGE->olc_CoreUpdate(); - } - - virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) override - { -#if defined(__APPLE__) - Class GLUTViewClass = objc_getClass("GLUTView"); - - SEL scrollWheelSel = sel_registerName("scrollWheel:"); - bool resultAddMethod = class_addMethod(GLUTViewClass, scrollWheelSel, (IMP)scrollWheelUpdate, "v@:@"); - assert(resultAddMethod); -#endif - - renderer->PrepareDevice(); - - if (bFullScreen) - { - vWindowSize.x = glutGet(GLUT_SCREEN_WIDTH); - vWindowSize.y = glutGet(GLUT_SCREEN_HEIGHT); - glutFullScreen(); - } - else - { - if (vWindowSize.x > glutGet(GLUT_SCREEN_WIDTH) || vWindowSize.y > glutGet(GLUT_SCREEN_HEIGHT)) - { - perror("ERROR: The specified window dimensions do not fit on your screen\n"); - return olc::FAIL; - } - glutReshapeWindow(vWindowSize.x, vWindowSize.y - 1); - } - - // Create Keyboard Mapping - mapKeys[0x00] = Key::NONE; - mapKeys['A'] = Key::A; mapKeys['B'] = Key::B; mapKeys['C'] = Key::C; mapKeys['D'] = Key::D; mapKeys['E'] = Key::E; - mapKeys['F'] = Key::F; mapKeys['G'] = Key::G; mapKeys['H'] = Key::H; mapKeys['I'] = Key::I; mapKeys['J'] = Key::J; - mapKeys['K'] = Key::K; mapKeys['L'] = Key::L; mapKeys['M'] = Key::M; mapKeys['N'] = Key::N; mapKeys['O'] = Key::O; - mapKeys['P'] = Key::P; mapKeys['Q'] = Key::Q; mapKeys['R'] = Key::R; mapKeys['S'] = Key::S; mapKeys['T'] = Key::T; - mapKeys['U'] = Key::U; mapKeys['V'] = Key::V; mapKeys['W'] = Key::W; mapKeys['X'] = Key::X; mapKeys['Y'] = Key::Y; - mapKeys['Z'] = Key::Z; - - mapKeys[GLUT_KEY_F1] = Key::F1; mapKeys[GLUT_KEY_F2] = Key::F2; mapKeys[GLUT_KEY_F3] = Key::F3; mapKeys[GLUT_KEY_F4] = Key::F4; - mapKeys[GLUT_KEY_F5] = Key::F5; mapKeys[GLUT_KEY_F6] = Key::F6; mapKeys[GLUT_KEY_F7] = Key::F7; mapKeys[GLUT_KEY_F8] = Key::F8; - mapKeys[GLUT_KEY_F9] = Key::F9; mapKeys[GLUT_KEY_F10] = Key::F10; mapKeys[GLUT_KEY_F11] = Key::F11; mapKeys[GLUT_KEY_F12] = Key::F12; - - mapKeys[GLUT_KEY_DOWN] = Key::DOWN; mapKeys[GLUT_KEY_LEFT] = Key::LEFT; mapKeys[GLUT_KEY_RIGHT] = Key::RIGHT; mapKeys[GLUT_KEY_UP] = Key::UP; - mapKeys[13] = Key::ENTER; - - mapKeys[127] = Key::BACK; mapKeys[27] = Key::ESCAPE; - mapKeys[9] = Key::TAB; mapKeys[GLUT_KEY_HOME] = Key::HOME; - mapKeys[GLUT_KEY_END] = Key::END; mapKeys[GLUT_KEY_PAGE_UP] = Key::PGUP; mapKeys[GLUT_KEY_PAGE_DOWN] = Key::PGDN; mapKeys[GLUT_KEY_INSERT] = Key::INS; - mapKeys[32] = Key::SPACE; mapKeys[46] = Key::PERIOD; - - mapKeys[48] = Key::K0; mapKeys[49] = Key::K1; mapKeys[50] = Key::K2; mapKeys[51] = Key::K3; mapKeys[52] = Key::K4; - mapKeys[53] = Key::K5; mapKeys[54] = Key::K6; mapKeys[55] = Key::K7; mapKeys[56] = Key::K8; mapKeys[57] = Key::K9; - - // NOTE: MISSING KEYS :O - - glutKeyboardFunc([](unsigned char key, int x, int y) -> void { - switch (glutGetModifiers()) { - case 0: //This is when there are no modifiers - if ('a' <= key && key <= 'z') key -= 32; - break; - case GLUT_ACTIVE_SHIFT: - ptrPGE->olc_UpdateKeyState(Key::SHIFT, true); - break; - case GLUT_ACTIVE_CTRL: - if ('a' <= key && key <= 'z') key -= 32; - ptrPGE->olc_UpdateKeyState(Key::CTRL, true); - break; - case GLUT_ACTIVE_ALT: - if ('a' <= key && key <= 'z') key -= 32; - break; - } - - if (mapKeys[key]) - ptrPGE->olc_UpdateKeyState(mapKeys[key], true); - }); - - glutKeyboardUpFunc([](unsigned char key, int x, int y) -> void { - switch (glutGetModifiers()) { - case 0: //This is when there are no modifiers - if ('a' <= key && key <= 'z') key -= 32; - break; - case GLUT_ACTIVE_SHIFT: - ptrPGE->olc_UpdateKeyState(Key::SHIFT, false); - break; - case GLUT_ACTIVE_CTRL: - if ('a' <= key && key <= 'z') key -= 32; - ptrPGE->olc_UpdateKeyState(Key::CTRL, false); - break; - case GLUT_ACTIVE_ALT: - if ('a' <= key && key <= 'z') key -= 32; - //No ALT in PGE - break; - } - - if (mapKeys[key]) - ptrPGE->olc_UpdateKeyState(mapKeys[key], false); - }); - - //Special keys - glutSpecialFunc([](int key, int x, int y) -> void { - if (mapKeys[key]) - ptrPGE->olc_UpdateKeyState(mapKeys[key], true); - }); - - glutSpecialUpFunc([](int key, int x, int y) -> void { - if (mapKeys[key]) - ptrPGE->olc_UpdateKeyState(mapKeys[key], false); - }); - - glutMouseFunc([](int button, int state, int x, int y) -> void { - switch (button) { - case GLUT_LEFT_BUTTON: - if (state == GLUT_UP) ptrPGE->olc_UpdateMouseState(0, false); - else if (state == GLUT_DOWN) ptrPGE->olc_UpdateMouseState(0, true); - break; - case GLUT_MIDDLE_BUTTON: - if (state == GLUT_UP) ptrPGE->olc_UpdateMouseState(2, false); - else if (state == GLUT_DOWN) ptrPGE->olc_UpdateMouseState(2, true); - break; - case GLUT_RIGHT_BUTTON: - if (state == GLUT_UP) ptrPGE->olc_UpdateMouseState(1, false); - else if (state == GLUT_DOWN) ptrPGE->olc_UpdateMouseState(1, true); - break; - } - }); - - auto mouseMoveCall = [](int x, int y) -> void { - ptrPGE->olc_UpdateMouse(x, y); - }; - - glutMotionFunc(mouseMoveCall); - glutPassiveMotionFunc(mouseMoveCall); - - glutEntryFunc([](int state) -> void { - if (state == GLUT_ENTERED) ptrPGE->olc_UpdateKeyFocus(true); - else if (state == GLUT_LEFT) ptrPGE->olc_UpdateKeyFocus(false); - }); - - glutDisplayFunc(DrawFunct); - glutIdleFunc(ThreadFunct); - - return olc::OK; - } - - virtual olc::rcode SetWindowTitle(const std::string& s) override - { - glutSetWindowTitle(s.c_str()); - return olc::OK; - } - - virtual olc::rcode StartSystemEventLoop() override { - glutMainLoop(); - return olc::OK; - } - - virtual olc::rcode HandleSystemEvent() override - { - return olc::OK; - } - }; - - std::atomic* Platform_GLUT::bActiveRef{ nullptr }; - - //Custom Start - olc::rcode PixelGameEngine::Start() - { - if (platform->ApplicationStartUp() != olc::OK) return olc::FAIL; - - // Construct the window - if (platform->CreateWindowPane({ 30,30 }, vWindowSize, bFullScreen) != olc::OK) return olc::FAIL; - olc_UpdateWindowSize(vWindowSize.x, vWindowSize.y); - - if (platform->ThreadStartUp() == olc::FAIL) return olc::FAIL; - olc_PrepareEngine(); - if (!OnUserCreate()) return olc::FAIL; - Platform_GLUT::bActiveRef = &bAtomActive; - glutWMCloseFunc(Platform_GLUT::ExitMainLoop); - bAtomActive = true; - platform->StartSystemEventLoop(); - - //This code will not even be run but why not - if (platform->ApplicationCleanUp() != olc::OK) return olc::FAIL; - - return olc::OK; - } -} - -#endif -// O------------------------------------------------------------------------------O -// | END PLATFORM: GLUT | -// O------------------------------------------------------------------------------O -#pragma endregion - - -#pragma region platform_emscripten -// O------------------------------------------------------------------------------O -// | START PLATFORM: Emscripten - Totally Game Changing... | -// O------------------------------------------------------------------------------O - -// -// Firstly a big mega thank you to members of the OLC Community for sorting this -// out. Making a browser compatible version has been a priority for quite some -// time, but I lacked the expertise to do it. This awesome feature is possible -// because a group of former strangers got together and formed friendships over -// their shared passion for code. If anything demonstrates how powerful helping -// each other can be, it's this. - Javidx9 - -// Emscripten Platform: MaGetzUb, Moros1138, Slavka, Dandistine, Gorbit99, Bispoo -// also: Ishidex, Gusgo99, SlicEnDicE, Alexio - - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - -#include -#include - -extern "C" -{ - EMSCRIPTEN_KEEPALIVE inline int olc_OnPageUnload() - { olc::platform->ApplicationCleanUp(); return 0; } -} - -namespace olc -{ - class Platform_Emscripten : public olc::Platform - { - public: - - virtual olc::rcode ApplicationStartUp() override - { return olc::rcode::OK; } - - virtual olc::rcode ApplicationCleanUp() override - { ThreadCleanUp(); return olc::rcode::OK; } - - virtual olc::rcode ThreadStartUp() override - { return olc::rcode::OK; } - - virtual olc::rcode ThreadCleanUp() override - { renderer->DestroyDevice(); return olc::OK; } - - virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) override - { - if (renderer->CreateDevice({}, bFullScreen, bEnableVSYNC) == olc::rcode::OK) - { - renderer->UpdateViewport(vViewPos, vViewSize); - return olc::rcode::OK; - } - else - return olc::rcode::FAIL; - } - - virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) override - { - emscripten_set_canvas_element_size("#canvas", vWindowSize.x, vWindowSize.y); - - mapKeys[DOM_PK_UNKNOWN] = Key::NONE; - mapKeys[DOM_PK_A] = Key::A; mapKeys[DOM_PK_B] = Key::B; mapKeys[DOM_PK_C] = Key::C; mapKeys[DOM_PK_D] = Key::D; - mapKeys[DOM_PK_E] = Key::E; mapKeys[DOM_PK_F] = Key::F; mapKeys[DOM_PK_G] = Key::G; mapKeys[DOM_PK_H] = Key::H; - mapKeys[DOM_PK_I] = Key::I; mapKeys[DOM_PK_J] = Key::J; mapKeys[DOM_PK_K] = Key::K; mapKeys[DOM_PK_L] = Key::L; - mapKeys[DOM_PK_M] = Key::M; mapKeys[DOM_PK_N] = Key::N; mapKeys[DOM_PK_O] = Key::O; mapKeys[DOM_PK_P] = Key::P; - mapKeys[DOM_PK_Q] = Key::Q; mapKeys[DOM_PK_R] = Key::R; mapKeys[DOM_PK_S] = Key::S; mapKeys[DOM_PK_T] = Key::T; - mapKeys[DOM_PK_U] = Key::U; mapKeys[DOM_PK_V] = Key::V; mapKeys[DOM_PK_W] = Key::W; mapKeys[DOM_PK_X] = Key::X; - mapKeys[DOM_PK_Y] = Key::Y; mapKeys[DOM_PK_Z] = Key::Z; - mapKeys[DOM_PK_0] = Key::K0; mapKeys[DOM_PK_1] = Key::K1; mapKeys[DOM_PK_2] = Key::K2; - mapKeys[DOM_PK_3] = Key::K3; mapKeys[DOM_PK_4] = Key::K4; mapKeys[DOM_PK_5] = Key::K5; - mapKeys[DOM_PK_6] = Key::K6; mapKeys[DOM_PK_7] = Key::K7; mapKeys[DOM_PK_8] = Key::K8; - mapKeys[DOM_PK_9] = Key::K9; - mapKeys[DOM_PK_F1] = Key::F1; mapKeys[DOM_PK_F2] = Key::F2; mapKeys[DOM_PK_F3] = Key::F3; mapKeys[DOM_PK_F4] = Key::F4; - mapKeys[DOM_PK_F5] = Key::F5; mapKeys[DOM_PK_F6] = Key::F6; mapKeys[DOM_PK_F7] = Key::F7; mapKeys[DOM_PK_F8] = Key::F8; - mapKeys[DOM_PK_F9] = Key::F9; mapKeys[DOM_PK_F10] = Key::F10; mapKeys[DOM_PK_F11] = Key::F11; mapKeys[DOM_PK_F12] = Key::F12; - mapKeys[DOM_PK_ARROW_UP] = Key::UP; mapKeys[DOM_PK_ARROW_DOWN] = Key::DOWN; - mapKeys[DOM_PK_ARROW_LEFT] = Key::LEFT; mapKeys[DOM_PK_ARROW_RIGHT] = Key::RIGHT; - mapKeys[DOM_PK_SPACE] = Key::SPACE; mapKeys[DOM_PK_TAB] = Key::TAB; - mapKeys[DOM_PK_SHIFT_LEFT] = Key::SHIFT; mapKeys[DOM_PK_SHIFT_RIGHT] = Key::SHIFT; - mapKeys[DOM_PK_CONTROL_LEFT] = Key::CTRL; mapKeys[DOM_PK_CONTROL_RIGHT] = Key::CTRL; - mapKeys[DOM_PK_INSERT] = Key::INS; mapKeys[DOM_PK_DELETE] = Key::DEL; mapKeys[DOM_PK_HOME] = Key::HOME; - mapKeys[DOM_PK_END] = Key::END; mapKeys[DOM_PK_PAGE_UP] = Key::PGUP; mapKeys[DOM_PK_PAGE_DOWN] = Key::PGDN; - mapKeys[DOM_PK_BACKSPACE] = Key::BACK; mapKeys[DOM_PK_ESCAPE] = Key::ESCAPE; - mapKeys[DOM_PK_ENTER] = Key::ENTER; mapKeys[DOM_PK_NUMPAD_EQUAL] = Key::EQUALS; - mapKeys[DOM_PK_NUMPAD_ENTER] = Key::ENTER; mapKeys[DOM_PK_PAUSE] = Key::PAUSE; - mapKeys[DOM_PK_SCROLL_LOCK] = Key::SCROLL; - mapKeys[DOM_PK_NUMPAD_0] = Key::NP0; mapKeys[DOM_PK_NUMPAD_1] = Key::NP1; mapKeys[DOM_PK_NUMPAD_2] = Key::NP2; - mapKeys[DOM_PK_NUMPAD_3] = Key::NP3; mapKeys[DOM_PK_NUMPAD_4] = Key::NP4; mapKeys[DOM_PK_NUMPAD_5] = Key::NP5; - mapKeys[DOM_PK_NUMPAD_6] = Key::NP6; mapKeys[DOM_PK_NUMPAD_7] = Key::NP7; mapKeys[DOM_PK_NUMPAD_8] = Key::NP8; - mapKeys[DOM_PK_NUMPAD_9] = Key::NP9; - mapKeys[DOM_PK_NUMPAD_MULTIPLY] = Key::NP_MUL; mapKeys[DOM_PK_NUMPAD_DIVIDE] = Key::NP_DIV; - mapKeys[DOM_PK_NUMPAD_ADD] = Key::NP_ADD; mapKeys[DOM_PK_NUMPAD_SUBTRACT] = Key::NP_SUB; - mapKeys[DOM_PK_NUMPAD_DECIMAL] = Key::NP_DECIMAL; - mapKeys[DOM_PK_PERIOD] = Key::PERIOD; mapKeys[DOM_PK_EQUAL] = Key::EQUALS; - mapKeys[DOM_PK_COMMA] = Key::COMMA; mapKeys[DOM_PK_MINUS] = Key::MINUS; - mapKeys[DOM_PK_CAPS_LOCK] = Key::CAPS_LOCK; - mapKeys[DOM_PK_SEMICOLON] = Key::OEM_1; mapKeys[DOM_PK_SLASH] = Key::OEM_2; mapKeys[DOM_PK_BACKQUOTE] = Key::OEM_3; - mapKeys[DOM_PK_BRACKET_LEFT] = Key::OEM_4; mapKeys[DOM_PK_BACKSLASH] = Key::OEM_5; mapKeys[DOM_PK_BRACKET_RIGHT] = Key::OEM_6; - mapKeys[DOM_PK_QUOTE] = Key::OEM_7; mapKeys[DOM_PK_BACKSLASH] = Key::OEM_8; - - // Keyboard Callbacks - emscripten_set_keydown_callback("#canvas", 0, 1, keyboard_callback); - emscripten_set_keyup_callback("#canvas", 0, 1, keyboard_callback); - - // Mouse Callbacks - emscripten_set_wheel_callback("#canvas", 0, 1, wheel_callback); - emscripten_set_mousedown_callback("#canvas", 0, 1, mouse_callback); - emscripten_set_mouseup_callback("#canvas", 0, 1, mouse_callback); - emscripten_set_mousemove_callback("#canvas", 0, 1, mouse_callback); - - // Touch Callbacks - emscripten_set_touchstart_callback("#canvas", 0, 1, touch_callback); - emscripten_set_touchmove_callback("#canvas", 0, 1, touch_callback); - emscripten_set_touchend_callback("#canvas", 0, 1, touch_callback); - - // Canvas Focus Callbacks - emscripten_set_blur_callback("#canvas", 0, 1, focus_callback); - emscripten_set_focus_callback("#canvas", 0, 1, focus_callback); - -#pragma warning disable format - EM_ASM( window.onunload = Module._olc_OnPageUnload; ); - - // IMPORTANT! - Sorry About This... - // - // In order to handle certain browser based events, such as resizing and - // going to full screen, we have to effectively inject code into the container - // running the PGE. Yes, I vomited about 11 times too when the others were - // convincing me this is the future. Well, this isnt the future, and if it - // were to be, I want no part of what must be a miserable distopian free - // for all of anarchic code injection to get rudimentary events like "Resize()". - // - // Wake up people! Of course theres a spoon. There has to be to keep feeding - // the giant web baby. - - - // Fullscreen and Resize Observers - EM_ASM({ - - // cache for reuse - Module._olc_EmscriptenShellCss = "width: 100%; height: 70vh; margin-left: auto; margin-right: auto;"; - - // width / height = aspect ratio - Module._olc_WindowAspectRatio = $0 / $1; - Module.canvas.parentNode.addEventListener("resize", function(e) { - - if (e.defaultPrevented) { e.stopPropagation(); return; } - var viewWidth = e.detail.width; - var viewHeight = e.detail.width / Module._olc_WindowAspectRatio; - if (viewHeight > e.detail.height) - { - viewHeight = e.detail.height; - viewWidth = e.detail.height * Module._olc_WindowAspectRatio; - } - - if (Module.canvas.parentNode.className == 'emscripten_border') - Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss + " width: " + viewWidth.toString() + "px; height: " + viewHeight.toString() + "px;"; - - Module.canvas.setAttribute("width", viewWidth); - Module.canvas.setAttribute("height", viewHeight); - - if (document.fullscreenElement != null) - { - var top = (e.detail.height - viewHeight) / 2; - var left = (e.detail.width - viewWidth) / 2; - Module.canvas.style.position = "fixed"; - Module.canvas.style.top = top.toString() + "px"; - Module.canvas.style.left = left.toString() + "px"; - Module.canvas.style.width = ""; - Module.canvas.style.height = ""; - } - - // trigger PGE update - Module._olc_PGE_UpdateWindowSize(viewWidth, viewHeight); - // this is really only needed when enter/exiting fullscreen - Module.canvas.focus(); - // prevent this event from ever affecting the document beyond this element - e.stopPropagation(); - }); - - // helper function to prevent repeating the same code everywhere - Module._olc_ResizeCanvas = function() - { - // yes, we still have to wait, sigh.. - setTimeout(function() - { - // if default template, stretch width as well - if (Module.canvas.parentNode.className == 'emscripten_border') - Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss; - - // override it's styling so we can get it's stretched size - Module.canvas.style.cssText = "width: 100%; height: 100%; outline: none;"; - - // setup custom resize event - var resizeEvent = new CustomEvent('resize', - { - detail: { - width: Module.canvas.clientWidth, - height : Module.canvas.clientHeight - }, - bubbles : true, - cancelable : true - }); - - // trigger custom resize event on canvas element - Module.canvas.dispatchEvent(resizeEvent); - }, 50); - }; - - - // Disable Refresh Gesture on mobile - document.body.style.cssText += " overscroll-behavior-y: contain;"; - - if (Module.canvas.parentNode.className == 'emscripten_border') - { - // force body to have no margin in emscripten's minimal shell - document.body.style.margin = "0"; - Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss; - } - - Module._olc_ResizeCanvas(); - - // observe and react to resizing of the container element - var resizeObserver = new ResizeObserver(function(entries) {Module._olc_ResizeCanvas();}).observe(Module.canvas.parentNode); - - // observe and react to changes that occur when entering/exiting fullscreen - var mutationObserver = new MutationObserver(function(mutationsList, observer) - { - // a change has occurred, let's check them out! - for (var i = 0; i < mutationsList.length; i++) - { - // cycle through all of the newly added elements - for (var j = 0; j < mutationsList[i].addedNodes.length; j++) - { - // if this element is a our canvas, trigger resize - if (mutationsList[i].addedNodes[j].id == 'canvas') - Module._olc_ResizeCanvas(); - } - } - }).observe(Module.canvas.parentNode, - { - attributes: false, - childList : true, - subtree : false - }); - - // add resize listener on window - window.addEventListener("resize", function(e) { Module._olc_ResizeCanvas(); }); - - }, vWindowSize.x, vWindowSize.y); // Fullscreen and Resize Observers -#pragma warning restore format - return olc::rcode::OK; - } - - // Interface PGE's UpdateWindowSize, for use in Javascript - void UpdateWindowSize(int width, int height) - { - ptrPGE->olc_UpdateWindowSize(width, height); - } - - //TY Gorbit - static EM_BOOL focus_callback(int eventType, const EmscriptenFocusEvent* focusEvent, void* userData) - { - if (eventType == EMSCRIPTEN_EVENT_BLUR) - { - ptrPGE->olc_UpdateKeyFocus(false); - ptrPGE->olc_UpdateMouseFocus(false); - } - else if (eventType == EMSCRIPTEN_EVENT_FOCUS) - { - ptrPGE->olc_UpdateKeyFocus(true); - ptrPGE->olc_UpdateMouseFocus(true); - } - - return 0; - } - - //TY Moros - static EM_BOOL keyboard_callback(int eventType, const EmscriptenKeyboardEvent* e, void* userData) - { - if (eventType == EMSCRIPTEN_EVENT_KEYDOWN) - ptrPGE->olc_UpdateKeyState(mapKeys[emscripten_compute_dom_pk_code(e->code)], true); - - // THANK GOD!! for this compute function. And thanks Dandistine for pointing it out! - if (eventType == EMSCRIPTEN_EVENT_KEYUP) - ptrPGE->olc_UpdateKeyState(mapKeys[emscripten_compute_dom_pk_code(e->code)], false); - - //Consume keyboard events so that keys like F1 and F5 don't do weird things - return EM_TRUE; - } - - //TY Moros - static EM_BOOL wheel_callback(int eventType, const EmscriptenWheelEvent* e, void* userData) - { - if (eventType == EMSCRIPTEN_EVENT_WHEEL) - ptrPGE->olc_UpdateMouseWheel(-1 * e->deltaY); - - return EM_TRUE; - } - - //TY Bispoo - static EM_BOOL touch_callback(int eventType, const EmscriptenTouchEvent* e, void* userData) - { - // Move - if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) - { - ptrPGE->olc_UpdateMouse(e->touches->targetX, e->touches->targetY); - } - - // Start - if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) - { - ptrPGE->olc_UpdateMouse(e->touches->targetX, e->touches->targetY); - ptrPGE->olc_UpdateMouseState(0, true); - } - - // End - if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) - { - ptrPGE->olc_UpdateMouseState(0, false); - } - - return EM_TRUE; - } - - //TY Moros - static EM_BOOL mouse_callback(int eventType, const EmscriptenMouseEvent* e, void* userData) - { - //Mouse Movement - if (eventType == EMSCRIPTEN_EVENT_MOUSEMOVE) - ptrPGE->olc_UpdateMouse(e->targetX, e->targetY); - - - //Mouse button press - if (e->button == 0) // left click - { - if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN) - ptrPGE->olc_UpdateMouseState(0, true); - else if (eventType == EMSCRIPTEN_EVENT_MOUSEUP) - ptrPGE->olc_UpdateMouseState(0, false); - } - - if (e->button == 2) // right click - { - if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN) - ptrPGE->olc_UpdateMouseState(1, true); - else if (eventType == EMSCRIPTEN_EVENT_MOUSEUP) - ptrPGE->olc_UpdateMouseState(1, false); - - } - - if (e->button == 1) // middle click - { - if (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN) - ptrPGE->olc_UpdateMouseState(2, true); - else if (eventType == EMSCRIPTEN_EVENT_MOUSEUP) - ptrPGE->olc_UpdateMouseState(2, false); - - //at the moment only middle mouse needs to consume events. - return EM_TRUE; - } - - return EM_FALSE; - } - - - virtual olc::rcode SetWindowTitle(const std::string& s) override - { emscripten_set_window_title(s.c_str()); return olc::OK; } - - virtual olc::rcode StartSystemEventLoop() override - { return olc::OK; } - - virtual olc::rcode HandleSystemEvent() override - { return olc::OK; } - - static void MainLoop() - { - olc::Platform::ptrPGE->olc_CoreUpdate(); - if (!ptrPGE->olc_IsRunning()) - { - if (ptrPGE->OnUserDestroy()) - { - emscripten_cancel_main_loop(); - platform->ApplicationCleanUp(); - } - else - { - ptrPGE->olc_Reanimate(); - } - } - } - }; - - //Emscripten needs a special Start function - //Much of this is usually done in EngineThread, but that isn't used here - olc::rcode PixelGameEngine::Start() - { - if (platform->ApplicationStartUp() != olc::OK) return olc::FAIL; - - // Construct the window - if (platform->CreateWindowPane({ 30,30 }, vWindowSize, bFullScreen) != olc::OK) return olc::FAIL; - olc_UpdateWindowSize(vWindowSize.x, vWindowSize.y); - - // Some implementations may form an event loop here - if (platform->ThreadStartUp() == olc::FAIL) return olc::FAIL; - - // Do engine context specific initialisation - olc_PrepareEngine(); - - // Consider the "thread" started - bAtomActive = true; - - // Create user resources as part of this thread - for (auto& ext : vExtensions) ext->OnBeforeUserCreate(); - if (!OnUserCreate()) bAtomActive = false; - for (auto& ext : vExtensions) ext->OnAfterUserCreate(); - - platform->StartSystemEventLoop(); - - //This causes a heap memory corruption in Emscripten for some reason - //Platform_Emscripten::bActiveRef = &bAtomActive; - emscripten_set_main_loop(&Platform_Emscripten::MainLoop, 0, 1); - - // Wait for thread to be exited - if (platform->ApplicationCleanUp() != olc::OK) return olc::FAIL; - return olc::OK; - } -} - -extern "C" -{ - EMSCRIPTEN_KEEPALIVE inline void olc_PGE_UpdateWindowSize(int width, int height) - { - emscripten_set_canvas_element_size("#canvas", width, height); - // Thanks slavka - ((olc::Platform_Emscripten*)olc::platform.get())->UpdateWindowSize(width, height); - } -} - -#endif -// O------------------------------------------------------------------------------O -// | END PLATFORM: Emscripten | -// O------------------------------------------------------------------------------O -#pragma endregion - - -#endif // Headless - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine Auto-Configuration | -// O------------------------------------------------------------------------------O -#pragma region pge_config -namespace olc -{ - void PixelGameEngine::olc_ConfigureSystem() - { - -#if !defined(OLC_PGE_HEADLESS) - -#if defined(OLC_IMAGE_GDI) - olc::Sprite::loader = std::make_unique(); -#endif - -#if defined(OLC_IMAGE_LIBPNG) - olc::Sprite::loader = std::make_unique(); -#endif - -#if defined(OLC_IMAGE_STB) - olc::Sprite::loader = std::make_unique(); -#endif - -#if defined(OLC_IMAGE_CUSTOM_EX) - olc::Sprite::loader = std::make_unique(); -#endif - - - - -#if defined(OLC_PLATFORM_WINAPI) - platform = std::make_unique(); -#endif - -#if defined(OLC_PLATFORM_X11) - platform = std::make_unique(); -#endif - -#if defined(OLC_PLATFORM_GLUT) - platform = std::make_unique(); -#endif - -#if defined(OLC_PLATFORM_EMSCRIPTEN) - platform = std::make_unique(); -#endif - -#if defined(OLC_PLATFORM_CUSTOM_EX) - platform = std::make_unique(); -#endif - - - -#if defined(OLC_GFX_OPENGL10) - renderer = std::make_unique(); -#endif - -#if defined(OLC_GFX_OPENGL33) - renderer = std::make_unique(); -#endif - -#if defined(OLC_GFX_OPENGLES2) - renderer = std::make_unique(); -#endif - -#if defined(OLC_GFX_DIRECTX10) - renderer = std::make_unique(); -#endif - -#if defined(OLC_GFX_DIRECTX11) - renderer = std::make_unique(); -#endif - -#if defined(OLC_GFX_CUSTOM_EX) - renderer = std::make_unique(); -#endif - - // Associate components with PGE instance - platform->ptrPGE = this; - renderer->ptrPGE = this; -#else - olc::Sprite::loader = nullptr; - platform = nullptr; - renderer = nullptr; -#endif - } -} - -#pragma endregion - -#endif // End OLC_PGE_APPLICATION - -// O------------------------------------------------------------------------------O -// | END OF OLC_PGE_APPLICATION | -// O------------------------------------------------------------------------------O -