Version 1.14
+ Static GDI initialiser for windows + 2D vector type + Sampling texels Accurately + Normalised mouse position + Pre-cache mouse position before frame update + Mouse wheel access
This commit is contained in:
parent
35acfcd278
commit
b3f124affd
@ -2,83 +2,73 @@
|
|||||||
olcPixelGameEngine.h
|
olcPixelGameEngine.h
|
||||||
|
|
||||||
+-------------------------------------------------------------+
|
+-------------------------------------------------------------+
|
||||||
| OneLoneCoder Pixel Game Engine v1.13 |
|
| OneLoneCoder Pixel Game Engine v1.14 |
|
||||||
| "Like the command prompt console one, but not..." - javidx9 |
|
| "Like the command prompt console one, but not..." - javidx9 |
|
||||||
+-------------------------------------------------------------+
|
+-------------------------------------------------------------+
|
||||||
|
|
||||||
What is this?
|
What is this?
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
The olcConsoleGameEngine has been a surprsing and wonderful
|
The olcConsoleGameEngine has been a surprising and wonderful success for me,
|
||||||
success for me, and I'm delighted how people have reacted so
|
and I'm delighted how people have reacted so positively towards it, so thanks
|
||||||
positively towards it, so thanks for that.
|
for that.
|
||||||
|
|
||||||
However, there are limitations that I simply cannot avoid.
|
However, there are limitations that I simply cannot avoid. Firstly, I need to
|
||||||
Firstly, I need to maintain several different versions of
|
maintain several different versions of it to accommodate users on Windows7,
|
||||||
it to accommodate users on Windows7, 8, 10, Linux, Mac,
|
8, 10, Linux, Mac, Visual Studio & Code::Blocks. Secondly, this year I've been
|
||||||
Visual Studio & Code::Blocks. Secondly, this year I've been
|
pushing the console to the limits of its graphical capabilities and the effect
|
||||||
pushing the console to the limits of its graphical capabilities
|
is becoming underwhelming. The engine itself is not slow at all, but the process
|
||||||
and the effect is becoming underwhelming. The engine itself
|
that Windows uses to draw the command prompt to the screen is, and worse still,
|
||||||
is not slow at all, but the process that Windows uses to
|
it's dynamic based upon the variation of character colours and glyphs. Sadly
|
||||||
draw the command prompt to the screen is, and worse still,
|
I have no control over this, and recent videos that are extremely graphical
|
||||||
it's dynamic based upon the variation of character colours
|
(for a command prompt :P ) have been dipping to unacceptable framerates. As
|
||||||
and glyphs. Sadly I have no control over this, and recent
|
the channel has been popular with aspiring game developers, I'm concerned that
|
||||||
videos that are extremely graphical (for a command prompt :P )
|
the visual appeal of the command prompt is perhaps limited to us oldies, and I
|
||||||
have been dipping to unacceptable framerates. As the channel
|
dont want to alienate younger learners. Finally, I'd like to demonstrate many
|
||||||
has been popular with aspiring game developers, I'm concerned
|
more algorithms and image processing that exist in the graphical domain, for
|
||||||
that the visual appeal of the command prompt is perhaps
|
which the console is insufficient.
|
||||||
limited to us oldies, and I dont want to alienate younger
|
|
||||||
learners. Finally, I'd like to demonstrate many more
|
|
||||||
algorithms and image processing that exist in the graphical
|
|
||||||
domain, for which the console is insufficient.
|
|
||||||
|
|
||||||
For this reason, I have created olcPixelGameEngine! The look
|
For this reason, I have created olcPixelGameEngine! The look and feel to the
|
||||||
and feel to the programmer is almost identical, so all of my
|
programmer is almost identical, so all of my existing code from the videos is
|
||||||
existing code from the videos is easily portable, and the
|
easily portable, and the programmer uses this file in exactly the same way. But
|
||||||
programmer uses this file in exactly the same way. But I've
|
I've decided that rather than just build a command prompt emulator, that I
|
||||||
decided that rather than just build a command prompt emulator,
|
would at least harness some modern(ish) portable technologies.
|
||||||
that I would at least harness some modern(ish) portable
|
|
||||||
technologies.
|
|
||||||
|
|
||||||
As a result, the olcPixelGameEngine supports 32-bit colour, is
|
As a result, the olcPixelGameEngine supports 32-bit colour, is written in a
|
||||||
written in a cross-platform style, uses modern(ish) C++
|
cross-platform style, uses modern(ish) C++ conventions and most importantly,
|
||||||
conventions and most importantly, renders much much faster. I
|
renders much much faster. I will use this version when my applications are
|
||||||
will use this version when my applications are predominantly
|
predominantly graphics based, but use the console version when they are
|
||||||
graphics based, but use the console version when they are
|
predominantly text based - Don't worry, loads more command prompt silliness to
|
||||||
predominantly text based - Don't worry, loads more command
|
come yet, but evolution is important!!
|
||||||
prompt silliness to come yet, but evolution is important!!
|
|
||||||
|
|
||||||
License (OLC-3)
|
License (OLC-3)
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Copyright 2018 - 2019 OneLoneCoder.com
|
Copyright 2018 - 2019 OneLoneCoder.com
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
modification, are permitted provided that the following conditions
|
are permitted provided that the following conditions are met:
|
||||||
are met:
|
|
||||||
|
|
||||||
1. Redistributions or derivations of source code must retain the above
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
copyright notice, this list of conditions and the following disclaimer.
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
2. Redistributions or derivative works in binary form must reproduce
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
the above copyright notice. This list of conditions and the following
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
disclaimer must be reproduced in the documentation and/or other
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
materials provided with the distribution.
|
|
||||||
|
|
||||||
3. Neither the name of the copyright holder nor the names of its
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
contributors may be used to endorse or promote products derived
|
be used to endorse or promote products derived from this software without specific
|
||||||
from this software without specific prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
SUCH DAMAGE.
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
Links
|
Links
|
||||||
~~~~~
|
~~~~~
|
||||||
@ -116,17 +106,25 @@
|
|||||||
in your build options, and add to your linker the following libraries:
|
in your build options, and add to your linker the following libraries:
|
||||||
user32 gdi32 opengl32 gdiplus
|
user32 gdi32 opengl32 gdiplus
|
||||||
|
|
||||||
|
Ports
|
||||||
|
~~~~~
|
||||||
|
olc::PixelGameEngine has been ported and tested with varying degrees of
|
||||||
|
success to: WinXP, Win7, Win8, Win10, Various Linux, Rapberry Pi,
|
||||||
|
Chromebook, Playstation Portable (PSP) and Nintendo Switch. If you are
|
||||||
|
interested in the details of these ports, come and visit the Discord!
|
||||||
|
|
||||||
Thanks
|
Thanks
|
||||||
~~~~~~
|
~~~~~~
|
||||||
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 & MagetzUb for advice, ideas and testing, and I'd like
|
Ralakus, Gorbit99, raoul, joshinils & MagetzUb for advice, ideas and
|
||||||
to extend my appreciation to the 23K YouTube followers and 1.5K Discord server
|
testing, and I'd like to extend my appreciation to the 36K YouTube followers
|
||||||
members who give me the motivation to keep going with all this :D
|
and 2.3K Discord server members who give me the motivation to keep
|
||||||
|
going with all this :D
|
||||||
|
|
||||||
Special thanks to those who bring gifts!
|
Special thanks to those who bring gifts!
|
||||||
GnarGnarHead.......Domina
|
GnarGnarHead.......Domina
|
||||||
Gorbit99...........Bastion
|
Gorbit99...........Bastion, Ori & The Blind Forest
|
||||||
|
|
||||||
Special thanks to my Patreons too - I wont name you on here, but I've
|
Special thanks to my Patreons too - I wont name you on here, but I've
|
||||||
certainly enjoyed my tea and flapjacks :D
|
certainly enjoyed my tea and flapjacks :D
|
||||||
@ -221,6 +219,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
@ -264,17 +263,56 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
NO_FILE = -1,
|
NO_FILE = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==================================================================================
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct v2d_generic
|
||||||
|
{
|
||||||
|
T x = 0;
|
||||||
|
T y = 0;
|
||||||
|
|
||||||
|
inline v2d_generic() : x(0), y(0) { }
|
||||||
|
inline v2d_generic(T _x, T _y) : x(_x), y(_y) { }
|
||||||
|
inline v2d_generic(const v2d_generic& v) : x(v.x), y(v.y){ }
|
||||||
|
inline T mag() { return sqrt(x * x + y * y); }
|
||||||
|
inline v2d_generic norm() { T r = 1 / mag(); return v2d_generic(x*r, y*r); }
|
||||||
|
inline v2d_generic perp() { return v2d_generic(-y, x); }
|
||||||
|
inline T dot(const v2d_generic& rhs) { return this->x * rhs.x + this->y * rhs.y; }
|
||||||
|
inline T cross(const v2d_generic& rhs) { return this->x * rhs.y - this->y * rhs.x; }
|
||||||
|
inline v2d_generic operator + (const v2d_generic& rhs) { return v2d_generic(this->x + rhs.x, this->y + rhs.y);}
|
||||||
|
inline v2d_generic operator - (const v2d_generic& rhs) { return v2d_generic(this->x - rhs.x, this->y - rhs.y);}
|
||||||
|
inline v2d_generic operator * (const T& rhs) { return v2d_generic(this->x * rhs, this->y * rhs); }
|
||||||
|
inline v2d_generic operator / (const T& rhs) { return v2d_generic(this->x / rhs, this->y / rhs); }
|
||||||
|
inline v2d_generic& operator += (const v2d_generic& rhs) { this->x += rhs.x; this->y += rhs.y; return *this; }
|
||||||
|
inline v2d_generic& operator -= (const v2d_generic& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this; }
|
||||||
|
inline v2d_generic& operator *= (const T& rhs) { this->x *= rhs; this->y *= rhs; return *this; }
|
||||||
|
inline v2d_generic& operator /= (const T& rhs) { this->x /= rhs; this->y /= rhs; return *this; }
|
||||||
|
inline T& operator [] (std::size_t i) { return *((T*)this + i); /* <-- D'oh :( */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> inline v2d_generic<T> operator * (const float& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
|
||||||
|
template<class T> inline v2d_generic<T> operator * (const double& lhs, const v2d_generic<T>& rhs){ return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
|
||||||
|
template<class T> inline v2d_generic<T> operator * (const int& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
|
||||||
|
template<class T> inline v2d_generic<T> operator / (const float& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
|
||||||
|
template<class T> inline v2d_generic<T> operator / (const double& lhs, const v2d_generic<T>& rhs){ return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
|
||||||
|
template<class T> inline v2d_generic<T> operator / (const int& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
|
||||||
|
|
||||||
|
typedef v2d_generic<int> vi2d;
|
||||||
|
typedef v2d_generic<float> vf2d;
|
||||||
|
typedef v2d_generic<double> vd2d;
|
||||||
|
|
||||||
//=============================================================
|
//=============================================================
|
||||||
|
|
||||||
struct HWButton
|
struct HWButton
|
||||||
{
|
{
|
||||||
bool bPressed = false; // Set once during the frame the event occurs
|
bool bPressed = false; // Set once during the frame the event occurs
|
||||||
bool bReleased = false; // Set once during the frame the event occurs
|
bool bReleased = false; // Set once during the frame the event occurs
|
||||||
bool bHeld = false; // Set tru for all frames between pressed and released events
|
bool bHeld = false; // Set true for all frames between pressed and released events
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================
|
//=============================================================
|
||||||
|
|
||||||
|
|
||||||
class ResourcePack
|
class ResourcePack
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -325,7 +363,7 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
public:
|
public:
|
||||||
void SetSampleMode(olc::Sprite::Mode mode = olc::Sprite::Mode::NORMAL);
|
void SetSampleMode(olc::Sprite::Mode mode = olc::Sprite::Mode::NORMAL);
|
||||||
Pixel GetPixel(int32_t x, int32_t y);
|
Pixel GetPixel(int32_t x, int32_t y);
|
||||||
void SetPixel(int32_t x, int32_t y, Pixel p);
|
bool SetPixel(int32_t x, int32_t y, Pixel p);
|
||||||
|
|
||||||
Pixel Sample(float x, float y);
|
Pixel Sample(float x, float y);
|
||||||
Pixel SampleBL(float u, float v);
|
Pixel SampleBL(float u, float v);
|
||||||
@ -346,6 +384,7 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
|
|
||||||
enum Key
|
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,
|
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,
|
K0, K1, K2, K3, K4, K5, K6, K7, K8, K9,
|
||||||
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||||
@ -387,6 +426,8 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
int32_t GetMouseX();
|
int32_t GetMouseX();
|
||||||
// Get Mouse Y coordinate in "pixel" space
|
// Get Mouse Y coordinate in "pixel" space
|
||||||
int32_t GetMouseY();
|
int32_t GetMouseY();
|
||||||
|
// Get Mouse Wheel Delta
|
||||||
|
int32_t GetMouseWheel();
|
||||||
|
|
||||||
public: // Utility
|
public: // Utility
|
||||||
// Returns the width of the screen in "pixels"
|
// Returns the width of the screen in "pixels"
|
||||||
@ -418,7 +459,7 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
void SetSubPixelOffset(float ox, float oy);
|
void SetSubPixelOffset(float ox, float oy);
|
||||||
|
|
||||||
// Draws a single Pixel
|
// Draws a single Pixel
|
||||||
virtual void Draw(int32_t x, int32_t y, Pixel p = olc::WHITE);
|
virtual bool Draw(int32_t x, int32_t y, Pixel p = olc::WHITE);
|
||||||
// Draws a line from (x1,y1) to (x2,y2)
|
// 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);
|
void DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p = olc::WHITE);
|
||||||
// Draws a circle located at (x,y) with radius
|
// Draws a circle located at (x,y) with radius
|
||||||
@ -443,6 +484,8 @@ 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;
|
||||||
|
|
||||||
@ -455,8 +498,14 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
uint32_t nScreenHeight = 240;
|
uint32_t nScreenHeight = 240;
|
||||||
uint32_t nPixelWidth = 4;
|
uint32_t nPixelWidth = 4;
|
||||||
uint32_t nPixelHeight = 4;
|
uint32_t nPixelHeight = 4;
|
||||||
int32_t nMousePosX = 0;
|
int32_t nMousePosX = 0;
|
||||||
int32_t nMousePosY = 0;
|
int32_t nMousePosY = 0;
|
||||||
|
int32_t nMouseWheelDelta = 0;
|
||||||
|
int32_t nMousePosXcache = 0;
|
||||||
|
int32_t nMousePosYcache = 0;
|
||||||
|
int32_t nMouseWheelDeltaCache = 0;
|
||||||
|
int32_t nWindowWidth = 0;
|
||||||
|
int32_t nWindowHeight = 0;
|
||||||
float fPixelX = 1.0f;
|
float fPixelX = 1.0f;
|
||||||
float fPixelY = 1.0f;
|
float fPixelY = 1.0f;
|
||||||
float fSubPixelOffsetX = 0.0f;
|
float fSubPixelOffsetX = 0.0f;
|
||||||
@ -494,9 +543,12 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
|
|
||||||
// Common initialisation functions
|
// Common initialisation functions
|
||||||
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_UpdateWindowSize(int32_t x, int32_t y);
|
||||||
bool olc_OpenGLCreate();
|
bool olc_OpenGLCreate();
|
||||||
void olc_ConstructFontSheet();
|
void olc_ConstructFontSheet();
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Windows specific window handling
|
// Windows specific window handling
|
||||||
HWND olc_hWnd = nullptr;
|
HWND olc_hWnd = nullptr;
|
||||||
@ -541,14 +593,6 @@ namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
|
|||||||
to including this file must have OLC_PGE_APPLICATION defined before it. This prevents
|
to including this file must have OLC_PGE_APPLICATION defined before it. This prevents
|
||||||
the definitions being duplicated.
|
the definitions being duplicated.
|
||||||
|
|
||||||
Consider the following project structure:
|
|
||||||
|
|
||||||
Class1.h - Includes olcPixelGameEngine.h, overrides olc::PixelGameEngine
|
|
||||||
Class1.cpp - #define OLC_PGE_APPLICATION #include "Class1.h"
|
|
||||||
Class2.h - Includes Class1.h, which includes olcPixelGameEngine.h
|
|
||||||
Class2.cpp - #define OLC_PGE_APPLICATION #include "Class2.h"
|
|
||||||
main.cpp - Includes Class1.h and Class2.h
|
|
||||||
|
|
||||||
If all else fails, create a file called "olcPixelGameEngine.cpp" with the following
|
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
|
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!
|
about defining things. Dont forget to include that cpp file as part of your build!
|
||||||
@ -812,7 +856,7 @@ namespace olc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite::SetPixel(int32_t x, int32_t y, Pixel p)
|
bool Sprite::SetPixel(int32_t x, int32_t y, Pixel p)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef OLC_DBG_OVERDRAW
|
#ifdef OLC_DBG_OVERDRAW
|
||||||
@ -820,13 +864,18 @@ namespace olc
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (x >= 0 && x < width && y >= 0 && y < height)
|
if (x >= 0 && x < width && y >= 0 && y < height)
|
||||||
|
{
|
||||||
pColData[y*width + x] = p;
|
pColData[y*width + x] = p;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pixel Sprite::Sample(float x, float y)
|
Pixel Sprite::Sample(float x, float y)
|
||||||
{
|
{
|
||||||
int32_t sx = (int32_t)((x * (float)width) - 0.5f);
|
int32_t sx = std::min((int32_t)((x * (float)width)), width - 1);
|
||||||
int32_t sy = (int32_t)((y * (float)height) - 0.5f);
|
int32_t sy = std::min((int32_t)((y * (float)height)), height - 1);
|
||||||
return GetPixel(sx, sy);
|
return GetPixel(sx, sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,17 +883,17 @@ namespace olc
|
|||||||
{
|
{
|
||||||
u = u * width - 0.5f;
|
u = u * width - 0.5f;
|
||||||
v = v * height - 0.5f;
|
v = v * height - 0.5f;
|
||||||
int x = (int)u;
|
int x = (int)floor(u); // cast to int rounds toward zero, not downward
|
||||||
int y = (int)v;
|
int y = (int)floor(v); // Thanks @joshinils
|
||||||
float u_ratio = u - x;
|
float u_ratio = u - x;
|
||||||
float v_ratio = v - y;
|
float v_ratio = v - y;
|
||||||
float u_opposite = 1 - u_ratio;
|
float u_opposite = 1 - u_ratio;
|
||||||
float v_opposite = 1 - v_ratio;
|
float v_opposite = 1 - v_ratio;
|
||||||
|
|
||||||
olc::Pixel p1 = GetPixel(x, y);
|
olc::Pixel p1 = GetPixel(std::max(x, 0), std::max(y, 0));
|
||||||
olc::Pixel p2 = GetPixel(x+1, y);
|
olc::Pixel p2 = GetPixel(std::min(x + 1, (int)width - 1), std::max(y, 0));
|
||||||
olc::Pixel p3 = GetPixel(x, y+1);
|
olc::Pixel p3 = GetPixel(std::max(x, 0), std::min(y + 1, (int)height - 1));
|
||||||
olc::Pixel p4 = GetPixel(x+1, y+1);
|
olc::Pixel p4 = GetPixel(std::min(x + 1, (int)width - 1), std::min(y + 1, (int)height - 1));
|
||||||
|
|
||||||
return olc::Pixel(
|
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.r * u_opposite + p2.r * u_ratio) * v_opposite + (p3.r * u_opposite + p4.r * u_ratio) * v_ratio),
|
||||||
@ -1036,15 +1085,15 @@ namespace olc
|
|||||||
return olc::FAIL;
|
return olc::FAIL;
|
||||||
|
|
||||||
// Load libraries required for PNG file interaction
|
// Load libraries required for PNG file interaction
|
||||||
#ifdef _WIN32
|
//#ifdef _WIN32
|
||||||
// Windows use GDI+
|
// // Windows use GDI+
|
||||||
Gdiplus::GdiplusStartupInput startupInput;
|
// Gdiplus::GdiplusStartupInput startupInput;
|
||||||
ULONG_PTR token;
|
// ULONG_PTR token;
|
||||||
Gdiplus::GdiplusStartup(&token, &startupInput, NULL);
|
// Gdiplus::GdiplusStartup(&token, &startupInput, NULL);
|
||||||
#else
|
//#else
|
||||||
// Linux use libpng
|
// // Linux use libpng
|
||||||
|
//
|
||||||
#endif
|
//#endif
|
||||||
// Start the thread
|
// Start the thread
|
||||||
bAtomActive = true;
|
bAtomActive = true;
|
||||||
std::thread t = std::thread(&PixelGameEngine::EngineThread, this);
|
std::thread t = std::thread(&PixelGameEngine::EngineThread, this);
|
||||||
@ -1118,6 +1167,11 @@ namespace olc
|
|||||||
return nMousePosY;
|
return nMousePosY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t PixelGameEngine::GetMouseWheel()
|
||||||
|
{
|
||||||
|
return nMouseWheelDelta;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t PixelGameEngine::ScreenWidth()
|
int32_t PixelGameEngine::ScreenWidth()
|
||||||
{
|
{
|
||||||
return nScreenWidth;
|
return nScreenWidth;
|
||||||
@ -1128,22 +1182,20 @@ namespace olc
|
|||||||
return nScreenHeight;
|
return nScreenHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelGameEngine::Draw(int32_t x, int32_t y, Pixel p)
|
bool PixelGameEngine::Draw(int32_t x, int32_t y, Pixel p)
|
||||||
{
|
{
|
||||||
if (!pDrawTarget) return;
|
if (!pDrawTarget) return false;
|
||||||
|
|
||||||
|
|
||||||
if (nPixelMode == Pixel::NORMAL)
|
if (nPixelMode == Pixel::NORMAL)
|
||||||
{
|
{
|
||||||
pDrawTarget->SetPixel(x, y, p);
|
return pDrawTarget->SetPixel(x, y, p);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nPixelMode == Pixel::MASK)
|
if (nPixelMode == Pixel::MASK)
|
||||||
{
|
{
|
||||||
if(p.a == 255)
|
if(p.a == 255)
|
||||||
pDrawTarget->SetPixel(x, y, p);
|
return pDrawTarget->SetPixel(x, y, p);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nPixelMode == Pixel::ALPHA)
|
if (nPixelMode == Pixel::ALPHA)
|
||||||
@ -1154,15 +1206,15 @@ namespace olc
|
|||||||
float r = a * (float)p.r + c * (float)d.r;
|
float r = a * (float)p.r + c * (float)d.r;
|
||||||
float g = a * (float)p.g + c * (float)d.g;
|
float g = a * (float)p.g + c * (float)d.g;
|
||||||
float b = a * (float)p.b + c * (float)d.b;
|
float b = a * (float)p.b + c * (float)d.b;
|
||||||
pDrawTarget->SetPixel(x, y, Pixel((uint8_t)r, (uint8_t)g, (uint8_t)b));
|
return pDrawTarget->SetPixel(x, y, Pixel((uint8_t)r, (uint8_t)g, (uint8_t)b));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nPixelMode == Pixel::CUSTOM)
|
if (nPixelMode == Pixel::CUSTOM)
|
||||||
{
|
{
|
||||||
pDrawTarget->SetPixel(x, y, funcPixelMode(x, y, p, pDrawTarget->GetPixel(x, y)));
|
return pDrawTarget->SetPixel(x, y, funcPixelMode(x, y, p, pDrawTarget->GetPixel(x, y)));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelGameEngine::SetSubPixelOffset(float ox, float oy)
|
void PixelGameEngine::SetSubPixelOffset(float ox, float oy)
|
||||||
@ -1598,22 +1650,47 @@ namespace olc
|
|||||||
{ return true; }
|
{ return true; }
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
void PixelGameEngine::EnableFullScreen(bool bFullScreen, bool bMaintainAspect)
|
||||||
|
{
|
||||||
|
if(bFullScreen)
|
||||||
|
{
|
||||||
|
// Go full Screen
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Go back to window
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixelGameEngine::olc_UpdateWindowSize(int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
nWindowWidth = x;
|
||||||
|
nWindowHeight = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixelGameEngine::olc_UpdateMouseWheel(int32_t delta)
|
||||||
|
{
|
||||||
|
nMouseWheelDeltaCache += delta;
|
||||||
|
}
|
||||||
|
|
||||||
void PixelGameEngine::olc_UpdateMouse(int32_t x, int32_t y)
|
void PixelGameEngine::olc_UpdateMouse(int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
// Mouse coords come in screen space
|
// Mouse coords come in screen space
|
||||||
// But leave in pixel space
|
// But leave in pixel space
|
||||||
nMousePosX = x / (int32_t)nPixelWidth;
|
nMousePosXcache = (int32_t)(((float)x / (float)nWindowWidth) * (float)nScreenWidth);
|
||||||
nMousePosY = y / (int32_t)nPixelHeight;
|
nMousePosYcache = (int32_t)(((float)y / (float)nWindowHeight) * (float)nScreenHeight);
|
||||||
|
|
||||||
if (nMousePosX >= (int32_t)nScreenWidth)
|
if (nMousePosXcache >= (int32_t)nScreenWidth)
|
||||||
nMousePosX = nScreenWidth - 1;
|
nMousePosXcache = nScreenWidth - 1;
|
||||||
if (nMousePosY >= (int32_t)nScreenHeight)
|
if (nMousePosYcache >= (int32_t)nScreenHeight)
|
||||||
nMousePosY = nScreenHeight - 1;
|
nMousePosYcache = nScreenHeight - 1;
|
||||||
|
|
||||||
if (nMousePosX < 0)
|
if (nMousePosXcache < 0)
|
||||||
nMousePosX = 0;
|
nMousePosXcache = 0;
|
||||||
if (nMousePosY < 0)
|
if (nMousePosYcache < 0)
|
||||||
nMousePosY = 0;
|
nMousePosYcache = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelGameEngine::EngineThread()
|
void PixelGameEngine::EngineThread()
|
||||||
@ -1666,6 +1743,12 @@ namespace olc
|
|||||||
XGetWindowAttributes(olc_Display, olc_Window, &gwa);
|
XGetWindowAttributes(olc_Display, olc_Window, &gwa);
|
||||||
glViewport(0, 0, gwa.width, gwa.height);
|
glViewport(0, 0, gwa.width, gwa.height);
|
||||||
}
|
}
|
||||||
|
else if (xev.type == ConfigureNotify)
|
||||||
|
{
|
||||||
|
XConfigureEvent xce = xev.xconfigure;
|
||||||
|
nWindowWidth = xce.width;
|
||||||
|
nWindowHeight = xce.height;
|
||||||
|
}
|
||||||
else if (xev.type == KeyPress)
|
else if (xev.type == KeyPress)
|
||||||
{
|
{
|
||||||
KeySym sym = XLookupKeysym(&xev.xkey, 0);
|
KeySym sym = XLookupKeysym(&xev.xkey, 0);
|
||||||
@ -1678,11 +1761,25 @@ namespace olc
|
|||||||
}
|
}
|
||||||
else if (xev.type == ButtonPress)
|
else if (xev.type == ButtonPress)
|
||||||
{
|
{
|
||||||
pMouseNewState[xev.xbutton.button-1] = true;
|
switch (xev.xbutton.button)
|
||||||
|
{
|
||||||
|
case 1: pMouseNewState[0] = true; break;
|
||||||
|
case 2: pMouseNewState[2] = true; break;
|
||||||
|
case 3: pMouseNewState[1] = true; break;
|
||||||
|
case 4: olc_UpdateMouseWheel(120); break;
|
||||||
|
case 5: olc_UpdateMouseWheel(-120); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (xev.type == ButtonRelease)
|
else if (xev.type == ButtonRelease)
|
||||||
{
|
{
|
||||||
pMouseNewState[xev.xbutton.button-1] = false;
|
switch (xev.xbutton.button)
|
||||||
|
{
|
||||||
|
case 1: pMouseNewState[0] = false; break;
|
||||||
|
case 2: pMouseNewState[2] = false; break;
|
||||||
|
case 3: pMouseNewState[1] = false; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (xev.type == MotionNotify)
|
else if (xev.type == MotionNotify)
|
||||||
{
|
{
|
||||||
@ -1749,6 +1846,14 @@ namespace olc
|
|||||||
pMouseOldState[i] = pMouseNewState[i];
|
pMouseOldState[i] = pMouseNewState[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache mouse coordinates so they remain
|
||||||
|
// consistent during frame
|
||||||
|
nMousePosX = nMousePosXcache;
|
||||||
|
nMousePosY = nMousePosYcache;
|
||||||
|
|
||||||
|
nMouseWheelDelta = nMouseWheelDeltaCache;
|
||||||
|
nMouseWheelDeltaCache = 0;
|
||||||
|
|
||||||
#ifdef OLC_DBG_OVERDRAW
|
#ifdef OLC_DBG_OVERDRAW
|
||||||
olc::Sprite::nOverdrawCount = 0;
|
olc::Sprite::nOverdrawCount = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -1823,6 +1928,21 @@ namespace olc
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// 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;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void PixelGameEngine::olc_ConstructFontSheet()
|
void PixelGameEngine::olc_ConstructFontSheet()
|
||||||
{
|
{
|
||||||
@ -1904,6 +2024,7 @@ namespace olc
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create Keyboard Mapping
|
// 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[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[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[0x4B] = Key::K; mapKeys[0x4C] = Key::L; mapKeys[0x4D] = Key::M; mapKeys[0x4E] = Key::N; mapKeys[0x4F] = Key::O;
|
||||||
@ -1955,7 +2076,7 @@ namespace olc
|
|||||||
|
|
||||||
// Remove Frame cap
|
// Remove Frame cap
|
||||||
wglSwapInterval = (wglSwapInterval_t*)wglGetProcAddress("wglSwapIntervalEXT");
|
wglSwapInterval = (wglSwapInterval_t*)wglGetProcAddress("wglSwapIntervalEXT");
|
||||||
wglSwapInterval(0);
|
if (wglSwapInterval) wglSwapInterval(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1975,11 +2096,21 @@ namespace olc
|
|||||||
sge->olc_UpdateMouse(ix, iy);
|
sge->olc_UpdateMouse(ix, iy);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case WM_MOUSELEAVE: sge->bHasMouseFocus = false;
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
sge->olc_UpdateWindowSize(lParam & 0xFFFF, (lParam >> 16) & 0xFFFF);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_MOUSEWHEEL:
|
||||||
|
{
|
||||||
|
sge->olc_UpdateMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case WM_MOUSELEAVE: sge->bHasMouseFocus = false; return 0;
|
||||||
case WM_SETFOCUS: sge->bHasInputFocus = true; return 0;
|
case WM_SETFOCUS: sge->bHasInputFocus = true; return 0;
|
||||||
case WM_KILLFOCUS: sge->bHasInputFocus = false; return 0;
|
case WM_KILLFOCUS: sge->bHasInputFocus = false; return 0;
|
||||||
case WM_KEYDOWN: sge->pKeyNewState[mapKeys[(uint16_t)wParam]] = true; return 0;
|
case WM_KEYDOWN: sge->pKeyNewState[mapKeys[wParam]] = true; return 0;
|
||||||
case WM_KEYUP: sge->pKeyNewState[mapKeys[(uint16_t)wParam]] = false; return 0;
|
case WM_KEYUP: sge->pKeyNewState[mapKeys[wParam]] = false; return 0;
|
||||||
case WM_LBUTTONDOWN:sge->pMouseNewState[0] = true; return 0;
|
case WM_LBUTTONDOWN:sge->pMouseNewState[0] = true; return 0;
|
||||||
case WM_LBUTTONUP: sge->pMouseNewState[0] = false; return 0;
|
case WM_LBUTTONUP: sge->pMouseNewState[0] = false; return 0;
|
||||||
case WM_RBUTTONDOWN:sge->pMouseNewState[1] = true; return 0;
|
case WM_RBUTTONDOWN:sge->pMouseNewState[1] = true; return 0;
|
||||||
@ -2008,7 +2139,7 @@ namespace olc
|
|||||||
olc_SetWindowAttribs.colormap = olc_ColourMap;
|
olc_SetWindowAttribs.colormap = olc_ColourMap;
|
||||||
|
|
||||||
// Register which events we are interested in receiving
|
// Register which events we are interested in receiving
|
||||||
olc_SetWindowAttribs.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
|
olc_SetWindowAttribs.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask | StructureNotifyMask;
|
||||||
|
|
||||||
// Create the window
|
// Create the window
|
||||||
olc_Window = XCreateWindow(olc_Display, olc_WindowRoot, 30, 30, nScreenWidth * nPixelWidth, nScreenHeight * nPixelHeight, 0, olc_VisualInfo->depth, InputOutput, olc_VisualInfo->visual, CWColormap | CWEventMask, &olc_SetWindowAttribs);
|
olc_Window = XCreateWindow(olc_Display, olc_WindowRoot, 30, 30, nScreenWidth * nPixelWidth, nScreenHeight * nPixelHeight, 0, olc_VisualInfo->depth, InputOutput, olc_VisualInfo->visual, CWColormap | CWEventMask, &olc_SetWindowAttribs);
|
||||||
@ -2020,6 +2151,7 @@ namespace olc
|
|||||||
XStoreName(olc_Display, olc_Window, "OneLoneCoder.com - Pixel Game Engine");
|
XStoreName(olc_Display, olc_Window, "OneLoneCoder.com - Pixel Game Engine");
|
||||||
|
|
||||||
// Create Keyboard Mapping
|
// 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[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[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[0x6B] = Key::K; mapKeys[0x6C] = Key::L; mapKeys[0x6D] = Key::M; mapKeys[0x6E] = Key::N; mapKeys[0x6F] = Key::O;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user