PixelGameEngine 1.16

Added Fullscreen mode
Maintains accurate mouse
Maintains aspect ratio of screen on window resize
Added extended numpad support
pull/113/head
Javidx9 6 years ago committed by GitHub
parent 7e72a7804c
commit 570e2cf84b
  1. 130
      olcPixelGameEngine.h

@ -2,7 +2,7 @@
olcPixelGameEngine.h olcPixelGameEngine.h
+-------------------------------------------------------------+ +-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine v1.15 | | OneLoneCoder Pixel Game Engine v1.16 |
| "Like the command prompt console one, but not..." - javidx9 | | "Like the command prompt console one, but not..." - javidx9 |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
@ -73,6 +73,7 @@
Links Links
~~~~~ ~~~~~
YouTube: https://www.youtube.com/javidx9 YouTube: https://www.youtube.com/javidx9
https://www.youtube.com/javidx9extra
Discord: https://discord.gg/WhwHUMV Discord: https://discord.gg/WhwHUMV
Twitter: https://www.twitter.com/javidx9 Twitter: https://www.twitter.com/javidx9
Twitch: https://www.twitch.tv/javidx9 Twitch: https://www.twitch.tv/javidx9
@ -117,9 +118,9 @@
~~~~~~ ~~~~~~
I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim, I'd like to extend thanks to Eremiell, slavka, gurkanctn, Phantim,
JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice
Ralakus, Gorbit99, raoul, joshinils & MagetzUb for advice, ideas and Ralakus, Gorbit99, raoul, joshinils, benedani & MagetzUb for advice, ideas and
testing, and I'd like to extend my appreciation to the 36K YouTube followers testing, and I'd like to extend my appreciation to the 40K YouTube followers,
and 2.3K Discord server members who give me the motivation to keep 22 Patreons and 2.6K Discord server members who give me the motivation to keep
going with all this :D going with all this :D
Special thanks to those who bring gifts! Special thanks to those who bring gifts!
@ -404,7 +405,7 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
PixelGameEngine(); PixelGameEngine();
public: public:
olc::rcode Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h); olc::rcode Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h, bool full_screen = false);
olc::rcode Start(); olc::rcode Start();
public: // Override Interfaces public: // Override Interfaces
@ -484,8 +485,6 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
// Clears entire draw target to Pixel // Clears entire draw target to Pixel
void Clear(Pixel p); void Clear(Pixel p);
void EnableFullScreen(bool bFullScreen, bool bMaintainAspect = true);
public: // Branding public: // Branding
std::string sAppName; std::string sAppName;
@ -506,6 +505,11 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
int32_t nMouseWheelDeltaCache = 0; int32_t nMouseWheelDeltaCache = 0;
int32_t nWindowWidth = 0; int32_t nWindowWidth = 0;
int32_t nWindowHeight = 0; int32_t nWindowHeight = 0;
int32_t nViewX = 0;
int32_t nViewY = 0;
int32_t nViewW = 0;
int32_t nViewH = 0;
bool bFullScreen = false;
float fPixelX = 1.0f; float fPixelX = 1.0f;
float fPixelY = 1.0f; float fPixelY = 1.0f;
float fSubPixelOffsetX = 0.0f; float fSubPixelOffsetX = 0.0f;
@ -545,6 +549,7 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
void olc_UpdateMouse(int32_t x, int32_t y); void olc_UpdateMouse(int32_t x, int32_t y);
void olc_UpdateMouseWheel(int32_t delta); void olc_UpdateMouseWheel(int32_t delta);
void olc_UpdateWindowSize(int32_t x, int32_t y); void olc_UpdateWindowSize(int32_t x, int32_t y);
void olc_UpdateViewport();
bool olc_OpenGLCreate(); bool olc_OpenGLCreate();
void olc_ConstructFontSheet(); void olc_ConstructFontSheet();
@ -1049,12 +1054,13 @@ namespace olc
olc::PGEX::pge = this; olc::PGEX::pge = this;
} }
olc::rcode PixelGameEngine::Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h) olc::rcode PixelGameEngine::Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h, bool full_screen)
{ {
nScreenWidth = screen_w; nScreenWidth = screen_w;
nScreenHeight = screen_h; nScreenHeight = screen_h;
nPixelWidth = pixel_w; nPixelWidth = pixel_w;
nPixelHeight = pixel_h; nPixelHeight = pixel_h;
bFullScreen = full_screen;
fPixelX = 2.0f / (float)(nScreenWidth); fPixelX = 2.0f / (float)(nScreenWidth);
fPixelY = 2.0f / (float)(nScreenHeight); fPixelY = 2.0f / (float)(nScreenHeight);
@ -1656,24 +1662,31 @@ namespace olc
{ return true; } { return true; }
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
void PixelGameEngine::olc_UpdateViewport()
void PixelGameEngine::EnableFullScreen(bool bFullScreen, bool bMaintainAspect)
{ {
if(bFullScreen) int32_t ww = nScreenWidth * nPixelWidth;
{ int32_t wh = nScreenHeight * nPixelHeight;
// Go full Screen float wasp = (float)ww / (float)wh;
} nViewW = nWindowWidth;
else nViewH = (float)nViewW / wasp;
if (nViewH > nWindowHeight)
{ {
// Go back to window nViewH = nWindowHeight;
nViewW = (float)nViewH * wasp;
} }
nViewX = (nWindowWidth - nViewW) / 2;
nViewY = (nWindowHeight - nViewH) / 2;
} }
void PixelGameEngine::olc_UpdateWindowSize(int32_t x, int32_t y) void PixelGameEngine::olc_UpdateWindowSize(int32_t x, int32_t y)
{ {
nWindowWidth = x; nWindowWidth = x;
nWindowHeight = y; nWindowHeight = y;
olc_UpdateViewport();
} }
void PixelGameEngine::olc_UpdateMouseWheel(int32_t delta) void PixelGameEngine::olc_UpdateMouseWheel(int32_t delta)
@ -1685,8 +1698,16 @@ namespace olc
{ {
// Mouse coords come in screen space // Mouse coords come in screen space
// But leave in pixel space // But leave in pixel space
nMousePosXcache = (int32_t)(((float)x / (float)nWindowWidth) * (float)nScreenWidth);
nMousePosYcache = (int32_t)(((float)y / (float)nWindowHeight) * (float)nScreenHeight); //if (bFullScreen)
{
// Full Screen mode may have a weird viewport we must clamp to
x -= nViewX;
y -= nViewY;
}
nMousePosXcache = (int32_t)(((float)x / (float)(nWindowWidth - (nViewX * 2)) * (float)nScreenWidth));
nMousePosYcache = (int32_t)(((float)y / (float)(nWindowHeight - (nViewY * 2)) * (float)nScreenHeight));
if (nMousePosXcache >= (int32_t)nScreenWidth) if (nMousePosXcache >= (int32_t)nScreenWidth)
nMousePosXcache = nScreenWidth - 1; nMousePosXcache = nScreenWidth - 1;
@ -1747,7 +1768,10 @@ namespace olc
{ {
XWindowAttributes gwa; XWindowAttributes gwa;
XGetWindowAttributes(olc_Display, olc_Window, &gwa); XGetWindowAttributes(olc_Display, olc_Window, &gwa);
glViewport(0, 0, gwa.width, gwa.height); nWindowWidth = gwa.width;
nWindowHeight = gwa.height;
olc_UpdateViewport();
glClear(GL_COLOR_BUFFER_BIT); // Thanks Benedani!
} }
else if (xev.type == ConfigureNotify) else if (xev.type == ConfigureNotify)
{ {
@ -1759,11 +1783,17 @@ namespace olc
{ {
KeySym sym = XLookupKeysym(&xev.xkey, 0); KeySym sym = XLookupKeysym(&xev.xkey, 0);
pKeyNewState[mapKeys[sym]] = true; pKeyNewState[mapKeys[sym]] = true;
XKeyEvent *e = (XKeyEvent *)&xev; // Because DragonEye loves numpads
XLookupString(e, NULL, 0, &sym, NULL);
pKeyNewState[mapKeys[sym]] = true;
} }
else if (xev.type == KeyRelease) else if (xev.type == KeyRelease)
{ {
KeySym sym = XLookupKeysym(&xev.xkey, 0); KeySym sym = XLookupKeysym(&xev.xkey, 0);
pKeyNewState[mapKeys[sym]] = false; pKeyNewState[mapKeys[sym]] = false;
XKeyEvent *e = (XKeyEvent *)&xev;
XLookupString(e, NULL, 0, &sym, NULL);
pKeyNewState[mapKeys[sym]] = false;
} }
else if (xev.type == ButtonPress) else if (xev.type == ButtonPress)
{ {
@ -1869,6 +1899,7 @@ namespace olc
bAtomActive = false; bAtomActive = false;
// Display Graphics // Display Graphics
glViewport(nViewX, nViewY, nViewW, nViewH);
// TODO: This is a bit slow (especially in debug, but 100x faster in release mode???) // TODO: This is a bit slow (especially in debug, but 100x faster in release mode???)
// Copy pixel array into texture // Copy pixel array into texture
@ -2010,23 +2041,46 @@ namespace olc
RegisterClass(&wc); RegisterClass(&wc);
nWindowWidth = (LONG)nScreenWidth * (LONG)nPixelWidth;
nWindowHeight = (LONG)nScreenHeight * (LONG)nPixelHeight;
// Define window furniture // Define window furniture
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
DWORD dwStyle = WS_CAPTION | WS_SYSMENU | WS_VISIBLE; DWORD dwStyle = WS_CAPTION | WS_SYSMENU | WS_VISIBLE; // | WS_THICKFRAME;
RECT rWndRect = { 0, 0, (LONG)nScreenWidth * (LONG)nPixelWidth, (LONG)nScreenHeight * (LONG)nPixelHeight };
int nCosmeticOffset = 30;
nViewW = nWindowWidth;
nViewH = nWindowHeight;
// Handle Fullscreen
if (bFullScreen)
{
dwExStyle = 0;
dwStyle = WS_VISIBLE | WS_POPUP;
nCosmeticOffset = 0;
HMONITOR hmon = MonitorFromWindow(olc_hWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi = { sizeof(mi) };
if (!GetMonitorInfo(hmon, &mi)) return NULL;
nWindowWidth = mi.rcMonitor.right;
nWindowHeight = mi.rcMonitor.bottom;
}
olc_UpdateViewport();
// Keep client size as requested // Keep client size as requested
RECT rWndRect = { 0, 0, nWindowWidth, nWindowHeight };
AdjustWindowRectEx(&rWndRect, dwStyle, FALSE, dwExStyle); AdjustWindowRectEx(&rWndRect, dwStyle, FALSE, dwExStyle);
int width = rWndRect.right - rWndRect.left; int width = rWndRect.right - rWndRect.left;
int height = rWndRect.bottom - rWndRect.top; int height = rWndRect.bottom - rWndRect.top;
#ifdef UNICODE #ifdef UNICODE
olc_hWnd = CreateWindowEx(dwExStyle, L"OLC_PIXEL_GAME_ENGINE", L"", dwStyle, olc_hWnd = CreateWindowEx(dwExStyle, L"OLC_PIXEL_GAME_ENGINE", L"", dwStyle,
30, 30, width, height, NULL, NULL, GetModuleHandle(nullptr), this); nCosmeticOffset, nCosmeticOffset, width, height, NULL, NULL, GetModuleHandle(nullptr), this);
#else #else
olc_hWnd = CreateWindowEx(dwExStyle, "OLC_PIXEL_GAME_ENGINE", "", dwStyle, olc_hWnd = CreateWindowEx(dwExStyle, "OLC_PIXEL_GAME_ENGINE", "", dwStyle,
30, 30, width, height, NULL, NULL, GetModuleHandle(nullptr), this); nCosmeticOffset, nCosmeticOffset, width, height, NULL, NULL, GetModuleHandle(nullptr), this);
#endif #endif
// Create Keyboard Mapping // Create Keyboard Mapping
@ -2080,6 +2134,8 @@ namespace olc
if (!(glRenderContext = wglCreateContext(glDeviceContext))) return false; if (!(glRenderContext = wglCreateContext(glDeviceContext))) return false;
wglMakeCurrent(glDeviceContext, glRenderContext); wglMakeCurrent(glDeviceContext, glRenderContext);
glViewport(nViewX, nViewY, nViewW, nViewH);
// Remove Frame cap // Remove Frame cap
wglSwapInterval = (wglSwapInterval_t*)wglGetProcAddress("wglSwapIntervalEXT"); wglSwapInterval = (wglSwapInterval_t*)wglGetProcAddress("wglSwapIntervalEXT");
if (wglSwapInterval) wglSwapInterval(0); if (wglSwapInterval) wglSwapInterval(0);
@ -2156,6 +2212,32 @@ namespace olc
XMapWindow(olc_Display, olc_Window); XMapWindow(olc_Display, olc_Window);
XStoreName(olc_Display, olc_Window, "OneLoneCoder.com - Pixel Game Engine"); 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);
nWindowWidth = gwa.width;
nWindowHeight = gwa.height;
olc_UpdateViewport();
}
// Create Keyboard Mapping // Create Keyboard Mapping
mapKeys[0x00] = Key::NONE; 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[0x61] = Key::A; mapKeys[0x62] = Key::B; mapKeys[0x63] = Key::C; mapKeys[0x64] = Key::D; mapKeys[0x65] = Key::E;

Loading…
Cancel
Save