Compare commits

...

4 Commits
sig ... develop

  1. 219
      examples/TEST_Camera2D.cpp
  2. 165
      olcPixelGameEngine.h
  3. 258
      utilities/olcUTIL_Camera2D.h

@ -0,0 +1,219 @@
/*
Example file for olcUTIL_Camera2D.h
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2022 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
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
Author
~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022
*/
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
#define OLC_PGEX_TRANSFORMEDVIEW
#include "extensions/olcPGEX_TransformedView.h"
#include "utilities/olcUTIL_Camera2D.h"
/*
To demonstrate the camera, we need a world. In this case its a simle tile
world of 80x75 tiles, and each tile is 32x32 screen pixels.
A transformed view is used to navigate the world manually via the middle
mouse button in "free roam" mode, or controlled by the camera.
Specifically a Tile Transformed View is used, which means all units for
drawing and for the camera are specified in tile space, i.e. 1 tile is
1x1 units (regardless of pixel size)
No assets are used for this application, so the world is constructed
out of coloured squares so you can see you are moving through it.
Pressing "TAB" key will swap between "free roam" and "play" modes. In
free roam mode, you can use middle mouse button to pan and zoom around
the world. The camera's visible area to the player is highlighted in red.
In play mode, the camera behaves as it would in a 2D game, depending upon
the selected mode.
*/
class TEST_Camera2D : public olc::PixelGameEngine
{
public:
TEST_Camera2D()
{
sAppName = "Camera2D Utility Test";
}
// Transformed view object to make world offsetting simple
olc::TileTransformedView tv;
// Conveninet constants to define tile map world
olc::vi2d m_vWorldSize = { 80, 75 };
olc::vi2d m_vTileSize = { 32, 32 };
// The camera!
olc::utils::Camera2D camera;
// The point that represents the player, it is "tracked"
// by the camera
olc::vf2d vTrackedPoint;
// Flag whether we are in "free roam" or "play" mode
bool bFreeRoam = false;
// The world map, stored as a 1D array
std::vector<uint8_t> vWorldMap;
public:
bool OnUserCreate() override
{
// Construct transform view
tv = olc::TileTransformedView(GetScreenSize(), m_vTileSize);
// Construct Camera
vTrackedPoint = { 20.0f, 20.0f };
camera = olc::utils::Camera2D(GetScreenSize() / m_vTileSize, vTrackedPoint);
// Configure Camera
camera.SetTarget(vTrackedPoint);
camera.SetMode(olc::utils::Camera2D::Mode::Simple);
camera.SetWorldBoundary({ 0.0f, 0.0f }, m_vWorldSize);
camera.EnableWorldBoundary(true);
// Create "tile map" world with just two tiles
vWorldMap.resize(m_vWorldSize.x * m_vWorldSize.y);
for (int i = 0; i < vWorldMap.size(); i++)
vWorldMap[i] = ((rand() % 20) == 1) ? 1 : 0;
// Set background colour
Clear(olc::CYAN);
return true;
}
bool OnUserUpdate(float fElapsedTime) override
{
// In free roam, middle mouse button pans & zooms
if (bFreeRoam)
tv.HandlePanAndZoom();
// Handle player "physics" in response to key presses
olc::vf2d vVel = { 0.0f, 0.0f };
if (GetKey(olc::Key::W).bHeld) vVel += {0, -1};
if (GetKey(olc::Key::S).bHeld) vVel += {0, +1};
if (GetKey(olc::Key::A).bHeld) vVel += {-1, 0};
if (GetKey(olc::Key::D).bHeld) vVel += {+1, 0};
vTrackedPoint += vVel * 8.0f * fElapsedTime;
// Switch between "free roam" and "play" mode with TAB key
if (GetKey(olc::Key::TAB).bPressed)
{
// Always setup camera to play mode when tab key pressed
tv.SetWorldOffset(camera.GetViewPosition());
tv.SetWorldScale(m_vTileSize);
bFreeRoam = !bFreeRoam;
}
// Switch camera mode in operation
if (GetKey(olc::Key::K1).bPressed)
camera.SetMode(olc::utils::Camera2D::Mode::Simple);
if (GetKey(olc::Key::K2).bPressed)
camera.SetMode(olc::utils::Camera2D::Mode::EdgeMove);
if (GetKey(olc::Key::K3).bPressed)
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
if (GetKey(olc::Key::K4).bPressed)
camera.SetMode(olc::utils::Camera2D::Mode::FixedScreens);
// Update the camera, if teh tracked object remains visible,
// true is returned
bool bOnScreen = camera.Update(fElapsedTime);
// In "play" mode, set the transformed view to that required by
// the camera
if (!bFreeRoam)
tv.SetWorldOffset(camera.GetViewPosition());
// Render "tile map", by getting visible tiles
olc::vi2d vTileTL = tv.GetTopLeftTile().max({ 0,0 });
olc::vi2d vTileBR = tv.GetBottomRightTile().min(m_vWorldSize);
olc::vi2d vTile;
// Then looping through them and drawing them
for (vTile.y = vTileTL.y; vTile.y < vTileBR.y; vTile.y++)
for (vTile.x = vTileTL.x; vTile.x < vTileBR.x; vTile.x++)
{
int idx = vTile.y * m_vWorldSize.x + vTile.x;
if (vWorldMap[idx] == 0)
tv.FillRectDecal(vTile, { 1.0f, 1.0f }, olc::Pixel(40, 40, 40));
if (vWorldMap[idx] == 1)
tv.FillRectDecal(vTile, { 1.0f, 1.0f }, olc::Pixel(60, 60, 60));
}
// Draw the "player" as a 1x1 cell
tv.FillRectDecal(vTrackedPoint - olc::vf2d(0.5f, 0.5f), {1.0f, 1.0f}, olc::BLUE);
// Overlay with information
if (bFreeRoam)
{
tv.FillRectDecal(camera.GetViewPosition(), camera.GetViewSize(), olc::PixelF(1.0f, 0.0f, 0.0f, 0.5f));
DrawStringPropDecal({ 2, 2 }, "TAB: Free Mode, M-Btn to Pan & Zoom", olc::YELLOW);
}
else
DrawStringPropDecal({ 2,2 }, "TAB: Play Mode", olc::YELLOW);
DrawStringPropDecal({ 2,12 }, "WASD : Move", olc::YELLOW);
DrawStringPropDecal({ 2,22 }, "CAMERA: 1) Simple 2) EdgeMove 3) LazyFollow 4) Screens", olc::YELLOW);
DrawStringPropDecal({ 2,42 }, vTrackedPoint.str(), olc::YELLOW);
return true;
}
};
int main()
{
TEST_Camera2D demo;
if (demo.Construct(512, 480, 2, 2))
demo.Start();
return 0;
}

