Add project files.

CorrectiveAction
sigonasr2 1 year ago
parent 0e2ae1bf70
commit a6301c6f6e
  1. 31
      olcCodeJam2023Entry.sln
  2. 32
      olcCodeJam2023Entry/VirusAttack.cpp
  3. 13
      olcCodeJam2023Entry/VirusAttack.h
  4. BIN
      olcCodeJam2023Entry/assets/MAINICON.ico
  5. BIN
      olcCodeJam2023Entry/assets/Vast Horizons.wav
  6. 2
      olcCodeJam2023Entry/emscripten_build.ps1
  7. BIN
      olcCodeJam2023Entry/icon.png
  8. BIN
      olcCodeJam2023Entry/olcCodeJam2023Entry.rc
  9. 158
      olcCodeJam2023Entry/olcCodeJam2023Entry.vcxproj
  10. 67
      olcCodeJam2023Entry/olcCodeJam2023Entry.vcxproj.filters
  11. 585
      olcCodeJam2023Entry/olcPGEX_PopUpMenu.h
  12. 1170
      olcCodeJam2023Entry/olcPGEX_QuickGUI.h
  13. 220
      olcCodeJam2023Entry/olcPGEX_SplashScreen.h
  14. 746
      olcCodeJam2023Entry/olcPGEX_TransformedView.h
  15. 6701
      olcCodeJam2023Entry/olcPixelGameEngine.h
  16. 1962
      olcCodeJam2023Entry/olcSoundWaveEngine.h
  17. 258
      olcCodeJam2023Entry/olcUTIL_Camera2D.h
  18. 1046
      olcCodeJam2023Entry/olcUTIL_Geometry2D.h
  19. BIN
      olcCodeJam2023Entry/pge.data
  20. 1296
      olcCodeJam2023Entry/pge.html
  21. 11121
      olcCodeJam2023Entry/pge.js
  22. BIN
      olcCodeJam2023Entry/pge.wasm
  23. 1
      olcCodeJam2023Entry/pge.wasm.map
  24. 16
      olcCodeJam2023Entry/resource.h
  25. 16
      olcCodeJam2023Entry/resource1.h

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33516.290
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "olcCodeJam2023Entry", "olcCodeJam2023Entry\olcCodeJam2023Entry.vcxproj", "{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Debug|x64.ActiveCfg = Debug|x64
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Debug|x64.Build.0 = Debug|x64
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Debug|x86.ActiveCfg = Debug|Win32
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Debug|x86.Build.0 = Debug|Win32
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Release|x64.ActiveCfg = Release|x64
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Release|x64.Build.0 = Release|x64
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Release|x86.ActiveCfg = Release|Win32
{FA5243BE-6446-44B1-ADE6-EB26118F6B3E}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {59D77397-F63B-47B2-B936-7BB19452CD50}
EndGlobalSection
EndGlobal

@ -0,0 +1,32 @@
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
#define OLC_SOUNDWAVE
#include "olcSoundWaveEngine.h"
#include "VirusAttack.h"
VirusAttack::VirusAttack()
{
// Name your application
sAppName = "olcCodeJam 2023 Entry";
}
bool VirusAttack::OnUserCreate(){
// Called once at the start, so create things here
return true;
}
bool VirusAttack::OnUserUpdate(float fElapsedTime){
// Called once per frame, draws random coloured pixels
for (int x = 0; x < ScreenWidth(); x++)
for (int y = 0; y < ScreenHeight(); y++)
Draw(x, y, olc::Pixel(rand() % 256, rand() % 256, rand() % 256));
return true;
}
int main()
{
VirusAttack app;
if (app.Construct(256, 240, 4, 4))
app.Start();
return 0;
}

