Skip to content

olc::PixelGameEngine

Javidx9 edited this page Sep 12, 2022 · 9 revisions

Setting Up

To use simply include the "olcPixelGameEngine.h" header file. You will also need to define OLC_PGE_APPLICATION before inclusion. Since PixelGameEngine is a single header solution, it only requires one implementation, which is enabled with this OLC_PGE_APPLICATION flag defined. In most javidx9 videos the code presented is a single file, and so the flag is defined before the inclusion as shown below. This will work with similar simple applications.

#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"

If your solution contains multiple ".cpp" files, with several inclusions of "olcPixelGameEngine.h" you need to understand where to define OLC_PGE_APPLICATION. A common and simple solution is to create a standalone "olcPixelGameEngine.cpp" file which has the above code contained within and nothing else. Include this new cpp file in your build as usual, and just reference "olcPixelGameEngine.h" as appropriate.

olc::rcode Construct(uint32_t screen_w, uint32_t screen_h, uint32_t pixel_w, uint32_t pixel_h)

Construct a PixelGameEngine window which is screen_w x screen_h olc::Pixels in size. Each olc::Pixel is defined a being pixel_w x pixel_h "screen pixels", i.e those native to your monitor. Therefore you can calculate the size of your window in "screen pixels" as being (screen_w * pixel_w) x (screen_h * pixel_h). This function will internally prepare the PixelGameEngine for starting. If it can't do this it will return olc::FAIL, otherwise olc::OK.

olc::rcode Start()

Starts the prepared PixelGameEngine. This will create the window, and create a context for internal rendering, then start the main game engine thread. This function will block until it returns. If the PixelGameEngine ran succesfully it will return olc::OK. If for any reason it could not start, for example inadequate resources, it will return olc::FAIL.

class Example : public olc::PixelGameEngine // Note olc::PixelGameEngine is inherited from
{

};

int main()
{
	Example demo;
	if (demo.Construct(256, 240, 4, 4))
		demo.Start();
	return 0;
}

Adding Functionality

On its own, the PixelGameEngine does nothing. It is a C++ class that you must inherit from and optionally override the following three members.

class Example : public olc::PixelGameEngine // Note olc::PixelGameEngine is inherited from
{
public:
	Example()
	{
		sAppName = "Example"; // You can name your application here
	}

public:
	bool OnUserCreate() override
	{
		// Called once at the start, so create things here
		return true;
	}

	bool OnUserUpdate(float fElapsedTime) override
	{
		// called once per frame
		return true;
	}

        // Optional!
        bool OnUserDestroy() override
	{
		// Called when window is closed
		return true;
	}
};

virtual bool OnUserCreate()

If the engine successfully starts, this function is called before the main game loop begins. It gives you the opportunity to load resources. You can still load resources later but this is a convenient place to do so. If you return false form this function, the PixelGameEngine will stop (and Start() will return), so its important to return true to keep the PixelGameEngine running. Note: this function is called from the thread that runs the game loop, so memory/context/thread sensitive operations performed here, persist into the main game loop. For example, if you need to interact with hardware, this would be an ideal place to establish communication with it.

bool OnUserCreate() override
{
        Ball.x = 50.0f;
        Ball.y = 50.0f;
        Ball.speed = 10.0f;
	return true;
}

virtual bool OnUserUpdate(float fElapsedTime)

This is the core PixelGameEngine function. It is called once per "frame" in your application. Here is where you would perform your game updates and drawing operations. the parameter fElapsedTime represents the time elapsed in seconds since the last time this function was called. This value can be used to accommodate fluctuations in resource availability and duration of this function. For example, consider moving a ball across the screen with a constant "apparent" speed. Simply moving the ball N pixels each frame will work, but will not look consistent. Since Distance (m) = Speed (m/s) * Time (s), we can deduce that the number of pixels required to move varies based on time.

bool OnUserUpdate(float fElapsedTime) override
{
        // Integrate Ball position with respect to time
        Ball.x += Ball.speed * fElapsedTime;
        Ball.y += Ball.speed * fElapsedTime;
      
        // Draw Ball
        ...
	return true;
}