@ -3,7 +3,7 @@
olcPixelGameEngine.h
+-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine v2.20 |
| OneLoneCoder Pixel Game Engine v2.21 |
| "What do you need? Pixels... Lots of Pixels..." - javidx9 |
+-------------------------------------------------------------+
@ -197,7 +197,7 @@
Author
~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2018, 2019, 2020, 2021, 2022
David Barr, aka javidx9, <EFBFBD>OneLoneCoder 2018, 2019, 2020, 2021, 2022
*/
#pragma endregion
@ -303,6 +303,7 @@
2.20: +DrawRectDecal() - Keeps OneSketchyGuy quiet
+GetScreenSize()
+olc::Sprite::Size() - returns size of sprite in vector format
2.21: Emscripten Overhaul - Thanks Moros!
!! Apple Platforms will not see these updates immediately - Sorry, I dont have a mac to test... !!
!! Volunteers willing to help appreciated, though PRs are manually integrated with credit !!
@ -382,7 +383,7 @@ int main()
#include <cstring>
#pragma endregion
#define PGE_VER 220
#define PGE_VER 221
// O------------------------------------------------------------------------------O
// | COMPILER CONFIGURATION ODDITIES |
@ -5817,118 +5818,100 @@ namespace olc
// the giant web baby.
// Fullscreen and Resize Observers
EM_ASM({
// cache for reuse
Module._olc_EmscriptenShellCss = "width: 100%; height: 70vh; margin-left: auto; margin-right: auto;";
// olc_ApsectRatio
//
// Used by olc_ResizeHandler to calculate the viewport from the
// dimensions of the canvas container's element.
Module.olc_AspectRatio = $0 / $1;
// width / height = aspect ratio
Module._olc_WindowAspectRatio = $0 / $1;
Module.canvas.parentNode.addEventListener("resize", function(e) {
// HACK ALERT!
//
// Here we assume any html shell that uses 3 or more instance of the class "emscripten"
// is using one of the default or minimal emscripten page layouts
Module.olc_AssumeDefaultShells = (document.querySelectorAll('.emscripten').length >= 3) ? true : false;
if (e.defaultPrevented) { e.stopPropagation(); return; }
var viewWidth = e.detail.width;
var viewHeight = e.detail.width / Module._olc_WindowAspectRatio;
if (viewHeight > e.detail.height)
{
viewHeight = e.detail.height;
viewWidth = e.detail.height * Module._olc_WindowAspectRatio;
}
// olc_ResizeHandler
//
// Used by olc_Init, and is called when a resize observer and fullscreenchange event is triggered.
var olc_ResizeHandler = function()
{
// are we in fullscreen mode?
let isFullscreen = (document.fullscreenElement != null);
if (Module.canvas.parentNode.className == 'emscripten_border')
Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss + " width: " + viewWidth.toString() + "px; height: " + viewHeight.toString() + "px;";
// get the width of the containing element
let width = (isFullscreen || !Module.olc_AssumeDefaultShells) ? window.innerWidth : Module.canvas.parentNode.clientWidth;
let height = (isFullscreen || !Module.olc_AssumeDefaultShells) ? window.innerHeight : Module.canvas.parentNode.clientHeight;
Module.canvas.setAttribute("width", viewWidth);
Module.canvas.setAttribute("height", viewHeight);
// calculate the expected viewport size
let viewWidth = width;
let viewHeight = width / Module.olc_AspectRatio;
if (document.fullscreenElement != null)
// if we're taller than the containing element, recalculate based on height
if(viewHeight > height)
{
var top = (e.detail.height - viewHeight) / 2;
var left = (e.detail.width - viewWidth) / 2;
Module.canvas.style.position = "fixed";
Module.canvas.style.top = top.toString() + "px";
Module.canvas.style.left = left.toString() + "px";
Module.canvas.style.width = "";
Module.canvas.style.height = "";
viewWidth = height * Module.olc_AspectRatio;
viewHeight = height;
}
// trigger PGE update
Module._olc_PGE_UpdateWindowSize(viewWidth, viewHeight);
// this is really only needed when enter/exiting fullscreen
Module.canvas.focus();
// prevent this event from ever affecting the document beyond this element
e.stopPropagation();
});
// ensure resulting viewport is in integer space
viewWidth = parseInt(viewWidth);
viewHeight = parseInt(viewHeight);
// helper function to prevent repeating the same code everywhere
Module._olc_ResizeCanvas = function()
{
// yes, we still have to wait, sigh..
setTimeout(function()
{
// if default template, stretch width as well
if (Module.canvas.parentNode.className == 'emscripten_border')
Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss;
// if default shells, apply default styles
if(Module.olc_AssumeDefaultShells)
Module.canvas.parentNode.setAttribute('style', 'width: 100%; height: 70vh; margin-left: auto; margin-right: auto;');
// override it's styling so we can get it's stretched size
Module.canvas.style.cssText = "width: 100%; height: 100%; outline: none;";
// apply viewport dimensions to teh canvas
Module.canvas.setAttribute('width', viewWidth);
Module.canvas.setAttribute('height', viewHeight);
Module.canvas.setAttribute('style', `width: ${viewWidth}px; height: ${viewHeight}px;`);
// setup custom resize event
var resizeEvent = new CustomEvent('resize',
{
detail: {
width: Module.canvas.clientWidth,
height : Module.canvas.clientHeight
},
bubbles : true,
cancelable : true
});
// trigger custom resize event on canvas element
Module.canvas.dispatchEvent(resizeEvent);
}, 50);
};
// update the PGE window size
Module._olc_PGE_UpdateWindowSize(viewWidth, viewHeight);
// force focus on our PGE canvas
Module.canvas.focus();
}, 200);
};
// Disable Refresh Gesture on mobile
document.body.style.cssText += " overscroll-behavior-y: contain;";
if (Module.canvas.parentNode.className == 'emscripten_border')
// olc_Init
//
// set up resize observer and fullscreenchange event handler
var olc_Init = function()
{
// force body to have no margin in emscripten's minimal shell
document.body.style.margin = "0";
Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss;
}
if(Module.olc_AspectRatio === undefined)
{
setTimeout(function() { Module.olc_Init(); }, 50);
return;
}
Module._olc_ResizeCanvas();
let resizeObserver = new ResizeObserver(function(entries)
{
Module.olc_ResizeHandler();
}).observe(Module.canvas.parentNode);
// observe and react to resizing of the container element
var resizeObserver = new ResizeObserver(function(entries) {Module._olc_ResizeCanvas();}).observe(Module.canvas.parentNode);
let mutationObserver = new MutationObserver(function(mutationsList, observer)
{
setTimeout(function() { Module.olc_ResizeHandler(); }, 200);
}).observe(Module.canvas.parentNode, { attributes: false, childList: true, subtree: false });
// observe and react to changes that occur when entering/exiting fullscreen
var mutationObserver = new MutationObserver(function(mutationsList, observer)
{
// a change has occurred, let's check them out!
for (var i = 0; i < mutationsList.length; i++)
window.addEventListener('fullscreenchange', function(e)
{
// cycle through all of the newly added elements
for (var j = 0; j < mutationsList[i].addedNodes.length; j++)
{
// if this element is a our canvas, trigger resize
if (mutationsList[i].addedNodes[j].id == 'canvas')
Module._olc_ResizeCanvas();
}
}
}).observe(Module.canvas.parentNode,
{
attributes: false,
childList : true,
subtree : false
});
setTimeout(function() { Module.olc_ResizeHandler();}, 200);
});
};
// set up hooks
Module.olc_ResizeHandler = (Module.olc_ResizeHandler != undefined) ? Module.olc_ResizeHandler : olc_ResizeHandler;
Module.olc_Init = (Module.olc_Init != undefined) ? Module.olc_Init : olc_Init;
// add resize listener on window
window.addEventListener("resize", function(e) { Module._olc_ResizeCanvas(); });
// run everything!
Module.olc_Init();
}, vWindowSize.x, vWindowSize.y); // Fullscreen and Resize Observers
#pragma warning restore format