@ -0,0 +1,13 @@
#include "olcPixelGameEngine.h"
#include "olcSoundWaveEngine.h"
class VirusAttack : public olc::PixelGameEngine
{
public:
VirusAttack();
public:
bool OnUserCreate() override;
bool OnUserUpdate(float fElapsedTime) override;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

@ -0,0 +1,2 @@
~\Documents\emsdk\emsdk_env.ps1 activate latest
em++ -std=c++20 -gsource-map -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 -s USE_SDL_MIXER=2 $(Get-ChildItem *.cpp) -o pge.html --preload-file assets

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{fa5243be-6446-44b1-ade6-eb26118f6b3e}</ProjectGuid>
<RootNamespace>olcCodeJam2023Entry</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<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" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<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>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="olcPGEX_PopUpMenu.h" />
<ClInclude Include="olcPGEX_QuickGUI.h" />
<ClInclude Include="olcPGEX_SplashScreen.h" />
<ClInclude Include="olcPGEX_TransformedView.h" />
<ClInclude Include="olcPixelGameEngine.h" />
<ClInclude Include="olcSoundWaveEngine.h" />
<ClInclude Include="olcUTIL_Camera2D.h" />
<ClInclude Include="olcUTIL_Geometry2D.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="resource1.h" />
<ClInclude Include="VirusAttack.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="VirusAttack.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="olcCodeJam2023Entry.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="assets\MAINICON.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<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="olcSoundWaveEngine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcPGEX_PopUpMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcPGEX_QuickGUI.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcPGEX_SplashScreen.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcPGEX_TransformedView.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcUTIL_Camera2D.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcUTIL_Geometry2D.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource1.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="VirusAttack.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="VirusAttack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="olcCodeJam2023Entry.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="assets\MAINICON.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

@ -0,0 +1,585 @@
/*
olcPGEX_PopUp.h
+-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine Extension |
| Retro PopUp Menu 1.0 |
+-------------------------------------------------------------+
What is this?
~~~~~~~~~~~~~
This is an extension to the olcPixelGameEngine, which provides
a quick and easy to use, flexible, skinnable context pop-up
menu system.
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2020 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
*/
/*
Example
~~~~~~~
#define OLC_PGEX_POPUPMENU
#include "olcPGEX_PopUpMenu.h"
NOTE: Requires a 9-patch sprite, by default each patch is
8x8 pixels, patches are as follows:
| PANEL TL | PANEL T | PANEL TR | SCROLL UP | CURSOR TL | CURSOR TR |
| PANEL L | PANEL M | PANEL R | SUBMENU | CURSOR BL | CURSOR BR |
| PANEL BL | PANEL B | PANEL BR | SCROLL DOWN | UNUSED | UNUSED |
You can find an example sprite here:
https://github.com/OneLoneCoder/olcPixelGameEngine/blob/master/Videos/RetroMenu.png
Constructing A Menu
~~~~~~~~~~~~~~~~~~~
// Declaration (presumably inside class)
olc::popup::Menu m;
// Construction (root menu is a 1x5 table)
m.SetTable(1, 5);
// Add first item to root menu (A 1x5 submenu)
m["Menu1"].SetTable(1, 5);
// Add items to first item
m["Menu1"]["Item1"];
m["Menu1"]["Item2"];
// Add a 4x3 submenu
m["Menu1"]["Item3"].SetTable(4, 3);
m["Menu1"]["Item3"]["Option1"];
m["Menu1"]["Item3"]["Option2"];
// Set properties of specific item
m["Menu1"]["Item3"]["Option3"].Enable(false);
m["Menu1"]["Item3"]["Option4"];
m["Menu1"]["Item3"]["Option5"];
m["Menu1"]["Item4"];
// Add second item to root menu
m["Menu2"].SetTable(3, 3);
m["Menu2"]["Item1"];
m["Menu2"]["Item2"].SetID(1001).Enable(true);
m["Menu2"]["Item3"];
// Construct the menu structure
m.Build();
Displaying a Menu
~~~~~~~~~~~~~~~~~
// Declaration of menu manager (presumably inside class)
olc::popup::Manager man;
// Set the Menu object to the MenuManager (call once per pop)
man.Open(&m);
// Draw Menu at position (30, 30), using "patch sprite"
man.Draw(sprGFX, { 30,30 });
Interacting with menu
~~~~~~~~~~~~~~~~~~~~~
// Send key events to menu
if (GetKey(olc::Key::UP).bPressed) man.OnUp();
if (GetKey(olc::Key::DOWN).bPressed) man.OnDown();
if (GetKey(olc::Key::LEFT).bPressed) man.OnLeft();
if (GetKey(olc::Key::RIGHT).bPressed) man.OnRight();
if (GetKey(olc::Key::Z).bPressed) man.OnBack();
// "Confirm/Action" Key does something, if it returns non-null
// then a menu item has been selected. The specific item will
// be returned
olc::popup::Menu* command = nullptr;
if (GetKey(olc::Key::SPACE).bPressed) command = man.OnConfirm();
if (command != nullptr)
{
std::string sLastAction =
"Selected: " + command->GetName() +
" ID: " + std::to_string(command->GetID());
// Optionally close menu?
man.Close();
}
*/
#ifndef OLC_PGEX_POPUPMENU_H
#define OLC_PGEX_POPUPMENU_H
#include <cstdint>
namespace olc
{
namespace popup
{
constexpr int32_t nPatch = 8;
class Menu
{
public:
Menu();
Menu(const std::string n);
Menu& SetTable(int32_t nColumns, int32_t nRows);
Menu& SetID(int32_t id);
Menu& Enable(bool b);
int32_t GetID();
std::string& GetName();
bool Enabled();
bool HasChildren();
olc::vi2d GetSize();
olc::vi2d& GetCursorPosition();
Menu& operator[](const std::string& name);
void Build();
void DrawSelf(olc::PixelGameEngine& pge, olc::Sprite* sprGFX, olc::vi2d vScreenOffset);
void ClampCursor();
void OnUp();
void OnDown();
void OnLeft();
void OnRight();
Menu* OnConfirm();
Menu* GetSelectedItem();
protected:
int32_t nID = -1;
olc::vi2d vCellTable = { 1, 0 };
std::unordered_map<std::string, size_t> itemPointer;
std::vector<olc::popup::Menu> items;
olc::vi2d vSizeInPatches = { 0, 0 };
olc::vi2d vCellSize = { 0, 0 };
olc::vi2d vCellPadding = { 2, 0 };
olc::vi2d vCellCursor = { 0, 0 };
int32_t nCursorItem = 0;
int32_t nTopVisibleRow = 0;
int32_t nTotalRows = 0;
const olc::vi2d vPatchSize = { nPatch, nPatch };
std::string sName;
olc::vi2d vCursorPos = { 0, 0 };
bool bEnabled = true;
};
class Manager : public olc::PGEX
{
public:
Manager();
void Open(Menu* mo);
void Close();
void OnUp();
void OnDown();
void OnLeft();
void OnRight();
void OnBack();
Menu* OnConfirm();
void Draw(olc::Sprite* sprGFX, olc::vi2d vScreenOffset);
private:
std::list<Menu*> panels;
};
}
};
#ifdef OLC_PGEX_POPUPMENU
#undef OLC_PGEX_POPUPMENU
namespace olc
{
namespace popup
{
Menu::Menu()
{
}
Menu::Menu(const std::string n)
{
sName = n;
}
Menu& Menu::SetTable(int32_t nColumns, int32_t nRows)
{
vCellTable = { nColumns, nRows };
return *this;
}
Menu& Menu::SetID(int32_t id)
{
nID = id;
return *this;
}
Menu& Menu::Enable(bool b)
{
bEnabled = b;
return *this;
}
int32_t Menu::GetID()
{
return nID;
}
std::string& Menu::GetName()
{
return sName;
}
bool Menu::Enabled()
{
return bEnabled;
}
bool Menu::HasChildren()
{
return !items.empty();
}
olc::vi2d Menu::GetSize()
{
return { int32_t(sName.size()), 1 };
}
olc::vi2d& Menu::GetCursorPosition()
{
return vCursorPos;
}
Menu& Menu::operator[](const std::string& name)
{
if (itemPointer.count(name) == 0)
{
itemPointer[name] = items.size();
items.push_back(Menu(name));
}
return items[itemPointer[name]];
}
void Menu::Build()
{
// Recursively build all children, so they can determine their size, use
// that size to indicate cell sizes if this object contains more than
// one item
for (auto& m : items)
{
if (m.HasChildren())
{
m.Build();
}
// Longest child name determines cell width
vCellSize.x = std::max(m.GetSize().x, vCellSize.x);
vCellSize.y = std::max(m.GetSize().y, vCellSize.y);
}
// Adjust size of this object (in patches) if it were rendered as a panel
vSizeInPatches.x = vCellTable.x * vCellSize.x + (vCellTable.x - 1) * vCellPadding.x + 2;
vSizeInPatches.y = vCellTable.y * vCellSize.y + (vCellTable.y - 1) * vCellPadding.y + 2;
// Calculate how many rows this item has to hold
nTotalRows = (items.size() / vCellTable.x) + (((items.size() % vCellTable.x) > 0) ? 1 : 0);
}
void Menu::DrawSelf(olc::PixelGameEngine& pge, olc::Sprite* sprGFX, olc::vi2d vScreenOffset)
{
// === Draw Panel
// Record current pixel mode user is using
olc::Pixel::Mode currentPixelMode = pge.GetPixelMode();
pge.SetPixelMode(olc::Pixel::MASK);
// Draw Panel & Border
olc::vi2d vPatchPos = { 0,0 };
for (vPatchPos.x = 0; vPatchPos.x < vSizeInPatches.x; vPatchPos.x++)
{
for (vPatchPos.y = 0; vPatchPos.y < vSizeInPatches.y; vPatchPos.y++)
{
// Determine position in screen space
olc::vi2d vScreenLocation = vPatchPos * nPatch + vScreenOffset;
// Calculate which patch is needed
olc::vi2d vSourcePatch = { 0, 0 };
if (vPatchPos.x > 0) vSourcePatch.x = 1;
if (vPatchPos.x == vSizeInPatches.x - 1) vSourcePatch.x = 2;
if (vPatchPos.y > 0) vSourcePatch.y = 1;
if (vPatchPos.y == vSizeInPatches.y - 1) vSourcePatch.y = 2;
// Draw Actual Patch
pge.DrawPartialSprite(vScreenLocation, sprGFX, vSourcePatch * nPatch, vPatchSize);
}
}
// === Draw Panel Contents
olc::vi2d vCell = { 0,0 };
vPatchPos = { 1,1 };
// Work out visible items
int32_t nTopLeftItem = nTopVisibleRow * vCellTable.x;
int32_t nBottomRightItem = vCellTable.y * vCellTable.x + nTopLeftItem;
// Clamp to size of child item vector
nBottomRightItem = std::min(int32_t(items.size()), nBottomRightItem);
int32_t nVisibleItems = nBottomRightItem - nTopLeftItem;
// Draw Scroll Markers (if required)
if (nTopVisibleRow > 0)
{
vPatchPos = { vSizeInPatches.x - 2, 0 };
olc::vi2d vScreenLocation = vPatchPos * nPatch + vScreenOffset;
olc::vi2d vSourcePatch = { 3, 0 };
pge.DrawPartialSprite(vScreenLocation, sprGFX, vSourcePatch * nPatch, vPatchSize);
}
if ((nTotalRows - nTopVisibleRow) > vCellTable.y)
{
vPatchPos = { vSizeInPatches.x - 2, vSizeInPatches.y - 1 };
olc::vi2d vScreenLocation = vPatchPos * nPatch + vScreenOffset;
olc::vi2d vSourcePatch = { 3, 2 };
pge.DrawPartialSprite(vScreenLocation, sprGFX, vSourcePatch * nPatch, vPatchSize);
}
// Draw Visible Items
for (int32_t i = 0; i < nVisibleItems; i++)
{
// Cell location
vCell.x = i % vCellTable.x;
vCell.y = i / vCellTable.x;
// Patch location (including border offset and padding)
vPatchPos.x = vCell.x * (vCellSize.x + vCellPadding.x) + 1;
vPatchPos.y = vCell.y * (vCellSize.y + vCellPadding.y) + 1;
// Actual screen location in pixels
olc::vi2d vScreenLocation = vPatchPos * nPatch + vScreenOffset;
// Display Item Header
pge.DrawString(vScreenLocation, items[nTopLeftItem + i].sName, items[nTopLeftItem + i].bEnabled ? olc::WHITE : olc::DARK_GREY);
if (items[nTopLeftItem + i].HasChildren())
{
// Display Indicator that panel has a sub panel
vPatchPos.x = vCell.x * (vCellSize.x + vCellPadding.x) + 1 + vCellSize.x;
vPatchPos.y = vCell.y * (vCellSize.y + vCellPadding.y) + 1;
olc::vi2d vSourcePatch = { 3, 1 };
vScreenLocation = vPatchPos * nPatch + vScreenOffset;
pge.DrawPartialSprite(vScreenLocation, sprGFX, vSourcePatch * nPatch, vPatchSize);
}
}
// Calculate cursor position in screen space in case system draws it
vCursorPos.x = (vCellCursor.x * (vCellSize.x + vCellPadding.x)) * nPatch + vScreenOffset.x - nPatch;
vCursorPos.y = ((vCellCursor.y - nTopVisibleRow) * (vCellSize.y + vCellPadding.y)) * nPatch + vScreenOffset.y + nPatch;
}
void Menu::ClampCursor()
{
// Find item in children
nCursorItem = vCellCursor.y * vCellTable.x + vCellCursor.x;
// Clamp Cursor
if (nCursorItem >= int32_t(items.size()))
{
vCellCursor.y = (items.size() / vCellTable.x);
vCellCursor.x = (items.size() % vCellTable.x) - 1;
nCursorItem = items.size() - 1;
}
}
void Menu::OnUp()
{
vCellCursor.y--;
if (vCellCursor.y < 0) vCellCursor.y = 0;
if (vCellCursor.y < nTopVisibleRow)
{
nTopVisibleRow--;
if (nTopVisibleRow < 0) nTopVisibleRow = 0;
}
ClampCursor();
}
void Menu::OnDown()
{
vCellCursor.y++;
if (vCellCursor.y == nTotalRows) vCellCursor.y = nTotalRows - 1;
if (vCellCursor.y > (nTopVisibleRow + vCellTable.y - 1))
{
nTopVisibleRow++;
if (nTopVisibleRow > (nTotalRows - vCellTable.y))
nTopVisibleRow = nTotalRows - vCellTable.y;
}
ClampCursor();
}
void Menu::OnLeft()
{
vCellCursor.x--;
if (vCellCursor.x < 0) vCellCursor.x = 0;
ClampCursor();
}
void Menu::OnRight()
{
vCellCursor.x++;
if (vCellCursor.x == vCellTable.x) vCellCursor.x = vCellTable.x - 1;
ClampCursor();
}
Menu* Menu::OnConfirm()
{
// Check if selected item has children
if (items[nCursorItem].HasChildren())
{
return &items[nCursorItem];
}
else
return this;
}
Menu* Menu::GetSelectedItem()
{
return &items[nCursorItem];
}
// =====================================================================
Manager::Manager()
{
}
void Manager::Open(Menu* mo)
{
Close();
panels.push_back(mo);
}
void Manager::Close()
{
panels.clear();
}
void Manager::OnUp()
{
if (!panels.empty()) panels.back()->OnUp();
}
void Manager::OnDown()
{
if (!panels.empty()) panels.back()->OnDown();
}
void Manager::OnLeft()
{
if (!panels.empty()) panels.back()->OnLeft();
}
void Manager::OnRight()
{
if (!panels.empty()) panels.back()->OnRight();
}
void Manager::OnBack()
{
if (!panels.empty()) panels.pop_back();
}
Menu* Manager::OnConfirm()
{
if (panels.empty()) return nullptr;
Menu* next = panels.back()->OnConfirm();
if (next == panels.back())
{
if (panels.back()->GetSelectedItem()->Enabled())
return panels.back()->GetSelectedItem();
}
else
{
if (next->Enabled())
panels.push_back(next);
}
return nullptr;
}
void Manager::Draw(olc::Sprite* sprGFX, olc::vi2d vScreenOffset)
{
if (panels.empty()) return;
// Draw Visible Menu System
for (auto& p : panels)
{
p->DrawSelf(*pge, sprGFX, vScreenOffset);
vScreenOffset += {10, 10};
}
// Draw Cursor
olc::Pixel::Mode currentPixelMode = pge->GetPixelMode();
pge->SetPixelMode(olc::Pixel::ALPHA);
pge->DrawPartialSprite(panels.back()->GetCursorPosition(), sprGFX, olc::vi2d(4, 0) * nPatch, { nPatch * 2, nPatch * 2 });
pge->SetPixelMode(currentPixelMode);
}
}
};
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,220 @@
/*
olcPGEX_SplashScreen.h
+-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine Extension |
| Splash Screen v1.0 |
+-------------------------------------------------------------+
NOTE: UNDER ACTIVE DEVELOPMENT - THERE ARE BUGS/GLITCHES
What is this?
~~~~~~~~~~~~~
This extension produces an animated splashscreen and copyright notice
at the beginning of a PGE application, for the purposes of remaining
OLC-3 compliant should it be ambiguous in your deployment.
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
Revisions:
1.00: Initial Release
*/
#pragma once
#include "olcPixelGameEngine.h"
namespace olc
{
class SplashScreen : public olc::PGEX
{
public:
SplashScreen();
protected:
virtual void OnAfterUserCreate() override;
virtual bool OnBeforeUserUpdate(float& fElapsedTime) override;
private:
olc::Renderable spr;
std::vector<std::pair<olc::vf2d, olc::vf2d>> vBoom;
olc::vf2d vScale;
olc::vf2d vPosition;
float fParticleTime = 0.0f;
float fAspect = 0.0f;
bool bComplete = false;
};
}
#ifdef OLC_PGEX_SPLASHSCREEN
#undef OLC_PGEX_SPLASHSCREEN
namespace olc
{
SplashScreen::SplashScreen() : olc::PGEX(true)
{
}
void SplashScreen::OnAfterUserCreate()
{
const char logo[] =
"000000000000000000000000000000000000000000000000000000000000000000005"
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED1EE"
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED5EEE"
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@E@000"
"0000000000000000000000000000000000000000000000000000000000001E1D:ZZZZ"
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ1D5BZZZZZZ"
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ5@E:P0002Z0"
"02ZZX000000000000ZP0000000000000000000000000000ZX000Z002XE1DX?o`o:Poo"
"800SooaE5@E1ED5BX?ol5E@E0E1ED?oo5@E1ED5DE1D5E@ZQEEBPEE2QD5BSooclZ?olQ"
"AB?oo5DEEDEEDE:SooaEEAE5DEEDoolEADEEDEAE5AEEBZ5EE:5EE:5@E:?oo?bXoob55"
"8o3lEAEEAD5ADZ?oo5@E5EEAD5Cl01E5AD5AE5DE5@E:X01DXEEDXE1DXo3lo:Sl0800S"
"ooaE1ED5EE5BXo00EEDEEE5EE?oo5EE5EE5DEEDEEDZQEEBQD5BQD5BSl?cl0?`0ZZZ?o"
"o5D5E@EEDE03loaEEAEEDEEDoolEED5EDEAEEAEEBZ5EE:5@E:5@E:?oo?oloob008o00"
"EAEEAD01EE?co5EE5EEAD03l01DE@05AE5AE5@0:XE000EEDXE1DXooloocoo8DDSlZQE"
"5EE5EE5EDoolE1DE4E5EE?oo5AE5EE5DE5DEEDZQEEAAEEBQD5BPoo3oo3olQAB?bZ5DE"
"1D5EDEE@ooaD5AD1D5EDoolE1DEE@EAD5@EEBZ5EE51ED:5@E:P000000020080:X0000"
"00000000000000000000000000000000000:X0000002XE1DZZZZZZZZZZZZZZZZZZZZZ"
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZQD5@ZZZZZZZZZZZZZZZZZZZZZZ"
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZX5@E@00000000000000000000000"
"00000000000000000000000000000000000000001E1EEEEEEEEEEEEEEEEEEEEEEEEEE"
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED5EEEEEEEEEEEEEEEEEEEEEEEEEEE"
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE@5EEEEEEEEEEEEEEEEEEEEEEEEEEEE"
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEED0000000000000000000000000000000"
"0000000000000000000000000000000000000";
spr.Create(203, 24);
int px = 0, py = 0;
for (size_t b = 0; b < 1624; b += 4)
{
uint32_t sym1 = (uint32_t)logo[b + 0] - 48;
uint32_t sym2 = (uint32_t)logo[b + 1] - 48;
uint32_t sym3 = (uint32_t)logo[b + 2] - 48;
uint32_t sym4 = (uint32_t)logo[b + 3] - 48;
uint32_t r = sym1 << 18 | sym2 << 12 | sym3 << 6 | sym4;
for (int i = 0; i < 12; i++)
{
olc::Pixel p = olc::RED;
switch ((r & 0xC00000) >> 22)
{
case 0: p = olc::Pixel(0, 0, 0, 255); break;
case 1: p = olc::Pixel(255, 255, 255, 255); break;
case 2: p = olc::Pixel(255, 120, 26, 255); break;
case 3: p = olc::Pixel(79, 193, 255, 255); break;
}
spr.Sprite()->SetPixel(px, py, p);
if (++px == 203) { py++; px = 0; }
r <<= 2;
}
}
spr.Decal()->Update();
vBoom.resize(spr.Sprite()->width * spr.Sprite()->height);
vScale = { float(pge->ScreenWidth()) / 500.0f, float(pge->ScreenWidth()) / 500.0f };
fAspect = float(pge->ScreenWidth()) / float(pge->ScreenHeight());
vPosition = olc::vf2d(
(250 - spr.Sprite()->width) / 2.0f,
(250 - spr.Sprite()->height) / 2.0f / fAspect);
for (int y = 0; y < spr.Sprite()->height; y++)
for (int x = 0; x < spr.Sprite()->width; x++)
vBoom[y * spr.Sprite()->width + x] = std::make_pair(
vPosition + olc::vf2d(x, y),
olc::vf2d(
(float(rand()) / float(RAND_MAX)) * 10.0f - 5.0f,
(float(rand()) / float(RAND_MAX)) * 10.0f - 5.0f)
);
}
bool SplashScreen::OnBeforeUserUpdate(float& fElapsedTime)
{
if (bComplete) return false;
fParticleTime += fElapsedTime;
for (int y = 0; y < spr.Sprite()->height; y++)
for (int x = 0; x < spr.Sprite()->width; x++)
{
if (fParticleTime < 1.0f)
{
}
else if (fParticleTime < 2.0f)
{
vBoom[y * spr.Sprite()->width + x].first =
olc::vf2d(
(250 - spr.Sprite()->width) / 2.0f + float(x),
(250 - spr.Sprite()->height) / 2.0f / fAspect + float(y)
) +
olc::vf2d(
(float(rand()) / float(RAND_MAX)) * 0.5f - 0.25f,
(float(rand()) / float(RAND_MAX)) * 0.5f - 0.25f);
}
else if(fParticleTime < 5.0f)
{
vBoom[y * spr.Sprite()->width + x].first += vBoom[y * spr.Sprite()->width + x].second * fElapsedTime * 20.0f;
}
else
{
bComplete = true;
}
pge->DrawPartialDecal(vScale * vBoom[y * spr.Sprite()->width + x].first * 2.0f, spr.Decal(), olc::vf2d(x, y), { 1, 1 }, vScale * 2.0f, olc::PixelF(1.0f, 1.0f, 1.0f, std::min(1.0f, std::max(4.0f - fParticleTime, 0.0f))));
}
olc::vi2d vSize = pge->GetTextSizeProp("Copyright OneLoneCoder.com 2022");
pge->DrawStringPropDecal(olc::vf2d(float(pge->ScreenWidth()/2) - vSize.x/2, float(pge->ScreenHeight()) - vSize.y * 3.0f), "Copyright OneLoneCoder.com 2022", olc::PixelF(1.0f, 1.0f, 1.0f, 0.5f), olc::vf2d(1.0, 2.0f));
return true;
}
}
#endif

@ -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, ©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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -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 };
};
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by olcCodeJam2023Entry.rc
//
#define IDI_ICON1 104
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by olcCodeJam2023Entry.rc
//
#define IDI_ICON1 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif
Loading…
Cancel
Save