From 8098d3ce5420afb8f121f0a3dd31ae68934ce447 Mon Sep 17 00:00:00 2001 From: Ahmed Al-kharusi <63564296+Ahmed-alkharusi@users.noreply.github.com> Date: Fri, 14 Aug 2020 11:55:48 +0400 Subject: [PATCH] Delete olcPixelGameEngine.h --- Source code/Project1/olcPixelGameEngine.h | 3584 --------------------- 1 file changed, 3584 deletions(-) delete mode 100644 Source code/Project1/olcPixelGameEngine.h diff --git a/Source code/Project1/olcPixelGameEngine.h b/Source code/Project1/olcPixelGameEngine.h deleted file mode 100644 index aba51fa..0000000 --- a/Source code/Project1/olcPixelGameEngine.h +++ /dev/null @@ -1,3584 +0,0 @@ -/* - olcPixelGameEngine.h - - +-------------------------------------------------------------+ - | OneLoneCoder Pixel Game Engine v2.07 | - | "What do you need? Pixels... Lots of Pixels..." - javidx9 | - +-------------------------------------------------------------+ - - What is this? - ~~~~~~~~~~~~~ - olc::PixelGameEngine is a single file, cross platform graphics and userinput - framework used for games, visualisations, algorithm exploration and learning. - It was developed by YouTuber "javidx9" as an assistive tool for many of his - videos. The goal of this project is to provide high speed graphics with - minimal project setup complexity, to encourage new programmers, younger people, - and anyone else that wants to make fun things. - - However, olc::PixelGameEngine is not a toy! It is a powerful and fast utility - capable of delivering high resolution, high speed, high quality applications - which behave the same way regardless of the operating system or platform. - - This file provides the core utility set of the olc::PixelGameEngine, including - window creation, keyboard/mouse input, main game thread, timing, pixel drawing - routines, image/sprite loading and drawing routines, and a bunch of utility - types to make rapid development of games/visualisations possible. - - - License (OLC-3) - ~~~~~~~~~~~~~~~ - - Copyright 2018 - 2020 OneLoneCoder.com - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - 1. Redistributions or derivations of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions or derivative works in binary form must reproduce the above - copyright notice. This list of conditions and the following disclaimer must be - reproduced in the documentation and/or other materials provided with the distribution. - - 3. Neither the name of the copyright holder nor the names of its contributors may - be used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Links - ~~~~~ - YouTube: https://www.youtube.com/javidx9 - https://www.youtube.com/javidx9extra - Discord: https://discord.gg/WhwHUMV - Twitter: https://www.twitter.com/javidx9 - Twitch: https://www.twitch.tv/javidx9 - GitHub: https://www.github.com/onelonecoder - Homepage: https://www.onelonecoder.com - Patreon: https://www.patreon.com/javidx9 - Community: https://community.onelonecoder.com - - Compiling in Linux - ~~~~~~~~~~~~~~~~~~ - You will need a modern C++ compiler, so update yours! - To compile use the command: - - g++ -o YourProgName YourSource.cpp -lX11 -lGL -lpthread -lpng -lstdc++fs -std=c++17 - - On some Linux configurations, the frame rate is locked to the refresh - rate of the monitor. This engine tries to unlock it but may not be - able to, in which case try launching your program like this: - - vblank_mode=0 ./YourProgName - - - Compiling in Code::Blocks on Windows - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Well I wont judge you, but make sure your Code::Blocks installation - is really up to date - you may even consider updating your C++ toolchain - to use MinGW32-W64. - - Guide for installing recent GCC for Windows: - https://www.msys2.org/ - Guide for configuring code::blocks: - https://solarianprogrammer.com/2019/11/05/install-gcc-windows/ - https://solarianprogrammer.com/2019/11/16/install-codeblocks-gcc-windows-build-c-cpp-fortran-programs/ - - Add these libraries to "Linker Options": - user32 gdi32 opengl32 gdiplus Shlwapi stdc++fs - - Set these compiler options: -std=c++17 - - Ports - ~~~~~ - olc::PixelGameEngine has been ported and tested with varying degrees of - success to: WinXP, Win7, Win8, Win10, Various Linux, Raspberry Pi, - Chromebook, Playstation Portable (PSP) and Nintendo Switch. If you are - interested in the details of these ports, come and visit the Discord! - - Thanks - ~~~~~~ - I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim, IProgramInCPP - JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice, dandistine - Ralakus, Gorbit99, raoul, joshinils, benedani, Moros1138, Alexio, SaladinAkara & MagetzUb - for advice, ideas and testing, and I'd like to extend my appreciation to the - 174K YouTube followers, 70+ Patreons and 8K Discord server members who give me - the motivation to keep going with all this :D - - Significant Contributors: @Moros1138, @SaladinAkara, @MaGetzUb, @slavka, @Dragoneye & @Gorbit99 - - Special thanks to those who bring gifts! - GnarGnarHead.......Domina - Gorbit99...........Bastion, Ori & The Blind Forest, Terraria - Marti Morta........Gris - Danicron...........Terraria - SaladinAkara.......Aseprite - AlterEgo...........Final Fantasy XII - The Zodiac Age - - Special thanks to my Patreons too - I wont name you on here, but I've - certainly enjoyed my tea and flapjacks :D - - Author - ~~~~~~ - David Barr, aka javidx9, ŠOneLoneCoder 2018, 2019, 2020 - - 2.01: Made renderer and platform static for multifile projects - 2.02: Added Decal destructor, optimised Pixel constructor - 2.03: Added FreeBSD flags, Added DrawStringDecal() - 2.04: Windows Full-Screen bug fixed - 2.05: +DrawPartialWarpedDecal() - draws a warped decal from a subset image - +DrawPartialRotatedDecal() - draws a rotated decal from a subset image - 2.06: +GetTextSize() - returns area occupied by multiline string - +GetWindowSize() - returns actual window size - +GetElapsedTime() - returns last calculated fElapsedTime - +GetWindowMouse() - returns actual mouse location in window - +DrawExplicitDecal() - bow-chikka-bow-bow - +DrawPartialDecal(pos, size) - draws a partial decal to specified area - +FillRectDecal() - draws a flat shaded rectangle as a decal - +GradientFillRectDecal() - draws a rectangle, with unique colour corners - +Modified DrawCircle() & FillCircle() - Thanks IanM-Matrix1 (#PR121) - +Gone someway to appeasing pedants - 2.07: +GetPixelSize() - returns user specified pixel size - +GetScreenPixelSize() - returns actual size in monitor pixels - +Pixel Cohesion Mode (flag in Construct()) - disallows arbitrary window scaling - +Working VSYNC in Windows windowed application - now much smoother - +Added string conversion for olc::vectors - +Added comparator operators for olc::vectors - +Added DestroyWindow() on windows platforms for serial PGE launches - +Added GetMousePos() to stop TarriestPython whinging -*/ - -////////////////////////////////////////////////////////////////////////////////////////// - - -// O------------------------------------------------------------------------------O -// | Example "Hello World" Program (main.cpp) | -// O------------------------------------------------------------------------------O -/* - -#define OLC_PGE_APPLICATION -#include "olcPixelGameEngine.h" - -// Override base class with your custom functionality -class Example : public olc::PixelGameEngine -{ -public: - Example() - { - // Name you application - sAppName = "Example"; - } - -public: - bool OnUserCreate() override - { - // Called once at the start, so create things here - return true; - } - - bool OnUserUpdate(float fElapsedTime) override - { - // called once per frame, draws random coloured pixels - for (int x = 0; x < ScreenWidth(); x++) - for (int y = 0; y < ScreenHeight(); y++) - Draw(x, y, olc::Pixel(rand() % 256, rand() % 256, rand()% 256)); - return true; - } -}; - -int main() -{ - Example demo; - if (demo.Construct(256, 240, 4, 4)) - demo.Start(); - return 0; -} - -*/ - -#ifndef OLC_PGE_DEF -#define OLC_PGE_DEF - -// O------------------------------------------------------------------------------O -// | STANDARD INCLUDES | -// O------------------------------------------------------------------------------O -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// O------------------------------------------------------------------------------O -// | COMPILER CONFIGURATION ODDITIES | -// O------------------------------------------------------------------------------O -#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__) -#if __cplusplus >= 201703L -#undef USE_EXPERIMENTAL_FS -#endif -#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) - - -#if !defined(OLC_GFX_OPENGL33) && !defined(OLC_GFX_DIRECTX10) -#define OLC_GFX_OPENGL10 -#endif - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine INTERFACE DECLARATION | -// O------------------------------------------------------------------------------O -namespace olc -{ - class PixelGameEngine; - - // Pixel Game Engine Advanced Configuration - constexpr uint8_t nMouseButtons = 5; - constexpr uint8_t nDefaultAlpha = 0xFF; - constexpr uint32_t nDefaultPixel = (nDefaultAlpha << 24); - 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); - bool operator==(const Pixel& p) const; - bool operator!=(const Pixel& p) const; - }; - - Pixel PixelF(float red, float green, float blue, float alpha = 1.0f); - - - - // 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); - - 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 - }; - - - - // 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) { } - T mag() { return T(std::sqrt(x * x + y * y)); } - T mag2() { return x * x + y * y; } - v2d_generic norm() { T r = 1 / mag(); return v2d_generic(x * r, y * r); } - v2d_generic perp() { return v2d_generic(-y, x); } - T dot(const v2d_generic& rhs) { return this->x * rhs.x + this->y * rhs.y; } - T cross(const v2d_generic& rhs) { 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; } - 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)); - } - - typedef v2d_generic vi2d; - typedef v2d_generic vu2d; - typedef v2d_generic vf2d; - typedef v2d_generic vd2d; -#endif - - - - // 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::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); - }; - - - - // 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(); - - public: - olc::rcode LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack = nullptr); - olc::rcode LoadFromPGESprFile(const std::string& sImageFile, olc::ResourcePack* pack = nullptr); - olc::rcode SaveToPGESprFile(const std::string& sImageFile); - - public: - int32_t width = 0; - int32_t height = 0; - enum Mode { NORMAL, PERIODIC }; - 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(); - Pixel* pColData = nullptr; - Mode modeSample = Mode::NORMAL; - }; - - // O------------------------------------------------------------------------------O - // | olc::Decal - A GPU resident storage of an olc::Sprite | - // O------------------------------------------------------------------------------O - class Decal - { - public: - Decal(olc::Sprite* spr); - virtual ~Decal(); - void Update(); - - public: // But dont touch - int32_t id = -1; - olc::Sprite* sprite = nullptr; - olc::vf2d vUVScale = { 1.0f, 1.0f }; - }; - - // O------------------------------------------------------------------------------O - // | olc::Renderable - Convenience class to keep a sprite and decal together | - // O------------------------------------------------------------------------------O - class Renderable - { - public: - Renderable() = default; - olc::rcode Load(const std::string& sFile, ResourcePack* pack = nullptr); - void Create(uint32_t width, uint32_t height); - 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; - olc::vf2d pos[4] = { { 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f} }; - olc::vf2d uv[4] = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; - float w[4] = { 1, 1, 1, 1 }; - olc::Pixel tint[4] = { olc::WHITE, olc::WHITE, olc::WHITE, olc::WHITE };; - }; - - struct DecalTriangleInstance - { - olc::vf2d points[3]; - olc::vf2d texture[3]; - olc::Pixel colours[3]; - olc::Decal* decal = nullptr; - }; - - struct LayerDesc - { - olc::vf2d vOffset = { 0, 0 }; - olc::vf2d vScale = { 1, 1 }; - bool bShow = false; - bool bUpdate = false; - olc::Sprite* pDrawTarget = nullptr; - uint32_t nResID = 0; - std::vector vecDecalInstance; - olc::Pixel tint = olc::WHITE; - std::function funcHook = nullptr; - }; - - class Renderer - { - public: - 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 DrawLayerQuad(const olc::vf2d& offset, const olc::vf2d& scale, const olc::Pixel tint) = 0; - virtual void DrawDecalQuad(const olc::DecalInstance& decal) = 0; - virtual uint32_t CreateTexture(const uint32_t width, const uint32_t height) = 0; - virtual void UpdateTexture(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 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; - }; - - 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(); - - public: // Hardware Interfaces - // Returns true if window is currently in focus - bool IsFocused(); - // Get the state of a specific keyboard button - HWButton GetKey(Key k); - // Get the state of a specific mouse button - HWButton GetMouse(uint32_t b); - // 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(); - // 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; - - public: // Utility - // Returns the width of the screen in "pixels" - int32_t ScreenWidth(); - // Returns the height of the screen in "pixels" - int32_t ScreenHeight(); - // Returns the width of the currently selected drawing target in "pixels" - int32_t GetDrawTargetWidth(); - // Returns the height of the currently selected drawing target in "pixels" - int32_t GetDrawTargetHeight(); - // Returns the currently active draw target - olc::Sprite* GetDrawTarget(); - // 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(); - // Gets last update of elapsed time - const 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); - 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 form between 0.0f to 1.0f; - void SetPixelBlend(float fBlend); - // Offset texels by sub-pixel amount (advanced, do not use) - [[deprecated]] - void SetSubPixelOffset(float ox, float oy); - - - 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 well in my defencelocation (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); - - // Decal Quad functions - - // 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); - // 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 }); - // 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 a single line of text - 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); - // Clears entire draw target to Pixel - void Clear(Pixel p); - // Clears the rendering back buffer - void ClearBuffer(Pixel p, bool bDepth = true); - - - public: // Branding - std::string sAppName; - - private: // Inner mysterious workings - 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; - Sprite* fontSprite = nullptr; - Decal* fontDecal = nullptr; - Sprite* pDefaultDrawTarget = nullptr; - std::vector vLayers; - uint8_t nTargetLayer = 0; - uint32_t nLastFPS = 0; - bool bPixelCohesion = false; - std::function funcPixelMode; - std::chrono::time_point m_tp1, m_tp2; - - // 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(); - - // At the very end of this file, chooses which - // components to compile - void olc_ConfigureSystem(); - - // 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(); - - // 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 }; - - friend class PGEX; - }; - - - - // O------------------------------------------------------------------------------O - // | PGE EXTENSION BASE CLASS - Permits access to PGE functions from extension | - // O------------------------------------------------------------------------------O - class PGEX - { - friend class olc::PixelGameEngine; - protected: - static PixelGameEngine* pge; - }; -} - -#endif // OLC_PGE_DEF - - - - -/* - Object Oriented Mode - ~~~~~~~~~~~~~~~~~~~~ - - If the olcPixelGameEngine.h is called from several sources it can cause - multiple definitions of objects. To prevent this, ONLY ONE of the pathways - to including this file must have OLC_PGE_APPLICATION defined before it. This prevents - the definitions being duplicated. - - If all else fails, create a file called "olcPixelGameEngine.cpp" with the following - two lines. Then you can just #include "olcPixelGameEngine.h" as normal without worrying - about defining things. Dont forget to include that cpp file as part of your build! - - #define OLC_PGE_APPLICATION - #include "olcPixelGameEngine.h" - -*/ - - -// 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 -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 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)); - } - - // O------------------------------------------------------------------------------O - // | olc::Sprite IMPLEMENTATION | - // O------------------------------------------------------------------------------O - Sprite::Sprite() - { - pColData = nullptr; width = 0; height = 0; - } - - Sprite::Sprite(const std::string& sImageFile, olc::ResourcePack* pack) - { - LoadFromFile(sImageFile, pack); - } - - Sprite::Sprite(int32_t w, int32_t h) - { - if (pColData) delete[] pColData; - width = w; height = h; - pColData = new Pixel[width * height]; - for (int32_t i = 0; i < width * height; i++) - pColData[i] = Pixel(); - } - - Sprite::~Sprite() - { - if (pColData) delete[] pColData; - } - - - olc::rcode Sprite::LoadFromPGESprFile(const std::string& sImageFile, olc::ResourcePack* pack) - { - if (pColData) delete[] pColData; - auto ReadData = [&](std::istream& is) - { - is.read((char*)&width, sizeof(int32_t)); - is.read((char*)&height, sizeof(int32_t)); - pColData = new Pixel[width * height]; - is.read((char*)pColData, (size_t)width * (size_t)height * sizeof(uint32_t)); - }; - - // These are essentially Memory Surfaces represented by olc::Sprite - // which load very fast, but are completely uncompressed - if (pack == nullptr) - { - std::ifstream ifs; - ifs.open(sImageFile, std::ifstream::binary); - if (ifs.is_open()) - { - ReadData(ifs); - return olc::OK; - } - else - return olc::FAIL; - } - else - { - ResourceBuffer rb = pack->GetFileBuffer(sImageFile); - std::istream is(&rb); - ReadData(is); - return olc::OK; - } - return olc::FAIL; - } - - olc::rcode Sprite::SaveToPGESprFile(const std::string& sImageFile) - { - if (pColData == nullptr) return olc::FAIL; - - std::ofstream ofs; - ofs.open(sImageFile, std::ifstream::binary); - if (ofs.is_open()) - { - ofs.write((char*)&width, sizeof(int32_t)); - ofs.write((char*)&height, sizeof(int32_t)); - ofs.write((char*)pColData, (size_t)width * (size_t)height * sizeof(uint32_t)); - ofs.close(); - return olc::OK; - } - - return olc::FAIL; - } - - 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 - { - return pColData[abs(y % height) * width + abs(x % width)]; - } - } - - 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; - } - - - // O------------------------------------------------------------------------------O - // | olc::Decal IMPLEMENTATION | - // O------------------------------------------------------------------------------O - Decal::Decal(olc::Sprite* spr) - { - id = -1; - if (spr == nullptr) return; - sprite = spr; - id = renderer->CreateTexture(sprite->width, sprite->height); - Update(); - } - - 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); - } - - Decal::~Decal() - { - if (id != -1) - { - renderer->DeleteTexture(id); - id = -1; - } - } - - void Renderable::Create(uint32_t width, uint32_t height) - { - pSprite = std::make_unique(width, height); - pDecal = std::make_unique(pSprite.get()); - } - - olc::rcode Renderable::Load(const std::string& sFile, ResourcePack* pack) - { - pSprite = std::make_unique(); - if (pSprite->LoadFromFile(sFile, pack)) - { - pDecal = std::make_unique(pSprite.get()); - 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 }; - for (auto& layer : vLayers) - { - delete layer.pDrawTarget; // Erase existing layer sprites - layer.pDrawTarget = new Sprite(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; - } - } - - void PixelGameEngine::SetDrawTarget(uint8_t layer) - { - if (layer < vLayers.size()) - { - pDrawTarget = vLayers[layer].pDrawTarget; - vLayers[layer].bUpdate = true; - 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 = new olc::Sprite(vScreenSize.x, vScreenSize.y); - ld.nResID = renderer->CreateTexture(vScreenSize.x, vScreenSize.y); - renderer->UpdateTexture(ld.nResID, ld.pDrawTarget); - vLayers.push_back(ld); - return uint32_t(vLayers.size()) - 1; - } - - Sprite* PixelGameEngine::GetDrawTarget() - { - return pDrawTarget; - } - - int32_t PixelGameEngine::GetDrawTargetWidth() - { - if (pDrawTarget) - return pDrawTarget->width; - else - return 0; - } - - int32_t PixelGameEngine::GetDrawTargetHeight() - { - if (pDrawTarget) - return pDrawTarget->height; - else - return 0; - } - - uint32_t PixelGameEngine::GetFPS() - { - return nLastFPS; - } - - bool PixelGameEngine::IsFocused() - { - return bHasInputFocus; - } - - HWButton PixelGameEngine::GetKey(Key k) - { - return pKeyboardState[k]; - } - - HWButton PixelGameEngine::GetMouse(uint32_t b) - { - 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() - { - return nMouseWheelDelta; - } - - int32_t PixelGameEngine::ScreenWidth() - { - return vScreenSize.x; - } - - int32_t PixelGameEngine::ScreenHeight() - { - return vScreenSize.y; - } - - const 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::SetSubPixelOffset(float ox, float oy) - { - //vSubPixelOffset.x = ox * vPixel.x; - //vSubPixelOffset.y = oy * vPixel.y; - } - - 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; }; - - // 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); - } - - 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::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) * -1.0f - }; - - olc::vf2d vScreenSpaceDim = - { - vScreenSpacePos.x + (2.0f * source_size.x * vInvScreenSize.x) * scale.x, - vScreenSpacePos.y - (2.0f * source_size.y * vInvScreenSize.y) * scale.y - }; - - DecalInstance di; di.decal = decal; di.tint[0] = tint; - - di.pos[0] = { vScreenSpacePos.x, vScreenSpacePos.y }; - di.pos[1] = { vScreenSpacePos.x, vScreenSpaceDim.y }; - di.pos[2] = { vScreenSpaceDim.x, vScreenSpaceDim.y }; - di.pos[3] = { vScreenSpaceDim.x, vScreenSpacePos.y }; - - olc::vf2d uvtl = source_pos * decal->vUVScale; - olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale); - di.uv[0] = { uvtl.x, uvtl.y }; di.uv[1] = { uvtl.x, uvbr.y }; - di.uv[2] = { uvbr.x, uvbr.y }; di.uv[3] = { uvbr.x, uvtl.y }; - 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.decal = decal; di.tint[0] = tint; - - di.pos[0] = { vScreenSpacePos.x, vScreenSpacePos.y }; - di.pos[1] = { vScreenSpacePos.x, vScreenSpaceDim.y }; - di.pos[2] = { vScreenSpaceDim.x, vScreenSpaceDim.y }; - di.pos[3] = { vScreenSpaceDim.x, vScreenSpacePos.y }; - - olc::vf2d uvtl = source_pos * decal->vUVScale; - olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale); - di.uv[0] = { uvtl.x, uvtl.y }; di.uv[1] = { uvtl.x, uvbr.y }; - di.uv[2] = { uvbr.x, uvbr.y }; di.uv[3] = { uvbr.x, uvtl.y }; - 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.tint[0] = tint; - di.pos[0] = { vScreenSpacePos.x, vScreenSpacePos.y }; - di.pos[1] = { vScreenSpacePos.x, vScreenSpaceDim.y }; - di.pos[2] = { vScreenSpaceDim.x, vScreenSpaceDim.y }; - di.pos[3] = { vScreenSpaceDim.x, vScreenSpacePos.y }; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - 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.tint[0] = tint; - 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; - } - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col) - { - DecalInstance di; - for (int i = 0; i < 4; 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]; - } - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - - void PixelGameEngine::FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col) - { - 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 = { {col, col, col, col} }; - DrawExplicitDecal(nullptr, points.data(), uvs.data(), cols.data()); - } - - 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()); - } - - - 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.tint[0] = tint; - 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[0] = { uvtl.x, uvtl.y }; di.uv[1] = { uvtl.x, uvbr.y }; - di.uv[2] = { uvbr.x, uvbr.y }; di.uv[3] = { uvbr.x, uvtl.y }; - - 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.decal = decal; - di.tint[0] = tint; - 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[0] = { uvtl.x, uvtl.y }; di.uv[1] = { uvtl.x, uvbr.y }; - di.uv[2] = { uvbr.x, uvbr.y }; di.uv[3] = { 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 }; - } - 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.decal = decal; - di.tint[0] = tint; - 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 }; - } - 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 - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialDecal(pos + spos, fontDecal, { float(ox) * 8.0f, float(oy) * 8.0f }, { 8.0f, 8.0f }, scale, col); - spos.x += 8.0f * scale.x; - } - } - } - - 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 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 (col.a != 255) SetPixelMode(Pixel::ALPHA); - else SetPixelMode(Pixel::MASK); - for (auto c : sText) - { - if (c == '\n') - { - sx = 0; sy += 8 * 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 (fontSprite->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 (fontSprite->GetPixel(i + ox * 8, j + oy * 8).r > 0) - Draw(x + sx + i, y + sy + j, col); - } - sx += 8 * 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; - } - - // 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::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_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 - if (!OnUserCreate()) bAtomActive = false; - - 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; - - // 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; - - // renderer->ClearBuffer(olc::BLACK, true); - - // Handle Frame Update - if (!OnUserUpdate(fElapsedTime)) - bAtomActive = false; - - // Display Frame - renderer->UpdateViewport(vViewPos, vViewSize); - renderer->ClearBuffer(olc::BLACK, true); - - // Layer 0 must always exist - vLayers[0].bUpdate = true; - vLayers[0].bShow = true; - renderer->PrepareDrawing(); - - for (auto layer = vLayers.rbegin(); layer != vLayers.rend(); ++layer) - { - if (layer->bShow) - { - if (layer->funcHook == nullptr) - { - renderer->ApplyTexture(layer->nResID); - if (layer->bUpdate) - { - renderer->UpdateTexture(layer->nResID, layer->pDrawTarget); - layer->bUpdate = false; - } - - renderer->DrawLayerQuad(layer->vOffset, layer->vScale, layer->tint); - - // Display Decals in order for this layer - for (auto& decal : layer->vecDecalInstance) - renderer->DrawDecalQuad(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 = "" + 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; } - } - } - - fontDecal = new olc::Decal(fontSprite); - } - - // 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; -}; - - - -// O------------------------------------------------------------------------------O -// | olcPixelGameEngine PLATFORM SPECIFIC IMPLEMENTATIONS | -// O------------------------------------------------------------------------------O - -// O------------------------------------------------------------------------------O -// | START RENDERER: OpenGL 1.0 (the original, the best...) | -// O------------------------------------------------------------------------------O -#if defined(OLC_GFX_OPENGL10) -#if defined(_WIN32) -#include -#include -#include -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 -namespace X11 -{ -#include -#include -#include -} -#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 - -namespace olc -{ - class Renderer_OGL10 : public olc::Renderer - { - private: - glDeviceContext_t glDeviceContext = 0; - glRenderContext_t glRenderContext = 0; - bool bSync = false; - -#if defined(__linux__) || defined(__FreeBSD__) - X11::Display* olc_Display = nullptr; - X11::Window* olc_Window = nullptr; - X11::XVisualInfo* olc_VisualInfo = nullptr; -#endif - - public: - void PrepareDevice() override - { } - - olc::rcode CreateDevice(std::vector params, bool bFullScreen, bool bVSYNC) override - { -#if defined(_WIN32) - // 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(__linux__) || defined(__FreeBSD__) - 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 - - glEnable(GL_TEXTURE_2D); // Turn on texturing - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - return olc::rcode::OK; - } - - olc::rcode DestroyDevice() override - { -#if defined(_WIN32) - wglDeleteContext(glRenderContext); -#endif - -#if defined(__linux__) || defined(__FreeBSD__) - glXMakeCurrent(olc_Display, None, NULL); - glXDestroyContext(olc_Display, glDeviceContext); -#endif - return olc::rcode::OK; - } - - void DisplayFrame() override - { -#if defined(_WIN32) - SwapBuffers(glDeviceContext); - if (bSync) DwmFlush(); // Woooohooooooo!!!! SMOOOOOOOTH! -#endif - -#if defined(__linux__) || defined(__FreeBSD__) - X11::glXSwapBuffers(olc_Display, *olc_Window); -#endif - } - - void PrepareDrawing() override - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - 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 DrawDecalQuad(const olc::DecalInstance& decal) override - { - if (decal.decal == nullptr) - { - glBindTexture(GL_TEXTURE_2D, 0); - glBegin(GL_QUADS); - glColor4ub(decal.tint[0].r, decal.tint[0].g, decal.tint[0].b, decal.tint[0].a); - glTexCoord4f(decal.uv[0].x, decal.uv[0].y, 0.0f, decal.w[0]); glVertex2f(decal.pos[0].x, decal.pos[0].y); - glColor4ub(decal.tint[1].r, decal.tint[1].g, decal.tint[1].b, decal.tint[1].a); - glTexCoord4f(decal.uv[1].x, decal.uv[1].y, 0.0f, decal.w[1]); glVertex2f(decal.pos[1].x, decal.pos[1].y); - glColor4ub(decal.tint[2].r, decal.tint[2].g, decal.tint[2].b, decal.tint[2].a); - glTexCoord4f(decal.uv[2].x, decal.uv[2].y, 0.0f, decal.w[2]); glVertex2f(decal.pos[2].x, decal.pos[2].y); - glColor4ub(decal.tint[3].r, decal.tint[3].g, decal.tint[3].b, decal.tint[3].a); - glTexCoord4f(decal.uv[3].x, decal.uv[3].y, 0.0f, decal.w[3]); glVertex2f(decal.pos[3].x, decal.pos[3].y); - glEnd(); - } - else - { - glBindTexture(GL_TEXTURE_2D, decal.decal->id); - glBegin(GL_QUADS); - glColor4ub(decal.tint[0].r, decal.tint[0].g, decal.tint[0].b, decal.tint[0].a); - glTexCoord4f(decal.uv[0].x, decal.uv[0].y, 0.0f, decal.w[0]); glVertex2f(decal.pos[0].x, decal.pos[0].y); - glTexCoord4f(decal.uv[1].x, decal.uv[1].y, 0.0f, decal.w[1]); glVertex2f(decal.pos[1].x, decal.pos[1].y); - glTexCoord4f(decal.uv[2].x, decal.uv[2].y, 0.0f, decal.w[2]); glVertex2f(decal.pos[2].x, decal.pos[2].y); - glTexCoord4f(decal.uv[3].x, decal.uv[3].y, 0.0f, decal.w[3]); glVertex2f(decal.pos[3].x, decal.pos[3].y); - glEnd(); - } - } - - uint32_t CreateTexture(const uint32_t width, const uint32_t height) override - { - uint32_t id = 0; - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - 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 - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, spr->width, spr->height, 0, 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 - - -// O------------------------------------------------------------------------------O -// | START PLATFORM: MICROSOFT WINDOWS XP, VISTA, 7, 8, 10 | -// O------------------------------------------------------------------------------O -#if defined(_WIN32) -#if !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 -#pragma comment(lib, "gdiplus.lib") -#pragma comment(lib, "Shlwapi.lib") -#pragma comment(lib, "Dwmapi.lib") -#else - // 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 -#endif - -// Include WinAPI -#if !defined(NOMINMAX) -#define NOMINMAX -#endif -#define VC_EXTRALEAN -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include - -namespace olc -{ - // Little utility function to convert from char to wchar in Windows environments - // depending upon how the compiler is configured. This should not be necessary - // on linux platforms - 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; - } - - // 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; - ULONG_PTR token; - Gdiplus::GdiplusStartup(&token, &startupInput, NULL); - }; - } gdistartup; - - - class Platform_Windows : public olc::Platform - { - private: - HWND olc_hWnd = nullptr; - std::wstring wsAppName; - - 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; - 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_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); - } - }; - - // On Windows load images using GDI+ library - olc::rcode Sprite::LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack) - { - 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 - { - // Load sprite from file - bmp = Gdiplus::Bitmap::FromFile(ConvertS2W(sImageFile).c_str()); - } - - if (bmp->GetLastStatus() != Gdiplus::Ok) return olc::NO_FILE; - width = bmp->GetWidth(); - height = bmp->GetHeight(); - pColData = new Pixel[width * height]; - - for (int y = 0; y < height; y++) - for (int x = 0; x < width; x++) - { - Gdiplus::Color c; - bmp->GetPixel(x, y, &c); - SetPixel(x, y, olc::Pixel(c.GetRed(), c.GetGreen(), c.GetBlue(), c.GetAlpha())); - } - delete bmp; - return olc::OK; - } -} -#endif -// O------------------------------------------------------------------------------O -// | END PLATFORM: MICROSOFT WINDOWS XP, VISTA, 7, 8, 10 | -// O------------------------------------------------------------------------------O - - - - - -// O------------------------------------------------------------------------------O -// | START PLATFORM: LINUX | -// O------------------------------------------------------------------------------O -#if defined(__linux__) || defined(__FreeBSD__) -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 - { - 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; - - 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; - } - }; - - 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); - } - - olc::rcode Sprite::LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack) - { - UNUSED(pack); - //////////////////////////////////////////////////////////////////////////// - // 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; - width = png_get_image_width(png, info); - 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) * height); - for (int y = 0; y < height; y++) { - row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info)); - } - png_read_image(png, row_pointers); - //////////////////////////////////////////////////////////////////////////// - // Create sprite array - pColData = new Pixel[width * height]; - // Iterate through image rows, converting into sprite format - for (int y = 0; y < height; y++) - { - png_bytep row = row_pointers[y]; - for (int x = 0; x < width; x++) - { - png_bytep px = &(row[x * 4]); - SetPixel(x, y, Pixel(px[0], px[1], px[2], px[3])); - } - } - - for (int y = 0; y < 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::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::OK; - - fail_load: - width = 0; - height = 0; - pColData = nullptr; - return olc::FAIL; - } -} -#endif -// O------------------------------------------------------------------------------O -// | END PLATFORM: LINUX | -// O------------------------------------------------------------------------------O - -namespace olc -{ - void PixelGameEngine::olc_ConfigureSystem() - { -#if defined(_WIN32) - platform = std::make_unique(); -#endif - -#if defined(__linux__) || defined(__FreeBSD__) - 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_DIRECTX10) - renderer = std::make_unique(); -#endif - - //// Associate components with PGE instance - platform->ptrPGE = this; - renderer->ptrPGE = this; - } -} - -#endif // End olc namespace - -// O------------------------------------------------------------------------------O -// | END OF OLC_PGE_APPLICATION | -// O------------------------------------------------------------------------------O -