You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
7.2 KiB
219 lines
7.2 KiB
/*
|
|
Example file for olcUTIL_Camera2D.h
|
|
|
|
License (OLC-3)
|
|
~~~~~~~~~~~~~~~
|
|
|
|
Copyright 2018 - 2022 OneLoneCoder.com
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
1. Redistributions or derivations of source code must retain the above
|
|
copyright notice, this list of conditions and the following disclaimer.
|
|
|
|
2. Redistributions or derivative works in binary form must reproduce
|
|
the above copyright notice. This list of conditions and the following
|
|
disclaimer must be reproduced in the documentation and/or other
|
|
materials provided with the distribution.
|
|
|
|
3. Neither the name of the copyright holder nor the names of its
|
|
contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
Links
|
|
~~~~~
|
|
YouTube: https://www.youtube.com/javidx9
|
|
Discord: https://discord.gg/WhwHUMV
|
|
Twitter: https://www.twitter.com/javidx9
|
|
Twitch: https://www.twitch.tv/javidx9
|
|
GitHub: https://www.github.com/onelonecoder
|
|
Homepage: https://www.onelonecoder.com
|
|
|
|
Author
|
|
~~~~~~
|
|
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022
|
|
|
|
*/
|
|
|
|
#define OLC_PGE_APPLICATION
|
|
#include "olcPixelGameEngine.h"
|
|
|
|
#define OLC_PGEX_TRANSFORMEDVIEW
|
|
#include "extensions/olcPGEX_TransformedView.h"
|
|
|
|
#include "utilities/olcUTIL_Camera2D.h"
|
|
|
|
/*
|
|
To demonstrate the camera, we need a world. In this case its a simle tile
|
|
world of 80x75 tiles, and each tile is 32x32 screen pixels.
|
|
|
|
A transformed view is used to navigate the world manually via the middle
|
|
mouse button in "free roam" mode, or controlled by the camera.
|
|
|
|
Specifically a Tile Transformed View is used, which means all units for
|
|
drawing and for the camera are specified in tile space, i.e. 1 tile is
|
|
1x1 units (regardless of pixel size)
|
|
|
|
No assets are used for this application, so the world is constructed
|
|
out of coloured squares so you can see you are moving through it.
|
|
|
|
Pressing "TAB" key will swap between "free roam" and "play" modes. In
|
|
free roam mode, you can use middle mouse button to pan and zoom around
|
|
the world. The camera's visible area to the player is highlighted in red.
|
|
In play mode, the camera behaves as it would in a 2D game, depending upon
|
|
the selected mode.
|
|
*/
|
|
|
|
class TEST_Camera2D : public olc::PixelGameEngine
|
|
{
|
|
public:
|
|
TEST_Camera2D()
|
|
{
|
|
sAppName = "Camera2D Utility Test";
|
|
}
|
|
|
|
// Transformed view object to make world offsetting simple
|
|
olc::TileTransformedView tv;
|
|
|
|
// Conveninet constants to define tile map world
|
|
olc::vi2d m_vWorldSize = { 80, 75 };
|
|
olc::vi2d m_vTileSize = { 32, 32 };
|
|
|
|
// The camera!
|
|
olc::utils::Camera2D camera;
|
|
|
|
// The point that represents the player, it is "tracked"
|
|
// by the camera
|
|
olc::vf2d vTrackedPoint;
|
|
|
|
// Flag whether we are in "free roam" or "play" mode
|
|
bool bFreeRoam = false;
|
|
|
|
// The world map, stored as a 1D array
|
|
std::vector<uint8_t> vWorldMap;
|
|
|
|
public:
|
|
bool OnUserCreate() override
|
|
{
|
|
// Construct transform view
|
|
tv = olc::TileTransformedView(GetScreenSize(), m_vTileSize);
|
|
|
|
// Construct Camera
|
|
vTrackedPoint = { 20.0f, 20.0f };
|
|
camera = olc::utils::Camera2D(GetScreenSize() / m_vTileSize, vTrackedPoint);
|
|
|
|
// Configure Camera
|
|
camera.SetTarget(vTrackedPoint);
|
|
camera.SetMode(olc::utils::Camera2D::Mode::Simple);
|
|
camera.SetWorldBoundary({ 0.0f, 0.0f }, m_vWorldSize);
|
|
camera.EnableWorldBoundary(true);
|
|
|
|
// Create "tile map" world with just two tiles
|
|
vWorldMap.resize(m_vWorldSize.x * m_vWorldSize.y);
|
|
for (int i = 0; i < vWorldMap.size(); i++)
|
|
vWorldMap[i] = ((rand() % 20) == 1) ? 1 : 0;
|
|
|
|
// Set background colour
|
|
Clear(olc::CYAN);
|
|
return true;
|
|
}
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override
|
|
{
|
|
// In free roam, middle mouse button pans & zooms
|
|
if (bFreeRoam)
|
|
tv.HandlePanAndZoom();
|
|
|
|
// Handle player "physics" in response to key presses
|
|
olc::vf2d vVel = { 0.0f, 0.0f };
|
|
if (GetKey(olc::Key::W).bHeld) vVel += {0, -1};
|
|
if (GetKey(olc::Key::S).bHeld) vVel += {0, +1};
|
|
if (GetKey(olc::Key::A).bHeld) vVel += {-1, 0};
|
|
if (GetKey(olc::Key::D).bHeld) vVel += {+1, 0};
|
|
vTrackedPoint += vVel * 8.0f * fElapsedTime;
|
|
|
|
// Switch between "free roam" and "play" mode with TAB key
|
|
if (GetKey(olc::Key::TAB).bPressed)
|
|
{
|
|
// Always setup camera to play mode when tab key pressed
|
|
tv.SetWorldOffset(camera.GetViewPosition());
|
|
tv.SetWorldScale(m_vTileSize);
|
|
bFreeRoam = !bFreeRoam;
|
|
}
|
|
|
|
// Switch camera mode in operation
|
|
if (GetKey(olc::Key::K1).bPressed)
|
|
camera.SetMode(olc::utils::Camera2D::Mode::Simple);
|
|
if (GetKey(olc::Key::K2).bPressed)
|
|
camera.SetMode(olc::utils::Camera2D::Mode::EdgeMove);
|
|
if (GetKey(olc::Key::K3).bPressed)
|
|
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
|
|
if (GetKey(olc::Key::K4).bPressed)
|
|
camera.SetMode(olc::utils::Camera2D::Mode::FixedScreens);
|
|
|
|
// Update the camera, if teh tracked object remains visible,
|
|
// true is returned
|
|
bool bOnScreen = camera.Update(fElapsedTime);
|
|
|
|
// In "play" mode, set the transformed view to that required by
|
|
// the camera
|
|
if (!bFreeRoam)
|
|
tv.SetWorldOffset(camera.GetViewPosition());
|
|
|
|
// Render "tile map", by getting visible tiles
|
|
olc::vi2d vTileTL = tv.GetTopLeftTile().max({ 0,0 });
|
|
olc::vi2d vTileBR = tv.GetBottomRightTile().min(m_vWorldSize);
|
|
olc::vi2d vTile;
|
|
// Then looping through them and drawing them
|
|
for (vTile.y = vTileTL.y; vTile.y < vTileBR.y; vTile.y++)
|
|
for (vTile.x = vTileTL.x; vTile.x < vTileBR.x; vTile.x++)
|
|
{
|
|
int idx = vTile.y * m_vWorldSize.x + vTile.x;
|
|
|
|
if (vWorldMap[idx] == 0)
|
|
tv.FillRectDecal(vTile, { 1.0f, 1.0f }, olc::Pixel(40, 40, 40));
|
|
|
|
if (vWorldMap[idx] == 1)
|
|
tv.FillRectDecal(vTile, { 1.0f, 1.0f }, olc::Pixel(60, 60, 60));
|
|
}
|
|
|
|
// Draw the "player" as a 1x1 cell
|
|
tv.FillRectDecal(vTrackedPoint - olc::vf2d(0.5f, 0.5f), {1.0f, 1.0f}, olc::BLUE);
|
|
|
|
// Overlay with information
|
|
if (bFreeRoam)
|
|
{
|
|
tv.FillRectDecal(camera.GetViewPosition(), camera.GetViewSize(), olc::PixelF(1.0f, 0.0f, 0.0f, 0.5f));
|
|
DrawStringPropDecal({ 2, 2 }, "TAB: Free Mode, M-Btn to Pan & Zoom", olc::YELLOW);
|
|
}
|
|
else
|
|
DrawStringPropDecal({ 2,2 }, "TAB: Play Mode", olc::YELLOW);
|
|
|
|
DrawStringPropDecal({ 2,12 }, "WASD : Move", olc::YELLOW);
|
|
DrawStringPropDecal({ 2,22 }, "CAMERA: 1) Simple 2) EdgeMove 3) LazyFollow 4) Screens", olc::YELLOW);
|
|
DrawStringPropDecal({ 2,42 }, vTrackedPoint.str(), olc::YELLOW);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
TEST_Camera2D demo;
|
|
if (demo.Construct(512, 480, 2, 2))
|
|
demo.Start();
|
|
return 0;
|
|
} |