Implement TransformedView and Camera util
This commit is contained in:
parent
6b9787d29b
commit
3dac286089
@ -17,7 +17,6 @@
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
@ -53,11 +52,10 @@
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared" >
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
@ -71,9 +69,7 @@
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
@ -108,6 +104,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -122,6 +119,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -130,8 +128,15 @@
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemGroup></ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="olcPGEX_TransformedView.h" />
|
||||
<ClInclude Include="olcPixelGameEngine.h" />
|
||||
<ClInclude Include="olcUTIL_Animate2D.h" />
|
||||
<ClInclude Include="olcUTIL_Camera2D.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
@ -14,4 +14,23 @@
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="olcPixelGameEngine.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="olcUTIL_Animate2D.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="olcUTIL_Camera2D.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="olcPGEX_TransformedView.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
BIN
Crawler/assets/nico-warrior.png
Normal file
BIN
Crawler/assets/nico-warrior.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
BIN
Crawler/assets/nico-warrior.xcf
Normal file
BIN
Crawler/assets/nico-warrior.xcf
Normal file
Binary file not shown.
BIN
Crawler/assets/slime.png
Normal file
BIN
Crawler/assets/slime.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
83
Crawler/main.cpp
Normal file
83
Crawler/main.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#define OLC_PGE_APPLICATION
|
||||
#include "olcPixelGameEngine.h"
|
||||
#include "olcUTIL_Camera2D.h"
|
||||
#define OLC_PGEX_TRANSFORMEDVIEW
|
||||
#include "olcPGEX_TransformedView.h"
|
||||
|
||||
using namespace olc;
|
||||
using namespace olc::utils;
|
||||
|
||||
const vi2d WINDOW_SIZE={24*8,24*8};
|
||||
|
||||
struct Player{
|
||||
vf2d pos;
|
||||
float moveSpd;
|
||||
Player(){};
|
||||
Player(vf2d pos,float moveSpd):
|
||||
pos(pos),moveSpd(moveSpd){};
|
||||
};
|
||||
|
||||
class Crawler : public olc::PixelGameEngine
|
||||
{
|
||||
const vi2d WORLD_SIZE={64,64};
|
||||
Camera2D camera;
|
||||
TileTransformedView view;
|
||||
Player player=Player{{},100};
|
||||
|
||||
public:
|
||||
Crawler()
|
||||
{
|
||||
sAppName = "Crawler Concept";
|
||||
}
|
||||
|
||||
public:
|
||||
bool OnUserCreate() override
|
||||
{
|
||||
camera=Camera2D{WINDOW_SIZE};
|
||||
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
|
||||
camera.SetTarget(player.pos);
|
||||
camera.SetWorldBoundary({0,0},WORLD_SIZE*24);
|
||||
camera.EnableWorldBoundary(true);
|
||||
view=TileTransformedView{GetScreenSize(),{1,1}};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnUserUpdate(float fElapsedTime) override
|
||||
{
|
||||
if(GetKey(RIGHT).bHeld){
|
||||
player.pos.x+=fElapsedTime*player.moveSpd;
|
||||
}
|
||||
if(GetKey(LEFT).bHeld){
|
||||
player.pos.x-=fElapsedTime*player.moveSpd;
|
||||
}
|
||||
if(GetKey(UP).bHeld){
|
||||
player.pos.y-=fElapsedTime*player.moveSpd;
|
||||
}
|
||||
if(GetKey(DOWN).bHeld){
|
||||
player.pos.y+=fElapsedTime*player.moveSpd;
|
||||
}
|
||||
|
||||
camera.Update(fElapsedTime);
|
||||
view.SetWorldOffset(camera.GetViewPosition());
|
||||
//view.HandlePanAndZoom();
|
||||
// called once per frame
|
||||
Clear(BLACK);
|
||||
for (int x = view.GetTopLeftTile().x/24; x <= view.GetBottomRightTile().x/24; x++){
|
||||
for (int y = view.GetTopLeftTile().y/24; y <= view.GetBottomRightTile().y/24; y++){
|
||||
view.DrawRect(vi2d{x,y}*24,{24,24},DARK_GREY);
|
||||
}
|
||||
}
|
||||
view.DrawCircle(player.pos,8);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Crawler demo;
|
||||
if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4))
|
||||
demo.Start();
|
||||
|
||||
return 0;
|
||||
}
|
746
Crawler/olcPGEX_TransformedView.h
Normal file
746
Crawler/olcPGEX_TransformedView.h
Normal file
@ -0,0 +1,746 @@
|
||||
/*
|
||||
olcPGEX_TransformedView.h
|
||||
|
||||
+-------------------------------------------------------------+
|
||||
| OneLoneCoder Pixel Game Engine Extension |
|
||||
| Transformed View v1.08 |
|
||||
+-------------------------------------------------------------+
|
||||
|
||||
NOTE: UNDER ACTIVE DEVELOPMENT - THERE ARE BUGS/GLITCHES
|
||||
|
||||
What is this?
|
||||
~~~~~~~~~~~~~
|
||||
This extension provides drawing routines that are compatible with
|
||||
changeable world and screen spaces. For example you can pan and
|
||||
zoom, and all PGE drawing routines will automatically adopt the current
|
||||
world scales and offsets.
|
||||
|
||||
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, <EFBFBD>OneLoneCoder 2019, 2020, 2021, 2022
|
||||
|
||||
Revisions:
|
||||
1.00: Initial Release
|
||||
1.01: Fix for rounding error when scaling to screen
|
||||
1.02: Added DrawLineDecal for convenience
|
||||
1.03: Removed std::floor from WorldToScreen()
|
||||
Added HandlePanAndZoom(...) convenience function
|
||||
Removed unused "range" facility in TileTransformView
|
||||
1.04: Added DrawPolygonDecal() for arbitrary polygons
|
||||
1.05: Clipped DrawSprite() to visible area, massive performance increase
|
||||
1.06: Fixed error in DrawLine() - Thanks CraisyDaisyRecords (& Fern)!
|
||||
1.07: +DrawRectDecal()
|
||||
+GetPGE()
|
||||
1.08: +DrawPolygonDecal() with tint overload, akin to PGE
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef OLC_PGEX_TRANSFORMEDVIEW_H
|
||||
#define OLC_PGEX_TRANSFORMEDVIEW_H
|
||||
|
||||
#include "olcPixelGameEngine.h"
|
||||
|
||||
|
||||
|
||||
namespace olc
|
||||
{
|
||||
class TransformedView : public olc::PGEX
|
||||
{
|
||||
public:
|
||||
TransformedView() = default;
|
||||
virtual void Initialise(const olc::vi2d& vViewArea, const olc::vf2d& vPixelScale = { 1.0f, 1.0f });
|
||||
|
||||
olc::PixelGameEngine* GetPGE();
|
||||
|
||||
public:
|
||||
void SetWorldOffset(const olc::vf2d& vOffset);
|
||||
void MoveWorldOffset(const olc::vf2d& vDeltaOffset);
|
||||
void SetWorldScale(const olc::vf2d& vScale);
|
||||
void SetViewArea(const olc::vi2d& vViewArea);
|
||||
olc::vf2d GetWorldTL() const;
|
||||
olc::vf2d GetWorldBR() const;
|
||||
olc::vf2d GetWorldVisibleArea() const;
|
||||
void ZoomAtScreenPos(const float fDeltaZoom, const olc::vi2d& vPos);
|
||||
void SetZoom(const float fZoom, const olc::vf2d& vPos);
|
||||
void StartPan(const olc::vi2d& vPos);
|
||||
void UpdatePan(const olc::vi2d& vPos);
|
||||
void EndPan(const olc::vi2d& vPos);
|
||||
const olc::vf2d& GetWorldOffset() const;
|
||||
const olc::vf2d& GetWorldScale() const;
|
||||
virtual olc::vf2d WorldToScreen(const olc::vf2d& vWorldPos) const;
|
||||
virtual olc::vf2d ScreenToWorld(const olc::vf2d& vScreenPos) const;
|
||||
virtual olc::vf2d ScaleToWorld(const olc::vf2d& vScreenSize) const;
|
||||
virtual olc::vf2d ScaleToScreen(const olc::vf2d& vWorldSize) const;
|
||||
virtual bool IsPointVisible(const olc::vf2d& vPos) const;
|
||||
virtual bool IsRectVisible(const olc::vf2d& vPos, const olc::vf2d& vSize) const;
|
||||
virtual void HandlePanAndZoom(const int nMouseButton = 2, const float fZoomRate = 0.1f, const bool bPan = true, const bool bZoom = true);
|
||||
protected:
|
||||
olc::vf2d m_vWorldOffset = { 0.0f, 0.0f };
|
||||
olc::vf2d m_vWorldScale = { 1.0f, 1.0f };
|
||||
olc::vf2d m_vRecipPixel = { 1.0f, 1.0f };
|
||||
olc::vf2d m_vPixelScale = { 1.0f, 1.0f };
|
||||
bool m_bPanning = false;
|
||||
olc::vf2d m_vStartPan = { 0.0f, 0.0f };
|
||||
olc::vi2d m_vViewArea;
|
||||
|
||||
public: // Hopefully, these should look familiar!
|
||||
// Plots a single point
|
||||
virtual bool Draw(float x, float y, olc::Pixel p = olc::WHITE);
|
||||
bool Draw(const olc::vf2d& pos, olc::Pixel p = olc::WHITE);
|
||||
// Draws a line from (x1,y1) to (x2,y2)
|
||||
void DrawLine(float x1, float y1, float x2, float y2, olc::Pixel p = olc::WHITE, uint32_t pattern = 0xFFFFFFFF);
|
||||
void DrawLine(const olc::vf2d& pos1, const olc::vf2d& pos2, olc::Pixel p = olc::WHITE, uint32_t pattern = 0xFFFFFFFF);
|
||||
// Draws a circle located at (x,y) with radius
|
||||
void DrawCircle(float x, float y, float radius, olc::Pixel p = olc::WHITE, uint8_t mask = 0xFF);
|
||||
void DrawCircle(const olc::vf2d& pos, float radius, olc::Pixel p = olc::WHITE, uint8_t mask = 0xFF);
|
||||
// Fills a circle located at (x,y) with radius
|
||||
void FillCircle(float x, float y, float radius, olc::Pixel p = olc::WHITE);
|
||||
void FillCircle(const olc::vf2d& pos, float radius, olc::Pixel p = olc::WHITE);
|
||||
// Draws a rectangle at (x,y) to (x+w,y+h)
|
||||
void DrawRect(float x, float y, float w, float h, olc::Pixel p = olc::WHITE);
|
||||
void DrawRect(const olc::vf2d& pos, const olc::vf2d& size, olc::Pixel p = olc::WHITE);
|
||||
// Fills a rectangle at (x,y) to (x+w,y+h)
|
||||
void FillRect(float x, float y, float w, float h, olc::Pixel p = olc::WHITE);
|
||||
void FillRect(const olc::vf2d& pos, const olc::vf2d& size, olc::Pixel p = olc::WHITE);
|
||||
// Draws a triangle between points (x1,y1), (x2,y2) and (x3,y3)
|
||||
void DrawTriangle(float x1, float y1, float x2, float y2, float x3, float y3, olc::Pixel p = olc::WHITE);
|
||||
void DrawTriangle(const olc::vf2d& pos1, const olc::vf2d& pos2, const olc::vf2d& pos3, olc::Pixel p = olc::WHITE);
|
||||
// Flat fills a triangle between points (x1,y1), (x2,y2) and (x3,y3)
|
||||
void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3, olc::Pixel p = olc::WHITE);
|
||||
void FillTriangle(const olc::vf2d& pos1, const olc::vf2d& pos2, const olc::vf2d& pos3, olc::Pixel p = olc::WHITE);
|
||||
// Draws an entire sprite at location (x,y)
|
||||
void DrawSprite(float x, float y, olc::Sprite* sprite, float scalex = 1, float scaley = 1, uint8_t flip = olc::Sprite::NONE);
|
||||
void DrawSprite(const olc::vf2d& pos, olc::Sprite* sprite, const olc::vf2d& scale = { 1.0f, 1.0f }, uint8_t flip = olc::Sprite::NONE);
|
||||
// Draws an area of a sprite at location (x,y), where the
|
||||
// selected area is (ox,oy) to (ox+w,oy+h)
|
||||
void DrawPartialSprite(float x, float y, Sprite* sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, float scalex = 1, float scaley = 1, uint8_t flip = olc::Sprite::NONE);
|
||||
void DrawPartialSprite(const olc::vf2d& pos, Sprite* sprite, const olc::vi2d& sourcepos, const olc::vi2d& size, const olc::vf2d& scale = { 1.0f, 1.0f }, uint8_t flip = olc::Sprite::NONE);
|
||||
void DrawString(float x, float y, const std::string& sText, Pixel col, const olc::vf2d& scale);
|
||||
void DrawString(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale);
|
||||
|
||||
|
||||
// Draws a whole decal, with optional scale and tinting
|
||||
void DrawDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
|
||||
// Draws a region of a decal, with optional scale and tinting
|
||||
void DrawPartialDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawPartialDecal(const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
|
||||
// Draws fully user controlled 4 vertices, pos(pixels), uv(pixels), colours
|
||||
void DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements = 4);
|
||||
//// Draws a decal with 4 arbitrary points, warping the texture to look "correct"
|
||||
void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawWarpedDecal(olc::Decal* decal, const std::array<olc::vf2d, 4>& pos, const olc::Pixel& tint = olc::WHITE);
|
||||
//// As above, but you can specify a region of a decal source sprite
|
||||
void DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawPartialWarpedDecal(olc::Decal* decal, const std::array<olc::vf2d, 4>& pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
|
||||
//// Draws a decal rotated to specified angle, wit point of rotation offset
|
||||
void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE);
|
||||
// Draws a multiline string as a decal, with tiniting and scaling
|
||||
void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
|
||||
void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
|
||||
// Draws a single shaded filled rectangle as a decal
|
||||
void FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE);
|
||||
void DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE);
|
||||
|
||||
// Draws a corner shaded rectangle as a decal
|
||||
void GradientFillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel colTL, const olc::Pixel colBL, const olc::Pixel colBR, const olc::Pixel colTR);
|
||||
// Draws an arbitrary convex textured polygon using GPU
|
||||
void DrawPolygonDecal(olc::Decal* decal, const std::vector<olc::vf2d>& pos, const std::vector<olc::vf2d>& uv, const olc::Pixel tint = olc::WHITE);
|
||||
void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE);
|
||||
void DrawPolygonDecal(olc::Decal* decal, const std::vector<olc::vf2d>&pos, const std::vector<olc::vf2d>&uv, const std::vector<olc::Pixel> &tint);
|
||||
void DrawPolygonDecal(olc::Decal* decal, const std::vector<olc::vf2d>& pos, const std::vector<olc::vf2d>& uv, const std::vector<olc::Pixel>& colours, const olc::Pixel tint);
|
||||
|
||||
|
||||
#if defined(OLC_PGEX_SHADER)
|
||||
// Shader Specific
|
||||
void DrawDecal(olc::Shade& shader, const olc::vf2d & pos, olc::Decal * decal, const olc::vf2d & scale = { 1.0f,1.0f }, const olc::Pixel & tint = olc::WHITE);
|
||||
void DrawPartialDecal(olc::Shade& shader, const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
|
||||
void DrawPartialDecal(olc::Shade& shader, const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint = olc::WHITE);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
class TileTransformedView : public TransformedView
|
||||
{
|
||||
public:
|
||||
TileTransformedView() = default;
|
||||
TileTransformedView(const olc::vi2d& vViewArea, const olc::vi2d& vTileSize);
|
||||
|
||||
public:
|
||||
olc::vi2d GetTopLeftTile() const;
|
||||
olc::vi2d GetBottomRightTile() const;
|
||||
olc::vi2d GetVisibleTiles() const;
|
||||
olc::vi2d GetTileUnderScreenPos(const olc::vi2d& vPos) const;
|
||||
const olc::vi2d GetTileOffset() const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef OLC_PGEX_TRANSFORMEDVIEW
|
||||
#undef OLC_PGEX_TRANSFORMEDVIEW
|
||||
|
||||
namespace olc
|
||||
{
|
||||
olc::PixelGameEngine* TransformedView::GetPGE()
|
||||
{
|
||||
return pge;
|
||||
}
|
||||
|
||||
void TransformedView::Initialise(const olc::vi2d& vViewArea, const olc::vf2d& vPixelScale)
|
||||
{
|
||||
SetViewArea(vViewArea);
|
||||
SetWorldScale(vPixelScale);
|
||||
m_vPixelScale = vPixelScale;
|
||||
m_vRecipPixel = 1.0f / m_vPixelScale;
|
||||
}
|
||||
|
||||
void TransformedView::SetWorldOffset(const olc::vf2d& vOffset)
|
||||
{
|
||||
m_vWorldOffset = vOffset;
|
||||
}
|
||||
|
||||
void TransformedView::MoveWorldOffset(const olc::vf2d& vDeltaOffset)
|
||||
{
|
||||
m_vWorldOffset += vDeltaOffset;
|
||||
}
|
||||
|
||||
void TransformedView::SetWorldScale(const olc::vf2d& vScale)
|
||||
{
|
||||
m_vWorldScale = vScale;
|
||||
}
|
||||
|
||||
void TransformedView::SetViewArea(const olc::vi2d& vViewArea)
|
||||
{
|
||||
m_vViewArea = vViewArea;
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::GetWorldTL() const
|
||||
{
|
||||
return TransformedView::ScreenToWorld({ 0,0 });
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::GetWorldBR() const
|
||||
{
|
||||
return TransformedView::ScreenToWorld(m_vViewArea);
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::GetWorldVisibleArea() const
|
||||
{
|
||||
return GetWorldBR() - GetWorldTL();
|
||||
}
|
||||
|
||||
void TransformedView::ZoomAtScreenPos(const float fDeltaZoom, const olc::vi2d& vPos)
|
||||
{
|
||||
olc::vf2d vOffsetBeforeZoom = ScreenToWorld(vPos);
|
||||
m_vWorldScale *= fDeltaZoom;
|
||||
olc::vf2d vOffsetAfterZoom = ScreenToWorld(vPos);
|
||||
m_vWorldOffset += vOffsetBeforeZoom - vOffsetAfterZoom;
|
||||
}
|
||||
|
||||
void TransformedView::SetZoom(const float fZoom, const olc::vf2d& vPos)
|
||||
{
|
||||
olc::vf2d vOffsetBeforeZoom = ScreenToWorld(vPos);
|
||||
m_vWorldScale = { fZoom, fZoom };
|
||||
olc::vf2d vOffsetAfterZoom = ScreenToWorld(vPos);
|
||||
m_vWorldOffset += vOffsetBeforeZoom - vOffsetAfterZoom;
|
||||
}
|
||||
|
||||
void TransformedView::StartPan(const olc::vi2d& vPos)
|
||||
{
|
||||
m_bPanning = true;
|
||||
m_vStartPan = olc::vf2d(vPos);
|
||||
}
|
||||
|
||||
void TransformedView::UpdatePan(const olc::vi2d& vPos)
|
||||
{
|
||||
if (m_bPanning)
|
||||
{
|
||||
m_vWorldOffset -= (olc::vf2d(vPos) - m_vStartPan) / m_vWorldScale;
|
||||
m_vStartPan = olc::vf2d(vPos);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformedView::EndPan(const olc::vi2d& vPos)
|
||||
{
|
||||
UpdatePan(vPos);
|
||||
m_bPanning = false;
|
||||
}
|
||||
|
||||
const olc::vf2d& TransformedView::GetWorldOffset() const
|
||||
{
|
||||
return m_vWorldOffset;
|
||||
}
|
||||
|
||||
const olc::vf2d& TransformedView::GetWorldScale() const
|
||||
{
|
||||
return m_vWorldScale;
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::WorldToScreen(const olc::vf2d& vWorldPos) const
|
||||
{
|
||||
olc::vf2d vFloat = ((vWorldPos - m_vWorldOffset) * m_vWorldScale);
|
||||
//vFloat = { std::floor(vFloat.x + 0.5f), std::floor(vFloat.y + 0.5f) };
|
||||
return vFloat;
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::ScreenToWorld(const olc::vf2d& vScreenPos) const
|
||||
{
|
||||
return (olc::vf2d(vScreenPos) / m_vWorldScale) + m_vWorldOffset;
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::ScaleToWorld(const olc::vf2d& vScreenSize) const
|
||||
{
|
||||
return (olc::vf2d(vScreenSize) / m_vWorldScale);
|
||||
}
|
||||
|
||||
olc::vf2d TransformedView::ScaleToScreen(const olc::vf2d& vWorldSize) const
|
||||
{
|
||||
//olc::vf2d vFloat = (vWorldSize * m_vWorldScale) + olc::vf2d(0.5f, 0.5f);
|
||||
//return vFloat.floor();
|
||||
return (vWorldSize * m_vWorldScale);
|
||||
}
|
||||
|
||||
bool TransformedView::IsPointVisible(const olc::vf2d & vPos) const
|
||||
{
|
||||
olc::vi2d vScreen = WorldToScreen(vPos);
|
||||
return vScreen.x >= 0 && vScreen.x < m_vViewArea.x&& vScreen.y >= 0 && vScreen.y < m_vViewArea.y;
|
||||
}
|
||||
|
||||
bool TransformedView::IsRectVisible(const olc::vf2d& vPos, const olc::vf2d& vSize) const
|
||||
{
|
||||
olc::vi2d vScreenPos = WorldToScreen(vPos);
|
||||
olc::vi2d vScreenSize = vSize * m_vWorldScale;
|
||||
return (vScreenPos.x < 0 + m_vViewArea.x && vScreenPos.x + vScreenSize.x > 0 && vScreenPos.y < m_vViewArea.y&& vScreenPos.y + vScreenSize.y > 0);
|
||||
}
|
||||
|
||||
void TransformedView::HandlePanAndZoom(const int nMouseButton, const float fZoomRate, const bool bPan, const bool bZoom)
|
||||
{
|
||||
const auto& vMousePos = pge->GetMousePos();
|
||||
if (bPan)
|
||||
{
|
||||
if (pge->GetMouse(nMouseButton).bPressed) StartPan(vMousePos);
|
||||
if (pge->GetMouse(nMouseButton).bHeld) UpdatePan(vMousePos);
|
||||
if (pge->GetMouse(nMouseButton).bReleased) EndPan(vMousePos);
|
||||
}
|
||||
|
||||
if (bZoom)
|
||||
{
|
||||
if (pge->GetMouseWheel() > 0) ZoomAtScreenPos(1.0f + fZoomRate, vMousePos);
|
||||
if (pge->GetMouseWheel() < 0) ZoomAtScreenPos(1.0f - fZoomRate, vMousePos);
|
||||
}
|
||||
}
|
||||
|
||||
bool TransformedView::Draw(float x, float y, olc::Pixel p)
|
||||
{
|
||||
return Draw({ x, y }, p);
|
||||
}
|
||||
|
||||
bool TransformedView::Draw(const olc::vf2d & pos, olc::Pixel p)
|
||||
{
|
||||
return pge->Draw(WorldToScreen(pos), p);
|
||||
}
|
||||
|
||||
void TransformedView::DrawLine(float x1, float y1, float x2, float y2, olc::Pixel p, uint32_t pattern)
|
||||
{
|
||||
DrawLine({ x1, y1 }, { x2, y2 }, p, pattern);
|
||||
}
|
||||
|
||||
void TransformedView::DrawLine(const olc::vf2d & pos1, const olc::vf2d & pos2, olc::Pixel p, uint32_t pattern)
|
||||
{
|
||||
pge->DrawLine(WorldToScreen(pos1), WorldToScreen(pos2), p, pattern);
|
||||
}
|
||||
|
||||
void TransformedView::DrawCircle(float x, float y, float radius, olc::Pixel p, uint8_t mask)
|
||||
{
|
||||
DrawCircle({ x,y }, radius, p, mask);
|
||||
}
|
||||
|
||||
void TransformedView::DrawCircle(const olc::vf2d & pos, float radius, olc::Pixel p, uint8_t mask)
|
||||
{
|
||||
pge->DrawCircle(WorldToScreen(pos), int32_t(radius * m_vWorldScale.x), p, mask);
|
||||
}
|
||||
|
||||
void TransformedView::FillCircle(float x, float y, float radius, olc::Pixel p)
|
||||
{
|
||||
FillCircle({ x,y }, radius, p);
|
||||
}
|
||||
|
||||
void TransformedView::FillCircle(const olc::vf2d & pos, float radius, olc::Pixel p)
|
||||
{
|
||||
pge->FillCircle(WorldToScreen(pos), int32_t(radius * m_vWorldScale.x), p);
|
||||
}
|
||||
|
||||
void TransformedView::DrawRect(float x, float y, float w, float h, olc::Pixel p)
|
||||
{
|
||||
DrawRect({ x, y }, { w, h }, p);
|
||||
}
|
||||
|
||||
void TransformedView::DrawRect(const olc::vf2d & pos, const olc::vf2d & size, olc::Pixel p)
|
||||
{
|
||||
pge->DrawRect(WorldToScreen(pos), ((size * m_vWorldScale) + olc::vf2d(0.5f, 0.5f)).floor(), p);
|
||||
}
|
||||
|
||||
void TransformedView::FillRect(float x, float y, float w, float h, olc::Pixel p)
|
||||
{
|
||||
FillRect({ x, y }, { w, h }, p);
|
||||
}
|
||||
|
||||
void TransformedView::FillRect(const olc::vf2d & pos, const olc::vf2d & size, olc::Pixel p)
|
||||
{
|
||||
pge->FillRect(WorldToScreen(pos), size * m_vWorldScale, p);
|
||||
}
|
||||
|
||||
void TransformedView::DrawTriangle(float x1, float y1, float x2, float y2, float x3, float y3, olc::Pixel p)
|
||||
{
|
||||
DrawTriangle({ x1, y1 }, { x2, y2 }, { x3, y3 }, p);
|
||||
}
|
||||
|
||||
void TransformedView::DrawTriangle(const olc::vf2d & pos1, const olc::vf2d & pos2, const olc::vf2d & pos3, olc::Pixel p)
|
||||
{
|
||||
pge->DrawTriangle(WorldToScreen(pos1), WorldToScreen(pos2), WorldToScreen(pos3), p);
|
||||
}
|
||||
|
||||
void TransformedView::FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3, olc::Pixel p)
|
||||
{
|
||||
FillTriangle({ x1, y1 }, { x2, y2 }, { x3, y3 }, p);
|
||||
}
|
||||
|
||||
void TransformedView::FillTriangle(const olc::vf2d & pos1, const olc::vf2d & pos2, const olc::vf2d & pos3, olc::Pixel p)
|
||||
{
|
||||
pge->FillTriangle(WorldToScreen(pos1), WorldToScreen(pos2), WorldToScreen(pos3), p);
|
||||
}
|
||||
|
||||
void TransformedView::DrawSprite(float x, float y, olc::Sprite* sprite, float scalex, float scaley, uint8_t flip)
|
||||
{
|
||||
DrawSprite({ x, y }, sprite, { scalex, scaley }, flip);
|
||||
}
|
||||
|
||||
void TransformedView::DrawSprite(const olc::vf2d & pos, olc::Sprite * sprite, const olc::vf2d & scale, uint8_t flip)
|
||||
{
|
||||
olc::vf2d vSpriteSize = olc::vf2d(float(sprite->width), float(sprite->height));
|
||||
if (IsRectVisible(pos, vSpriteSize * scale))
|
||||
{
|
||||
olc::vf2d vSpriteScaledSize = vSpriteSize * m_vRecipPixel * m_vWorldScale * scale;
|
||||
olc::vi2d vPixel;
|
||||
olc::vi2d vSpritePixelStart = WorldToScreen(pos);
|
||||
olc::vi2d vSpritePixelEnd = WorldToScreen((vSpriteSize * scale) + pos);
|
||||
|
||||
olc::vi2d vScreenPixelStart = (vSpritePixelStart).max({0,0});
|
||||
olc::vi2d vScreenPixelEnd = (vSpritePixelEnd).min({ pge->ScreenWidth(),pge->ScreenHeight() });
|
||||
|
||||
olc::vf2d vPixelStep = 1.0f / vSpriteScaledSize;
|
||||
|
||||
for (vPixel.y = vScreenPixelStart.y; vPixel.y < vScreenPixelEnd.y; vPixel.y++)
|
||||
{
|
||||
for (vPixel.x = vScreenPixelStart.x; vPixel.x < vScreenPixelEnd.x; vPixel.x++)
|
||||
{
|
||||
olc::vf2d vSample = olc::vf2d(vPixel - vSpritePixelStart) * vPixelStep;
|
||||
pge->Draw(vPixel, sprite->Sample(vSample.x, vSample.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TransformedView::DrawPartialSprite(float x, float y, Sprite* sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, float scalex, float scaley, uint8_t flip)
|
||||
{
|
||||
DrawPartialSprite({ x,y }, sprite, { ox,oy }, { w, h }, { scalex, scaley }, flip);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialSprite(const olc::vf2d& pos, Sprite* sprite, const olc::vi2d& sourcepos, const olc::vi2d& size, const olc::vf2d& scale, uint8_t flip)
|
||||
{
|
||||
olc::vf2d vSpriteSize = size;
|
||||
if (IsRectVisible(pos, size * scale))
|
||||
{
|
||||
olc::vf2d vSpriteScaledSize = olc::vf2d(size) * m_vRecipPixel * m_vWorldScale * scale;
|
||||
olc::vf2d vSpritePixelStep = 1.0f / olc::vf2d(float(sprite->width), float(sprite->height));
|
||||
olc::vi2d vPixel, vStart = WorldToScreen(pos), vEnd = vSpriteScaledSize + vStart;
|
||||
olc::vf2d vScreenPixelStep = 1.0f / vSpriteScaledSize;
|
||||
|
||||
for (vPixel.y = vStart.y; vPixel.y < vEnd.y; vPixel.y++)
|
||||
{
|
||||
for (vPixel.x = vStart.x; vPixel.x < vEnd.x; vPixel.x++)
|
||||
{
|
||||
olc::vf2d vSample = ((olc::vf2d(vPixel - vStart) * vScreenPixelStep) * size * vSpritePixelStep) + olc::vf2d(sourcepos) * vSpritePixelStep;
|
||||
pge->Draw(vPixel, sprite->Sample(vSample.x, vSample.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransformedView::DrawString(float x, float y, const std::string& sText, Pixel col, const olc::vf2d& scale)
|
||||
{
|
||||
DrawString({ x, y }, sText, col, scale);
|
||||
}
|
||||
|
||||
void TransformedView::DrawString(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale)
|
||||
{
|
||||
olc::vf2d vOffset = { 0.0f, 0.0f };
|
||||
Pixel::Mode m = pge->GetPixelMode();
|
||||
|
||||
auto StringPlot = [&col](const int x, const int y, const olc::Pixel& pSource, const olc::Pixel& pDest)
|
||||
{
|
||||
return pSource.r > 1 ? col : pDest;
|
||||
};
|
||||
|
||||
pge->SetPixelMode(StringPlot);
|
||||
|
||||
for (auto c : sText)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
vOffset.x = 0.0f; vOffset.y += 8.0f * m_vRecipPixel.y * scale.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
int32_t ox = ((c - 32) % 16) * 8;
|
||||
int32_t oy = ((c - 32) / 16) * 8;
|
||||
DrawPartialSprite(pos + vOffset, pge->GetFontSprite(), { ox, oy }, { 8, 8 }, scale);
|
||||
vOffset.x += 8.0f * m_vRecipPixel.x * scale.x;
|
||||
}
|
||||
}
|
||||
pge->SetPixelMode(m);
|
||||
}
|
||||
|
||||
|
||||
void TransformedView::DrawDecal(const olc::vf2d & pos, olc::Decal * decal, const olc::vf2d & scale, const olc::Pixel & tint)
|
||||
{
|
||||
pge->DrawDecal(WorldToScreen(pos), decal, scale * m_vWorldScale * m_vRecipPixel, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialDecal(const olc::vf2d & pos, olc::Decal * decal, const olc::vf2d & source_pos, const olc::vf2d & source_size, const olc::vf2d & scale, const olc::Pixel & tint)
|
||||
{
|
||||
pge->DrawPartialDecal(WorldToScreen(pos), decal, source_pos, source_size, scale * m_vWorldScale * m_vRecipPixel, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialDecal(const olc::vf2d & pos, const olc::vf2d & size, olc::Decal * decal, const olc::vf2d & source_pos, const olc::vf2d & source_size, const olc::Pixel & tint)
|
||||
{
|
||||
pge->DrawPartialDecal(WorldToScreen(pos), size * m_vWorldScale * m_vRecipPixel, decal, source_pos, source_size, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawExplicitDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d* uv, const olc::Pixel* col, uint32_t elements)
|
||||
{
|
||||
std::vector<olc::vf2d> vTransformed(elements);
|
||||
for (uint32_t n = 0; n < elements; n++)
|
||||
vTransformed[n] = WorldToScreen(pos[n]);
|
||||
pge->DrawExplicitDecal(decal, vTransformed.data(), uv, col, elements);
|
||||
}
|
||||
|
||||
void TransformedView::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint)
|
||||
{
|
||||
std::array<olc::vf2d, 4> vTransformed =
|
||||
{ {
|
||||
WorldToScreen(pos[0]), WorldToScreen(pos[1]),
|
||||
WorldToScreen(pos[2]), WorldToScreen(pos[3]),
|
||||
} };
|
||||
|
||||
pge->DrawWarpedDecal(decal, vTransformed, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint)
|
||||
{
|
||||
DrawWarpedDecal(decal, &pos[0], tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawWarpedDecal(olc::Decal* decal, const std::array<olc::vf2d, 4>& pos, const olc::Pixel& tint)
|
||||
{
|
||||
DrawWarpedDecal(decal, pos.data(), tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint)
|
||||
{
|
||||
DrawPartialWarpedDecal(decal, &pos[0], source_pos, source_size, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint)
|
||||
{
|
||||
std::array<olc::vf2d, 4> vTransformed =
|
||||
{ {
|
||||
WorldToScreen(pos[0]), WorldToScreen(pos[1]),
|
||||
WorldToScreen(pos[2]), WorldToScreen(pos[3]),
|
||||
} };
|
||||
|
||||
pge->DrawPartialWarpedDecal(decal, vTransformed, source_pos, source_size, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialWarpedDecal(olc::Decal* decal, const std::array<olc::vf2d, 4>& pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint)
|
||||
{
|
||||
DrawPartialWarpedDecal(decal, pos.data(), source_pos, source_size, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawRotatedDecal(const olc::vf2d & pos, olc::Decal * decal, const float fAngle, const olc::vf2d & center, const olc::vf2d & scale, const olc::Pixel & tint)
|
||||
{
|
||||
pge->DrawRotatedDecal(WorldToScreen(pos), decal, fAngle, center, scale * m_vWorldScale * m_vRecipPixel, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialRotatedDecal(const olc::vf2d & pos, olc::Decal * decal, const float fAngle, const olc::vf2d & center, const olc::vf2d & source_pos, const olc::vf2d & source_size, const olc::vf2d & scale, const olc::Pixel & tint)
|
||||
{
|
||||
pge->DrawPartialRotatedDecal(WorldToScreen(pos), decal, fAngle, center, source_pos, source_size, scale * m_vWorldScale * m_vRecipPixel, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawStringDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::vf2d & scale)
|
||||
{
|
||||
pge->DrawStringDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel);
|
||||
}
|
||||
|
||||
void TransformedView::DrawStringPropDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::vf2d & scale )
|
||||
{
|
||||
pge->DrawStringPropDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel);
|
||||
}
|
||||
|
||||
void TransformedView::FillRectDecal(const olc::vf2d & pos, const olc::vf2d & size, const olc::Pixel col)
|
||||
{
|
||||
pge->FillRectDecal(WorldToScreen(pos), (size * m_vWorldScale).ceil(), col);
|
||||
}
|
||||
|
||||
void TransformedView::DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col)
|
||||
{
|
||||
pge->DrawRectDecal(WorldToScreen(pos), (size * m_vWorldScale).ceil(), col);
|
||||
}
|
||||
|
||||
void TransformedView::DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p)
|
||||
{
|
||||
pge->DrawLineDecal(WorldToScreen(pos1), WorldToScreen(pos2), p);
|
||||
}
|
||||
|
||||
void TransformedView::GradientFillRectDecal(const olc::vf2d & pos, const olc::vf2d & size, const olc::Pixel colTL, const olc::Pixel colBL, const olc::Pixel colBR, const olc::Pixel colTR)
|
||||
{
|
||||
pge->GradientFillRectDecal(WorldToScreen(pos), size * m_vWorldScale, colTL, colBL, colBR, colTR);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPolygonDecal(olc::Decal* decal, const std::vector<olc::vf2d>& pos, const std::vector<olc::vf2d>& uv, const olc::Pixel tint)
|
||||
{
|
||||
std::vector<olc::vf2d> vTransformed(pos.size());
|
||||
for (uint32_t n = 0; n < pos.size(); n++)
|
||||
vTransformed[n] = WorldToScreen(pos[n]);
|
||||
pge->DrawPolygonDecal(decal, vTransformed, uv, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPolygonDecal(olc::Decal* decal, const std::vector<olc::vf2d>& pos, const std::vector<olc::vf2d>& uv, const std::vector<olc::Pixel> &tint)
|
||||
{
|
||||
std::vector<olc::vf2d> vTransformed(pos.size());
|
||||
for (uint32_t n = 0; n < pos.size(); n++)
|
||||
vTransformed[n] = WorldToScreen(pos[n]);
|
||||
pge->DrawPolygonDecal(decal, vTransformed, uv, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPolygonDecal(olc::Decal* decal, const std::vector<olc::vf2d>& pos, const std::vector<olc::vf2d>& uv, const std::vector<olc::Pixel>& colours, const olc::Pixel tint)
|
||||
{
|
||||
std::vector<olc::vf2d> vTransformed(pos.size());
|
||||
for (uint32_t n = 0; n < pos.size(); n++)
|
||||
vTransformed[n] = WorldToScreen(pos[n]);
|
||||
pge->DrawPolygonDecal(decal, vTransformed, uv, colours, tint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined (OLC_PGEX_SHADER)
|
||||
|
||||
void TransformedView::DrawDecal(olc::Shade &shade, const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& scale, const olc::Pixel& tint)
|
||||
{
|
||||
shade.DrawDecal(WorldToScreen(pos), decal, scale * m_vWorldScale * m_vRecipPixel, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialDecal(olc::Shade& shade, const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale, const olc::Pixel& tint)
|
||||
{
|
||||
shade.DrawPartialDecal(WorldToScreen(pos), decal, source_pos, source_size, scale * m_vWorldScale * m_vRecipPixel, tint);
|
||||
}
|
||||
|
||||
void TransformedView::DrawPartialDecal(olc::Shade& shade, const olc::vf2d& pos, const olc::vf2d& size, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint)
|
||||
{
|
||||
shade.DrawPartialDecal(WorldToScreen(pos), size * m_vWorldScale * m_vRecipPixel, decal, source_pos, source_size, tint);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
TileTransformedView::TileTransformedView(const olc::vi2d& vViewArea, const olc::vi2d& vTileSize)
|
||||
{
|
||||
Initialise(vViewArea, vTileSize);
|
||||
}
|
||||
|
||||
|
||||
olc::vi2d TileTransformedView::GetTopLeftTile() const
|
||||
{
|
||||
return ScreenToWorld({ 0,0 }).floor();
|
||||
}
|
||||
|
||||
olc::vi2d TileTransformedView::GetBottomRightTile() const
|
||||
{
|
||||
return ScreenToWorld(m_vViewArea).ceil();
|
||||
}
|
||||
|
||||
olc::vi2d TileTransformedView::GetVisibleTiles() const
|
||||
{
|
||||
return GetBottomRightTile() - GetTopLeftTile();
|
||||
}
|
||||
|
||||
olc::vi2d TileTransformedView::GetTileUnderScreenPos(const olc::vi2d& vPos) const
|
||||
{
|
||||
return ScreenToWorld(vPos).floor();
|
||||
}
|
||||
|
||||
const olc::vi2d TileTransformedView::GetTileOffset() const
|
||||
{
|
||||
return { int32_t((m_vWorldOffset.x - std::floor(m_vWorldOffset.x)) * m_vWorldScale.x),
|
||||
int32_t((m_vWorldOffset.y - std::floor(m_vWorldOffset.y)) * m_vWorldScale.y) };
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
6695
Crawler/olcPixelGameEngine.h
Normal file
6695
Crawler/olcPixelGameEngine.h
Normal file
File diff suppressed because it is too large
Load Diff
212
Crawler/olcUTIL_Animate2D.h
Normal file
212
Crawler/olcUTIL_Animate2D.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
OneLoneCoder - Animate2D v1.00
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Handles animated Sprites efficiently
|
||||
|
||||
|
||||
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, <EFBFBD>OneLoneCoder 2019, 2020, 2021, 2022
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "olcPixelGameEngine.h"
|
||||
#include "utilities/olcUTIL_Geometry2D.h"
|
||||
|
||||
namespace olc::utils::Animate2D
|
||||
{
|
||||
// This class rerpresents a valid "frame" of an animation. It could be from any image source, and
|
||||
// any location withing that image source. Once it's constructed, it's advised not to change it, as
|
||||
// this likely indicates a usage bug.
|
||||
//
|
||||
// "Sourceless" frames are valid too - this is useful if you have a particular animation set, but
|
||||
// want to apply it to a variety of sources, for example sprite maps with common layouts.
|
||||
class Frame
|
||||
{
|
||||
public:
|
||||
inline Frame(const olc::Renderable* gfxSource, const geom2d::rect<int32_t>& rectSource = { {0,0},{0,0} })
|
||||
: gfxImageSource(gfxSource), rectFrameSource(rectSource)
|
||||
{
|
||||
// If no source rectangle specified then use whole image source. Ignore in the event
|
||||
// that a frame is set up as source-less
|
||||
if(gfxSource && rectFrameSource.size.x == 0)
|
||||
rectFrameSource.size = gfxSource->Sprite()->Size();
|
||||
}
|
||||
|
||||
inline const olc::Renderable* GetSourceImage() const
|
||||
{
|
||||
return gfxImageSource;
|
||||
}
|
||||
|
||||
inline const geom2d::rect<int32_t>& GetSourceRect() const
|
||||
{
|
||||
return rectFrameSource;
|
||||
}
|
||||
|
||||
private:
|
||||
const olc::Renderable* gfxImageSource;
|
||||
geom2d::rect<int32_t> rectFrameSource;
|
||||
};
|
||||
|
||||
// Animation styles decide how the frames should be traversed in time
|
||||
enum class Style : uint8_t
|
||||
{
|
||||
Repeat, // Cycle through, go back to beginning
|
||||
OneShot, // Play once and suspend on final frame
|
||||
PingPong, // Traverse through forwards, then backwards
|
||||
Reverse, // Cycle through sequence backwards
|
||||
};
|
||||
|
||||
class FrameSequence
|
||||
{
|
||||
public:
|
||||
// Constructs a sequence of frames with a duration and a traversal style
|
||||
inline FrameSequence(const float fFrameDuration = 0.1f, const Style nStyle = Style::Repeat)
|
||||
{
|
||||
m_fFrameDuration = fFrameDuration;
|
||||
m_fFrameRate = 1.0f / m_fFrameDuration;
|
||||
m_nStyle = nStyle;
|
||||
}
|
||||
|
||||
// Adds a frame to this sequence
|
||||
inline void AddFrame(const Frame& frame)
|
||||
{
|
||||
m_vFrames.emplace_back(frame);
|
||||
}
|
||||
|
||||
// Returns a Frame Object for a given time into an animation
|
||||
inline const Frame& GetFrame(const float fTime) const
|
||||
{
|
||||
return m_vFrames[ConvertTimeToFrame(fTime)];
|
||||
}
|
||||
|
||||
private:
|
||||
Style m_nStyle;
|
||||
std::vector<Frame> m_vFrames;
|
||||
float m_fFrameDuration = 0.1f;
|
||||
float m_fFrameRate = 10.0f;
|
||||
|
||||
inline const size_t ConvertTimeToFrame(const float fTime) const
|
||||
{
|
||||
switch (m_nStyle)
|
||||
{
|
||||
case Style::Repeat:
|
||||
return size_t(fTime * m_fFrameRate) % m_vFrames.size();
|
||||
break;
|
||||
case Style::OneShot:
|
||||
return std::clamp(size_t(fTime * m_fFrameRate), size_t(0), m_vFrames.size() - 1);
|
||||
break;
|
||||
case Style::PingPong:
|
||||
// TODO
|
||||
break;
|
||||
case Style::Reverse:
|
||||
return (m_vFrames.size() - 1) - (size_t(fTime * m_fFrameRate) % m_vFrames.size());
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// A Animate2D::State is a lightweight token that can be attached to things
|
||||
// that are animated. Under normal circumstances, it is never updated manually
|
||||
struct AnimationState
|
||||
{
|
||||
private:
|
||||
size_t nIndex = 0;
|
||||
float fTime = 0.0f;
|
||||
template<typename StatesEnum>
|
||||
friend class Animation;
|
||||
};
|
||||
|
||||
// Animation object holds a group of frame sequences and can mutate an AnimationState token
|
||||
template<typename StatesEnum>
|
||||
class Animation
|
||||
{
|
||||
public:
|
||||
Animation() = default;
|
||||
|
||||
// Change an animation state token to a new state
|
||||
inline bool ChangeState(AnimationState& state, const StatesEnum& sStateName) const
|
||||
{
|
||||
size_t idx = m_mapStateIndices.at(sStateName);
|
||||
if (state.nIndex != idx)
|
||||
{
|
||||
state.fTime = 0.0f;
|
||||
state.nIndex = idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update an animation state token
|
||||
inline void UpdateState(AnimationState& state, const float fElapsedTime) const
|
||||
{
|
||||
state.fTime += fElapsedTime;
|
||||
}
|
||||
|
||||
public:
|
||||
// Retrieve the frame information for a given animation state
|
||||
inline const Frame& GetFrame(const AnimationState& state) const
|
||||
{
|
||||
return m_vSequences[state.nIndex].GetFrame(state.fTime);
|
||||
}
|
||||
|
||||
public:
|
||||
// Add a named Frame sequence as a state
|
||||
inline void AddState(const StatesEnum& sStateName, const FrameSequence& sequence)
|
||||
{
|
||||
m_vSequences.emplace_back(sequence);
|
||||
m_mapStateIndices[sStateName] = m_vSequences.size() - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<FrameSequence> m_vSequences;
|
||||
std::unordered_map<StatesEnum, size_t> m_mapStateIndices;
|
||||
};
|
||||
}
|
258
Crawler/olcUTIL_Camera2D.h
Normal file
258
Crawler/olcUTIL_Camera2D.h
Normal file
@ -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, <EFBFBD>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…
x
Reference in New Issue
Block a user