When you wish to exit the PixelGameEngine (from perhaps an in-game menu), you can return false from this function, otherwise return true to keep the engine running.

virtual bool OnUserDestroy()

This method is mostly optional, but is called when the user closes the PixelGameEngine window, giving you the opportunity to unload resources, disconnect from hardware and be an all round tidy programmer. You can veto the closing action by returning false. This will stop the PixelGameEngine from closing, otherwise, return true to allow the application to exit gracefully. Note: In many javidx9 videos you do not see this function being used. Closing the window will in turn exit the process, thus clearing up any trivially allocated memory automatically. However be cautious if you are doing more sophisticated things with memory or connected devices.

User Input

The PixelGameEngine presents easy to use methods to access the state of the keyboard and mouse for the current frame. There is no such thing as an event in PixelGameEngine, instead for a specific button you can determine if it was held down, pressed or released for that frame. Events therefore are actions triggered based on the state of these flags. Buttons return a olc::HWButton object that contains these flags.

Returns the state of a specific key k. PixelGameEngine provides convenience constants to access specific keys. These are listed here olc::Key.

olc::HWButton GetMouse(uint32_t b)

In a similar way to keyboard input, mouse buttons can be assessed for state. Convention dictates that left click is 0, right click is 1 and middle click is 2. Support for up to 5 mouse buttons is provided. The index of the mouse button should be bassed through the b argument. NOTE: At this time, there is no support for Mouse Wheel behaviour.

int32_t GetMouseX()

Returns the mouse's X location (i.e. columns) at the start of the frame in olc::Pixels, with top left corner of display representing (0, 0) and bottom right determined by (ScreenWidth()-1, ScreenHeight()-1).

int32_t GetMouseY()

Returns the mouse's Y location (i.e. rows) at the start of the frame in olc::Pixels, with top left corner of display representing (0, 0) and bottom right determined by (ScreenWidth()-1, ScreenHeight()-1).

bool IsFocused()

Returns true if the PixelGameEngine window is currently in focus of the operating system. The PixelGameEngine does not respond to system events, it simply analyses the state of peripherals, this means input is still accepted when the window does not have focus, so erroneous and unwanted input can be filtered by checking if the PixelGameEngine is in focus first.

if (IsFocused())
{
        if(GetKey(olc::Key::UP).bPressed)
        {
                // Respond to "event" of up direction key being pressed down
        }
}

Environment

int32_t ScreenWidth()

Return the width of the display in olc::Pixels.

int32_t ScreenHeight()

Return the height of the display in olc::Pixels.

void SetDrawTarget(olc::Sprite *target)

Sets the target olc::Sprite for all subsequent draw functions. By default the PixelGameEngine is set up with an olc::Sprite the size of which is determined by the arguments passed into the ConstructConsole() function. Fundamentally the final display is in fact an olc::Sprite. Setting target to nullptr will divert all draw calls to the final display. You can divert drawing functions to any olc::Sprite, for example, rendering things off-screen and then compositing the final scene.

int32_t GetDrawTargetWidth()

Returns the width of the currently selected draw target in olc::Pixels.

int32_t GetDrawTargetHeight()

Returns the height of the currently selected draw target in olc::Pixels.

olc::Sprite* GetDrawTarget()

Returns a pointer to the currently selected olc::Sprite which receives draw calls.

void SetSubPixelOffset(float ox, float oy)

EXPERIMENTAL, CAUTION! This function "shifts" olc::Pixels by a fractional amount of a single olc::Pixel. ox and oy are normalised to the dimensions of a single olc::Pixel This shift occurs in screen pixels and is applied to all drawing routines. Since high definition displays became common, seeing things move in large pixel sized steps can be jarring. In some situations this jarring can be mitigated by also offsetting the pixels in coordination with the direction of movement.

Blending Routines

Drawing in the PixelGameEngine is effectively painting colours at specific locations. However, PIxelGameEngine offers different blending modes that enable transparency and other effects.

void SetPixelBlend(float fBlend)