@ -0,0 +1,258 @@
/*
OneLoneCoder - Camera2D v1.00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A 2D world camera with various modes
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2022 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
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
Author
~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022
*/
#pragma once
#include "olcPixelGameEngine.h"
namespace olc::utils
{
class Camera2D
{
public:
enum class Mode : uint8_t
{
Simple, // No motion, just directly settable
EdgeMove, // Moves as target crosses boundary
LazyFollow, // Lazily follows the target
FixedScreens, // Moves statically between "screens"
};
public:
inline Camera2D() : m_pTarget(&m_vLocalTarget) {}
// Construct a camera with a viewable area size, and an optional starting position
inline Camera2D(const olc::vf2d& vViewSize, const olc::vf2d& vViewPos = { 0.0f, 0.0f }) : m_pTarget(&m_vLocalTarget)
{
m_vViewSize = vViewSize;
m_vViewPos = vViewPos;
}
// Set the operational mode of this camera
inline void SetMode(const Mode t)
{
m_nMode = t;
}
// Get the operational mode of this camera
inline Mode GetMode() const
{
return m_nMode;
}
// Get the position of the target being tracked by this camera
inline const olc::vf2d& GetTarget() const
{
return *m_pTarget;
}
// Get the position of the cameras focus point
inline const olc::vf2d& GetPosition() const
{
return m_vPosition;
}
// Get the top left of teh cameras visible area in world space
inline const olc::vf2d& GetViewPosition() const
{
return m_vViewPos;
}
// Get the camera's visible area
inline const olc::vf2d& GetViewSize() const
{
return m_vViewSize;
}
// Set tracked point via pointer
inline void SetTarget(olc::vf2d& vTarget)
{
m_pTarget = &vTarget;
}
// Set tracked point via const ref - {10, 35} for example
inline void SetTarget(const olc::vf2d&& vTarget)
{
m_vLocalTarget = vTarget;
m_pTarget = &m_vLocalTarget;
}
// Set world boundary rectangle
inline void SetWorldBoundary(const olc::vf2d& vPos, const olc::vf2d& vSize)
{
m_vWorldBoundaryPos = vPos;
m_vWorldBoundarySize = vSize;
}
// Instruct camera to respect world boundaries
inline void EnableWorldBoundary(const bool bEnable)
{
m_bWorldBoundary = bEnable;
}
// Are we using a world boundary?
inline bool IsWorldBoundaryEnabled() const
{
return m_bWorldBoundary;
}
// Get the world boundary rectangle position
inline const olc::vf2d& GetWorldBoundaryPosition() const
{
return m_vWorldBoundaryPos;
}
// Get the world boundary rectangle size
inline const olc::vf2d& GetWorldBoundarySize() const
{
return m_vWorldBoundarySize;
}
// Set the velocity at which the lazy follower reaches tracked point
inline void SetLazyFollowRate(const float fRate)
{
m_fLazyFollowRate = fRate;
}
// Get the velocity at which the lazy follower reaches tracked point
inline float GetLazyFollowRate() const
{
return m_fLazyFollowRate;
}
// Set distance from tracked point to start nudging screen
inline void SetEdgeTriggerDistance(const olc::vf2d& vEdge)
{
m_vEdgeTriggerDistance = vEdge;
}
// Return disance from tracked point that screen will nudge
inline const olc::vf2d& GetEdgeTriggerDistance() const
{
return m_vEdgeTriggerDistance;
}
// Update camera, animating if necessary, obeying world boundary rules
// returns true if target is visible
inline virtual bool Update(const float fElapsedTime)
{
switch (m_nMode)
{
case Mode::Simple:
{
m_vPosition = GetTarget();
}
break;
case Mode::EdgeMove:
{
olc::vf2d vOverlap = GetTarget() - m_vPosition;
if (vOverlap.x > m_vEdgeTriggerDistance.x) m_vPosition.x += vOverlap.x - m_vEdgeTriggerDistance.x;
if (vOverlap.x < -m_vEdgeTriggerDistance.x) m_vPosition.x += vOverlap.x + m_vEdgeTriggerDistance.x;
if (vOverlap.y > m_vEdgeTriggerDistance.y) m_vPosition.y += vOverlap.y - m_vEdgeTriggerDistance.y;
if (vOverlap.y < -m_vEdgeTriggerDistance.y) m_vPosition.y += vOverlap.y + m_vEdgeTriggerDistance.y;
}
break;
case Mode::LazyFollow:
{
m_vPosition += (GetTarget() - m_vPosition) * m_fLazyFollowRate * fElapsedTime;
}
break;
case Mode::FixedScreens:
{
m_vPosition = olc::vf2d(olc::vi2d(GetTarget() / m_vScreenSize) * olc::vi2d(m_vScreenSize)) + (m_vViewSize * 0.5f);
}
break;
}
// Make camera target the middle of the view
m_vViewPos = m_vPosition - (m_vViewSize * 0.5f);
// Clamp to World Boundary (if in place)
if (m_bWorldBoundary)
{
m_vViewPos = m_vViewPos.max(m_vWorldBoundaryPos).min(m_vWorldBoundaryPos + m_vWorldBoundarySize - m_vViewSize);
}
return GetTarget().x >= m_vViewPos.x && GetTarget().x < (m_vViewPos.x + m_vViewSize.x) &&
GetTarget().y >= m_vViewPos.y && GetTarget().y < (m_vViewPos.y + m_vViewSize.y);
}
protected:
// Position of camera focus point in the world
olc::vf2d m_vPosition;
// Rectangular size of camera viewing area
olc::vf2d m_vViewSize;
// Top left coordinate of camera viewing area
olc::vf2d m_vViewPos;
// Camera movement mode
Mode m_nMode = Mode::Simple;
// Target Vector2D object camera should follow (either ref or ptr)
olc::vf2d* m_pTarget = nullptr;
olc::vf2d m_vLocalTarget;
// World Boundary
bool m_bWorldBoundary = false;
olc::vf2d m_vWorldBoundaryPos = { 0.0f, 0.0f };
olc::vf2d m_vWorldBoundarySize = { 256.0f, 240.0f };
// Mode specific
olc::vf2d m_vEdgeTriggerDistance = { 1.0f, 1.0f };
float m_fLazyFollowRate = 4.0f;
olc::vi2d m_vScreenSize = { 16,15 };
};
}
Loading…
Cancel
Save