No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

olcPixelGameEngine.h 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /*
  2. olcPixelGameEngine.h
  3. +-------------------------------------------------------------+
  4. | OneLoneCoder Pixel Game Engine v1.17 |
  5. | "Like the command prompt console one, but not..." - javidx9 |
  6. +-------------------------------------------------------------+
  7. What is this?
  8. ~~~~~~~~~~~~~
  9. The olcConsoleGameEngine has been a surprising and wonderful success for me,
  10. and I'm delighted how people have reacted so positively towards it, so thanks
  11. for that.
  12. However, there are limitations that I simply cannot avoid. Firstly, I need to
  13. maintain several different versions of it to accommodate users on Windows7,
  14. 8, 10, Linux, Mac, Visual Studio & Code::Blocks. Secondly, this year I've been
  15. pushing the console to the limits of its graphical capabilities and the effect
  16. is becoming underwhelming. The engine itself is not slow at all, but the process
  17. that Windows uses to draw the command prompt to the screen is, and worse still,
  18. it's dynamic based upon the variation of character colours and glyphs. Sadly
  19. I have no control over this, and recent videos that are extremely graphical
  20. (for a command prompt :P ) have been dipping to unacceptable framerates. As
  21. the channel has been popular with aspiring game developers, I'm concerned that
  22. the visual appeal of the command prompt is perhaps limited to us oldies, and I
  23. dont want to alienate younger learners. Finally, I'd like to demonstrate many
  24. more algorithms and image processing that exist in the graphical domain, for
  25. which the console is insufficient.
  26. For this reason, I have created olcPixelGameEngine! The look and feel to the
  27. programmer is almost identical, so all of my existing code from the videos is
  28. easily portable, and the programmer uses this file in exactly the same way. But
  29. I've decided that rather than just build a command prompt emulator, that I
  30. would at least harness some modern(ish) portable technologies.
  31. As a result, the olcPixelGameEngine supports 32-bit colour, is written in a
  32. cross-platform style, uses modern(ish) C++ conventions and most importantly,
  33. renders much much faster. I will use this version when my applications are
  34. predominantly graphics based, but use the console version when they are
  35. predominantly text based - Don't worry, loads more command prompt silliness to
  36. come yet, but evolution is important!!
  37. License (OLC-3)
  38. ~~~~~~~~~~~~~~~
  39. Copyright 2018 - 2019 OneLoneCoder.com
  40. Redistribution and use in source and binary forms, with or without modification,
  41. are permitted provided that the following conditions are met:
  42. 1. Redistributions or derivations of source code must retain the above copyright
  43. notice, this list of conditions and the following disclaimer.
  44. 2. Redistributions or derivative works in binary form must reproduce the above
  45. copyright notice. This list of conditions and the following disclaimer must be
  46. reproduced in the documentation and/or other materials provided with the distribution.
  47. 3. Neither the name of the copyright holder nor the names of its contributors may
  48. be used to endorse or promote products derived from this software without specific
  49. prior written permission.
  50. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  51. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  52. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  53. SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  54. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  55. TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  56. BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  57. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  58. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. SUCH DAMAGE.
  60. Links
  61. ~~~~~
  62. YouTube: https://www.youtube.com/javidx9
  63. https://www.youtube.com/javidx9extra
  64. Discord: https://discord.gg/WhwHUMV
  65. Twitter: https://www.twitter.com/javidx9
  66. Twitch: https://www.twitch.tv/javidx9
  67. GitHub: https://www.github.com/onelonecoder
  68. Homepage: https://www.onelonecoder.com
  69. Patreon: https://www.patreon.com/javidx9
  70. Relevant Videos
  71. ~~~~~~~~~~~~~~~
  72. https://youtu.be/kRH6oJLFYxY Introducing olcPixelGameEngine
  73. Compiling in Linux
  74. ~~~~~~~~~~~~~~~~~~
  75. You will need a modern C++ compiler, so update yours!
  76. To compile use the command:
  77. g++ -o YourProgName YourSource.cpp -lX11 -lGL -lpthread -lpng
  78. On some Linux configurations, the frame rate is locked to the refresh
  79. rate of the monitor. This engine tries to unlock it but may not be
  80. able to, in which case try launching your program like this:
  81. vblank_mode=0 ./YourProgName
  82. Compiling in Code::Blocks on Windows
  83. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  84. Well I wont judge you, but make sure your Code::Blocks installation
  85. is really up to date - you may even consider updating your C++ toolchain
  86. to use MinGW32-W64, so google this. You will also need to enable C++14
  87. in your build options, and add to your linker the following libraries:
  88. user32 gdi32 opengl32 gdiplus
  89. Ports
  90. ~~~~~
  91. olc::PixelGameEngine has been ported and tested with varying degrees of
  92. success to: WinXP, Win7, Win8, Win10, Various Linux, Rapberry Pi,
  93. Chromebook, Playstation Portable (PSP) and Nintendo Switch. If you are
  94. interested in the details of these ports, come and visit the Discord!
  95. Thanks
  96. ~~~~~~
  97. I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim,
  98. JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice
  99. Ralakus, Gorbit99, raoul, joshinils, benedani & MagetzUb for advice, ideas and
  100. testing, and I'd like to extend my appreciation to the 40K YouTube followers,
  101. 22 Patreons and 2.6K Discord server members who give me the motivation to keep
  102. going with all this :D
  103. Special thanks to those who bring gifts!
  104. GnarGnarHead.......Domina
  105. Gorbit99...........Bastion, Ori & The Blind Forest
  106. Marti Morta........Gris
  107. Special thanks to my Patreons too - I wont name you on here, but I've
  108. certainly enjoyed my tea and flapjacks :D
  109. Author
  110. ~~~~~~
  111. David Barr, aka javidx9, ©OneLoneCoder 2018, 2019
  112. */
  113. //////////////////////////////////////////////////////////////////////////////////////////
  114. /* Example Usage (main.cpp)
  115. #define OLC_PGE_APPLICATION
  116. #include "olcPixelGameEngine.h"
  117. // Override base class with your custom functionality
  118. class Example : public olc::PixelGameEngine
  119. {
  120. public:
  121. Example()
  122. {
  123. sAppName = "Example";
  124. }
  125. public:
  126. bool OnUserCreate() override
  127. {
  128. // Called once at the start, so create things here
  129. return true;
  130. }
  131. bool OnUserUpdate(float fElapsedTime) override
  132. {
  133. // called once per frame, draws random coloured pixels
  134. for (int x = 0; x < ScreenWidth(); x++)
  135. for (int y = 0; y < ScreenHeight(); y++)
  136. Draw(x, y, olc::Pixel(rand() % 255, rand() % 255, rand()% 255));
  137. return true;
  138. }
  139. };
  140. int main()
  141. {
  142. Example demo;
  143. if (demo.Construct(256, 240, 4, 4))
  144. demo.Start();
  145. return 0;
  146. }
  147. */
  148. #ifndef OLC_PGE_DEF
  149. #define OLC_PGE_DEF
  150. #ifdef _WIN32
  151. // Link to libraries
  152. #ifndef __MINGW32__
  153. #pragma comment(lib, "user32.lib") // Visual Studio Only
  154. #pragma comment(lib, "gdi32.lib") // For other Windows Compilers please add
  155. #pragma comment(lib, "opengl32.lib") // these libs to your linker input
  156. #pragma comment(lib, "gdiplus.lib")
  157. #else
  158. // In Code::Blocks, Select C++14 in your build options, and add the
  159. // following libs to your linker: user32 gdi32 opengl32 gdiplus
  160. #if !defined _WIN32_WINNT
  161. #ifdef HAVE_MSMF
  162. #define _WIN32_WINNT 0x0600 // Windows Vista
  163. #else
  164. #define _WIN32_WINNT 0x0500 // Windows 2000
  165. #endif
  166. #endif
  167. #endif
  168. // Include WinAPI
  169. #include <windows.h>
  170. #include <gdiplus.h>
  171. // OpenGL Extension
  172. #include <GL/gl.h>
  173. typedef BOOL(WINAPI wglSwapInterval_t) (int interval);
  174. #else
  175. #include <GL/gl.h>
  176. #include <GL/glx.h>
  177. #include <X11/X.h>
  178. #include <X11/Xlib.h>
  179. typedef int(glSwapInterval_t) (Display *dpy, GLXDrawable drawable, int interval);
  180. #endif
  181. // Standard includes
  182. #include <cmath>
  183. #include <cstdint>
  184. #include <string>
  185. #include <iostream>
  186. #include <streambuf>
  187. #include <chrono>
  188. #include <vector>
  189. #include <list>
  190. #include <thread>
  191. #include <atomic>
  192. #include <condition_variable>
  193. #include <fstream>
  194. #include <map>
  195. #include <functional>
  196. #include <algorithm>
  197. #include "olcPGE_Common.h"
  198. #include "olcPGE_Sprite.h"
  199. #include "olcPGE_ResourcePack.h"
  200. #undef min
  201. #undef max
  202. namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
  203. {
  204. struct HWButton
  205. {
  206. bool bPressed = false; // Set once during the frame the event occurs
  207. bool bReleased = false; // Set once during the frame the event occurs
  208. bool bHeld = false; // Set true for all frames between pressed and released events
  209. };
  210. //=============================================================
  211. enum Key
  212. {
  213. NONE,
  214. 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,
  215. K0, K1, K2, K3, K4, K5, K6, K7, K8, K9,
  216. F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
  217. UP, DOWN, LEFT, RIGHT,
  218. SPACE, TAB, SHIFT, CTRL, INS, DEL, HOME, END, PGUP, PGDN,
  219. BACK, ESCAPE, RETURN, ENTER, PAUSE, SCROLL,
  220. NP0, NP1, NP2, NP3, NP4, NP5, NP6, NP7, NP8, NP9,
  221. NP_MUL, NP_DIV, NP_ADD, NP_SUB, NP_DECIMAL,
  222. };
  223. //=============================================================
  224. class PixelGameEngine
  225. {
  226. public:
  227. PixelGameEngine();
  228. public:
  229. olc::rcode Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h, bool full_screen = false);
  230. // Selects maximum pixel size to fit in the display resolution
  231. olc::rcode ConstructAuto(uint32_t screen_w, uint32_t screen_h, bool full_screen = false);
  232. olc::rcode Start();
  233. public: // Override Interfaces
  234. // Called once on application startup, use to load your resources
  235. virtual bool OnUserCreate();
  236. // Called every frame, and provides you with a time per frame value
  237. virtual bool OnUserUpdate(float fElapsedTime);
  238. // Called once on application termination, so you can be a clean coder
  239. virtual bool OnUserDestroy();
  240. public: // Hardware Interfaces
  241. // Returns true if window is currently in focus
  242. bool IsFocused();
  243. // Get the state of a specific keyboard button
  244. HWButton GetKey(Key k);
  245. // Get the state of a specific mouse button
  246. HWButton GetMouse(uint32_t b);
  247. // Get Mouse X coordinate in "pixel" space
  248. int32_t GetMouseX();
  249. // Get Mouse Y coordinate in "pixel" space
  250. int32_t GetMouseY();
  251. // Get Mouse Wheel Delta
  252. int32_t GetMouseWheel();
  253. public: // Utility
  254. // Returns the width of the screen in "pixels"
  255. int32_t ScreenWidth();
  256. // Returns the height of the screen in "pixels"
  257. int32_t ScreenHeight();
  258. // Returns the width of the currently selected drawing target in "pixels"
  259. int32_t GetDrawTargetWidth();
  260. // Returns the height of the currently selected drawing target in "pixels"
  261. int32_t GetDrawTargetHeight();
  262. // Returns the currently active draw target
  263. Sprite* GetDrawTarget();
  264. public: // Draw Routines
  265. // Specify which Sprite should be the target of drawing functions, use nullptr
  266. // to specify the primary screen
  267. void SetDrawTarget(Sprite *target);
  268. // Change the pixel mode for different optimisations
  269. // olc::Pixel::NORMAL = No transparency
  270. // olc::Pixel::MASK = Transparent if alpha is < 255
  271. // olc::Pixel::ALPHA = Full transparency
  272. void SetPixelMode(Pixel::Mode m);
  273. Pixel::Mode GetPixelMode();
  274. // Use a custom blend function
  275. void SetPixelMode(std::function<olc::Pixel(const int x, const int y, const olc::Pixel& pSource, const olc::Pixel& pDest)> pixelMode);
  276. // Change the blend factor form between 0.0f to 1.0f;
  277. void SetPixelBlend(float fBlend);
  278. // Offset texels by sub-pixel amount (advanced, do not use)
  279. void SetSubPixelOffset(float ox, float oy);
  280. // Draws a single Pixel
  281. virtual bool Draw(int32_t x, int32_t y, Pixel p = olc::WHITE);
  282. // Draws a line from (x1,y1) to (x2,y2)
  283. void DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p = olc::WHITE, uint32_t pattern = 0xFFFFFFFF);
  284. // Draws a circle located at (x,y) with radius
  285. void DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE, uint8_t mask = 0xFF);
  286. // Fills a circle located at (x,y) with radius
  287. void FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE);
  288. // Draws a rectangle at (x,y) to (x+w,y+h)
  289. void DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p = olc::WHITE);
  290. // Fills a rectangle at (x,y) to (x+w,y+h)
  291. void FillRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p = olc::WHITE);
  292. // Draws a triangle between points (x1,y1), (x2,y2) and (x3,y3)
  293. void DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE);
  294. // Flat fills a triangle between points (x1,y1), (x2,y2) and (x3,y3)
  295. void FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE);
  296. // Draws an entire sprite at location (x,y)
  297. void DrawSprite(int32_t x, int32_t y, Sprite *sprite, uint32_t scale = 1, bool centered = false);
  298. // Draws an area of a sprite at location (x,y), where the
  299. // selected area is (ox,oy) to (ox+w,oy+h)
  300. 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, bool centered = false);
  301. // Draws a single line of text
  302. void DrawString(int32_t x, int32_t y, std::string sText, Pixel col = olc::WHITE, uint32_t scale = 1);
  303. // Clears entire draw target to Pixel
  304. void Clear(Pixel p);
  305. public: // Branding
  306. std::string sAppName;
  307. private: // Inner mysterious workings
  308. Sprite *pDefaultDrawTarget = nullptr;
  309. Sprite *pDrawTarget = nullptr;
  310. Pixel::Mode nPixelMode = Pixel::NORMAL;
  311. float fBlendFactor = 1.0f;
  312. uint32_t nScreenWidth = 256;
  313. uint32_t nScreenHeight = 240;
  314. uint32_t nPixelWidth = 4;
  315. uint32_t nPixelHeight = 4;
  316. int32_t nMousePosX = 0;
  317. int32_t nMousePosY = 0;
  318. int32_t nMouseWheelDelta = 0;
  319. int32_t nMousePosXcache = 0;
  320. int32_t nMousePosYcache = 0;
  321. int32_t nMouseWheelDeltaCache = 0;
  322. int32_t nWindowWidth = 0;
  323. int32_t nWindowHeight = 0;
  324. int32_t nViewX = 0;
  325. int32_t nViewY = 0;
  326. int32_t nViewW = 0;
  327. int32_t nViewH = 0;
  328. bool bFullScreen = false;
  329. float fPixelX = 1.0f;
  330. float fPixelY = 1.0f;
  331. float fSubPixelOffsetX = 0.0f;
  332. float fSubPixelOffsetY = 0.0f;
  333. bool bHasInputFocus = false;
  334. bool bHasMouseFocus = false;
  335. float fFrameTimer = 1.0f;
  336. int nFrameCount = 0;
  337. Sprite *fontSprite = nullptr;
  338. std::function<olc::Pixel(const int x, const int y, const olc::Pixel&, const olc::Pixel&)> funcPixelMode;
  339. static std::map<uint16_t, uint8_t> mapKeys;
  340. bool pKeyNewState[256]{ 0 };
  341. bool pKeyOldState[256]{ 0 };
  342. HWButton pKeyboardState[256];
  343. bool pMouseNewState[5]{ 0 };
  344. bool pMouseOldState[5]{ 0 };
  345. HWButton pMouseState[5];
  346. #ifdef _WIN32
  347. HDC glDeviceContext = nullptr;
  348. HGLRC glRenderContext = nullptr;
  349. #else
  350. GLXContext glDeviceContext = nullptr;
  351. GLXContext glRenderContext = nullptr;
  352. #endif
  353. GLuint glBuffer;
  354. void EngineThread();
  355. // If anything sets this flag to false, the engine
  356. // "should" shut down gracefully
  357. static std::atomic<bool> bAtomActive;
  358. // Common initialisation functions
  359. void olc_UpdateMouse(int32_t x, int32_t y);
  360. void olc_UpdateMouseWheel(int32_t delta);
  361. void olc_UpdateWindowSize(int32_t x, int32_t y);
  362. void olc_UpdateViewport();
  363. bool olc_OpenGLCreate();
  364. void olc_ConstructFontSheet();
  365. uint32_t olc_GetMaximumPixelSize(uint32_t w, uint32_t h);
  366. #ifdef _WIN32
  367. // Windows specific window handling
  368. HWND olc_hWnd = nullptr;
  369. HWND olc_WindowCreate();
  370. std::wstring wsAppName;
  371. static LRESULT CALLBACK olc_WindowEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  372. #else
  373. // Non-Windows specific window handling
  374. Display* olc_Display = nullptr;
  375. Window olc_WindowRoot;
  376. Window olc_Window;
  377. XVisualInfo* olc_VisualInfo;
  378. Colormap olc_ColourMap;
  379. XSetWindowAttributes olc_SetWindowAttribs;
  380. XSizeHints olc_SizeHints;
  381. Display* olc_WindowCreate();
  382. #endif
  383. };
  384. class PGEX
  385. {
  386. friend class olc::PixelGameEngine;
  387. protected:
  388. static PixelGameEngine* pge;
  389. };
  390. //=============================================================
  391. }
  392. #endif // OLC_PGE_DEF