If an alpha blending pixel mode is in effect, the overall transparency (alpha component) of subsequent draw calls can be set. If fBlend == 1.0f, then no transparency is applied, if fBlend == 0.0f then subsequent draw calls will not be visible.

void SetPixelMode(olc::Pixel::Mode m)

Sets the current blending mode for all subsequent draw calls. m (olc::Pixel::Mode) is one of the following constants:

  • NORMAL - No blending effects are used, this is the fastest, and is the default.
  • MASK - If the alpha component contains anything other than 1.0f (255) the pixel is not drawn.
  • ALPHA - Full alpha blending is applied per pixel enabling varying degrees of translucency. This does affect performance so use only when required.
  • CUSTOM - See Below.

void SetPixelMode(std::function<olc::Pixel(const int x, const int y, const olc::Pixel& pSource, const olc::Pixel& pDest)> pixelMode)

This function allows you to specify a C++ Lambda function to calculate the blending between two pixels, therefore opening up the possibility for all sorts of effects. This lambda function should return the final calculated pixel. You are provided with the current location of the pixel drawing, the specified pixel to draw, and the pixel that already exists in the target location.

olc::Pixel::Mode GetPixelMode()

Returns the current olc::Pixel::Mode in effect.

Drawing Routines

The following routines provide simple and convenient drawing utilities to PixelGameEngine. Where the drawing occurs is determined by the current Draw Target in effect.

void Clear(olc::Pixel p)

Quickly sets the entire current draw target to olc::Pixel p.

virtual bool Draw(int32_t x, int32_t y, olc::Pixel p = olc::WHITE)

Draws a single olc::Pixel p at the location (x, y).

void DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, olc::Pixel p = olc::WHITE)

Draws a one pixel wide line, defined by p from (x1, y1) to (x2, y2).

void DrawCircle(int32_t x, int32_t y, int32_t radius, olc::Pixel p = olc::WHITE)

Draws a one pixel wide circle, centered on (x, y), with a radius. The pixel is defined by p.

void FillCircle(int32_t x, int32_t y, int32_t radius, olc::Pixel p = olc::WHITE)

Fills a circle, centered on (x, y), with a radius. The pixel is defined by p.

void DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, olc::Pixel p = olc::WHITE)

Draws a one pixel wide rectangle from (x, y) to (x + w, y + h) with a pixel defined by p.

void FillRect(int32_t x, int32_t y, int32_t w, int32_t h, olc::Pixel p = olc::WHITE)

Fills a rectangle from (x, y) to (x + w, y + h) with a pixel defined by p.

void DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, olc::Pixel p = olc::WHITE)

Draws a one pixel wide triangle defined by three points (x1, y1), (x2, y2) and (x3, y3). The pixel is defined by p.

void FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, olc::Pixel p = olc::WHITE)

Fills a triangle defined by three points (x1, y1), (x2, y2) and (x3, y3). The pixel is defined by p.

void DrawSprite(int32_t x, int32_t y, olc::Sprite *sprite, uint32_t scale = 1)

Draws an entire olc::Sprite sprite at location (x, y). An optional integer scaling scale can be applied to increase the sprite size, where 2 doubles it, 3 triples it etc.

void DrawPartialSprite(int32_t x, int32_t y, olc::Sprite *sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale = 1)

Draws a region of an olc::Sprite sprite at location (x, y). An optional integer scaling scale can be applied to increase the sprite size, where 2 doubles it, 3 triples it etc. The source olc::Sprite region is defined as being (ox, oy) to (ox + w, oy + h).

void DrawString(int32_t x, int32_t y, std::string sText, olc::Pixel col = olc::WHITE, uint32_t scale = 1)

Draws a text string sText at location (x, y) with a olc::Pixel defined by col. An optional integer scaling scale can be applied to increase the sprite size, where 2 doubles it, 3 triples it etc. Text strings may contain newline character '\n' to draw multi-line text. The PixelGameEngine has a built in monospace font, where each character is 8 x 8 pixels. Drawing a string will temporarily set the pixel blending mode to MASK, but will revert to previous mode when drawing has completed.