Upstream for PGE updates.
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.
 
 
 
olcPixelGameEngine/Videos/SavingSedit/olcPGEX_TileMaps_new.h

381 lines
9.8 KiB

#pragma once
#include "olcPixelGameEngine.h"
#include <algorithm>
#undef min
#undef max
namespace olc
{
class TILE : public olc::PGEX
{
public:
struct Edge
{
float sx, sy;
float ex, ey;
};
public:
class Atlas
{
public:
Atlas();
void Create(olc::Sprite *tileSheet);
olc::rcode LoadFromFile(std::string filename);
olc::rcode SaveToFile(std::string filename);
public:
olc::Sprite *sprTileSheet;
std::vector<std::tuple<int32_t, int32_t, int32_t, int32_t>> location;
};
public:
template <class T>
class Layer
{
public:
Layer();
void Create(int32_t w, int32_t h, int32_t tw, int32_t th);
olc::rcode LoadFromFile(std::string filename);
olc::rcode SaveToFile(std::string filename);
T* GetTile(int32_t x, int32_t y);
public:
int32_t nLayerWidth;
int32_t nLayerHeight;
int32_t nTileWidth;
int32_t nTileHeight;
private:
T *pTiles;
};
class BasicTile
{
public:
BasicTile();
public:
int32_t id;
bool exist;
int edge_id[4];
bool edge_exist[4];
};
public:
template<typename T>
static void DrawLayer(olc::TILE::Layer<T> &layer, olc::TILE::Atlas &atlas, float cam_x, float cam_y, int tiles_x, int tiles_y, int nScale = 1);
template<typename T>
static olc::Pixel GetLayerPixel(olc::TILE::Layer<T> &layer, olc::TILE::Atlas &atlas, float x, float y);
template<typename T>
static std::vector<olc::TILE::Edge> ExtractEdgesFromLayer(olc::TILE::Layer<T> &layer, int sx, int sy, int width, int height);
};
}
namespace olc
{
TILE::BasicTile::BasicTile()
{
exist = false;
id = 0;
for (int i = 0; i < 4; i++)
{
edge_exist[i] = false;
edge_id[i] = 0;
}
}
template <class T>
TILE::Layer<T>::Layer()
{
}
template <class T>
void TILE::Layer<T>::Create(int32_t w, int32_t h, int32_t tw, int32_t th)
{
nLayerWidth = w;
nLayerHeight = h;
nTileWidth = tw;
nTileHeight = th;
pTiles = new T[nLayerWidth * nLayerHeight];
for (int i = 0; i < nLayerWidth*nLayerHeight; i++)
{
pTiles[i].id = 0;
}
}
template <class T>
olc::rcode TILE::Layer<T>::LoadFromFile(std::string filename)
{
return olc::FAIL;
}
template <class T>
olc::rcode TILE::Layer<T>::SaveToFile(std::string filename)
{
return olc::FAIL;
}
template <class T>
T* TILE::Layer<T>::GetTile(int32_t x, int32_t y)
{
if (x < 0 || x >= nLayerWidth || y < 0 || y >= nLayerHeight)
return nullptr;
else
return &pTiles[y*nLayerWidth + x];
}
template<typename T>
void TILE::DrawLayer(olc::TILE::Layer<T> &layer, olc::TILE::Atlas &atlas, float cam_x, float cam_y, int32_t tiles_x, int32_t tiles_y, int nScale)
{
float fOffsetX = cam_x - (int)cam_x;
float fOffsetY = cam_y - (int)cam_y;
for (int32_t x = 0; x < tiles_x; x++)
{
for (int32_t y = 0; y < tiles_y; y++)
{
olc::TILE::BasicTile *t = layer.GetTile(x + (int)cam_x, y + (int)cam_y);
if (t != nullptr && t->exist)
{
float fx = (int)(((float)x - fOffsetX) * (float)(layer.nTileWidth));
float fy = (int)(((float)y - fOffsetY) * (float)(layer.nTileHeight));
pge->DrawPartialSprite(
fx + 0.5f - (fx < 0.0f),
fy + 0.5f - (fy < 0.0f),
atlas.sprTileSheet,
std::get<0>(atlas.location[t->id]),
std::get<1>(atlas.location[t->id]),
std::get<2>(atlas.location[t->id]),
std::get<3>(atlas.location[t->id]),
nScale);
}
}
}
}
template<typename T>
olc::Pixel TILE::GetLayerPixel(olc::TILE::Layer<T> &layer, olc::TILE::Atlas &atlas, float x, float y)
{
olc::TILE::BasicTile *t = layer.GetTile((int32_t)x, (int32_t)y);
if (t != nullptr)
{
float fOffsetX = x - (int)x;
float fOffsetY = y - (int)y;
return atlas.sprTileSheet->GetPixel(std::get<0>(atlas.location[t->id]) + fOffsetX * std::get<2>(atlas.location[t->id]),
std::get<1>(atlas.location[t->id]) + fOffsetX * std::get<3>(atlas.location[t->id]));
}
else
return olc::BLANK;
}
template<typename T>
std::vector<olc::TILE::Edge> TILE::ExtractEdgesFromLayer(olc::TILE::Layer<T> &layer, int sx, int sy, int width, int height)
{
enum
{
NORTH = 0,
EAST = 1,
SOUTH = 2,
WEST = 3
};
std::vector<olc::TILE::Edge> vecEdges;
for (int x = -1; x < width + 1; x++)
for (int y = -1; y < height + 1; y++)
for (int j = 0; j < 4; j++)
{
if ((x + sx) >= 0 && (y + sy) >= 0 && (x + sx) < (layer.nLayerWidth - 1) && (y + sy) < (layer.nLayerHeight - 1))
{
layer.GetTile(x + sx, y + sy)->edge_exist[j] = false;
layer.GetTile(x + sx, y + sy)->edge_id[j] = 0;
}
}
// Add boundary edges
vecEdges.push_back({ (float)(sx)* layer.nTileWidth, (float)(sy)*layer.nTileHeight, (float)(sx + width)*layer.nTileWidth, (float)(sy)*layer.nTileHeight });
vecEdges.push_back({ (float)(sx + width)* layer.nTileWidth, (float)(sy)*layer.nTileHeight, (float)(sx + width)*layer.nTileWidth, (float)(sy + height)*layer.nTileHeight });
vecEdges.push_back({ (float)(sx + width)* layer.nTileWidth, (float)(sy + height)*layer.nTileHeight, (float)(sx)*layer.nTileWidth, (float)(sy + height)*layer.nTileHeight });
vecEdges.push_back({ (float)(sx)* layer.nTileWidth, (float)(sy + height)*layer.nTileHeight, (float)(sx)*layer.nTileWidth, (float)(sy)*layer.nTileHeight });
// Iterate through region from top left to bottom right
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
T* i = layer.GetTile(x + sx, y + sy); //This
T* n = layer.GetTile(x + sx, y + sy - 1);
T* s = layer.GetTile(x + sx, y + sy + 1);
T* w = layer.GetTile(x + sx - 1, y + sy);
T* e = layer.GetTile(x + sx + 1, y + sy);
// If this cell exists, check if it needs edges
if (i->exist)
{
// If this cell has no western neighbour, it needs a western edge
if (w && !w->exist)
{
// It can either extend it from its northern neighbour if they have
// one, or It can start a new one.
if (n && n->edge_exist[WEST])
{
// Northern neighbour has a western edge, so grow it downwards
vecEdges[n->edge_id[WEST]].ey += layer.nTileHeight;
i->edge_id[WEST] = n->edge_id[WEST];
i->edge_exist[WEST] = true;
}
else
{
// Northern neighbour does not have one, so create one
olc::TILE::Edge edge;
edge.sx = (sx + x) * layer.nTileWidth; edge.sy = (sy + y) * layer.nTileHeight;
edge.ex = edge.sx; edge.ey = edge.sy + layer.nTileHeight;
// Add edge to Polygon Pool
int edge_id = vecEdges.size();
vecEdges.push_back(edge);
// Update tile information with edge information
i->edge_id[WEST] = edge_id;
i->edge_exist[WEST] = true;
}
}
// If this cell dont have an eastern neignbour, It needs a eastern edge
if (e && !e->exist)
{
// It can either extend it from its northern neighbour if they have
// one, or It can start a new one.
if (n && n->edge_exist[EAST])
{
// Northern neighbour has one, so grow it downwards
vecEdges[n->edge_id[EAST]].ey += layer.nTileHeight;
i->edge_id[EAST] = n->edge_id[EAST];
i->edge_exist[EAST] = true;
}
else
{
// Northern neighbour does not have one, so create one
olc::TILE::Edge edge;
edge.sx = (sx + x + 1) * layer.nTileWidth; edge.sy = (sy + y) * layer.nTileHeight;
edge.ex = edge.sx; edge.ey = edge.sy + layer.nTileHeight;
// Add edge to Polygon Pool
int edge_id = vecEdges.size();
vecEdges.push_back(edge);
// Update tile information with edge information
i->edge_id[EAST] = edge_id;
i->edge_exist[EAST] = true;
}
}
// If this cell doesnt have a northern neignbour, It needs a northern edge
if (n && !n->exist)
{
// It can either extend it from its western neighbour if they have
// one, or It can start a new one.
if (w && w->edge_exist[NORTH])
{
// Western neighbour has one, so grow it eastwards
vecEdges[w->edge_id[NORTH]].ex += layer.nTileWidth;
i->edge_id[NORTH] = w->edge_id[NORTH];
i->edge_exist[NORTH] = true;
}
else
{
// Western neighbour does not have one, so create one
olc::TILE::Edge edge;
edge.sx = (sx + x) * layer.nTileWidth; edge.sy = (sy + y) * layer.nTileHeight;
edge.ex = edge.sx + layer.nTileWidth; edge.ey = edge.sy;
// Add edge to Polygon Pool
int edge_id = vecEdges.size();
vecEdges.push_back(edge);
// Update tile information with edge information
i->edge_id[NORTH] = edge_id;
i->edge_exist[NORTH] = true;
}
}
// If this cell doesnt have a southern neignbour, It needs a southern edge
if (s && !s->exist)
{
// It can either extend it from its western neighbour if they have
// one, or It can start a new one.
if (w && w->edge_exist[SOUTH])
{
// Western neighbour has one, so grow it eastwards
vecEdges[w->edge_id[SOUTH]].ex += layer.nTileWidth;
i->edge_id[SOUTH] = w->edge_id[SOUTH];
i->edge_exist[SOUTH] = true;
}
else
{
// Western neighbour does not have one, so I need to create one
olc::TILE::Edge edge;
edge.sx = (sx + x) * layer.nTileWidth; edge.sy = (sy + y + 1) * layer.nTileHeight;
edge.ex = edge.sx + layer.nTileWidth; edge.ey = edge.sy;
// Add edge to Polygon Pool
int edge_id = vecEdges.size();
vecEdges.push_back(edge);
// Update tile information with edge information
i->edge_id[SOUTH] = edge_id;
i->edge_exist[SOUTH] = true;
}
}
}
}
return vecEdges;
}
TILE::Atlas::Atlas()
{
}
void TILE::Atlas::Create(olc::Sprite *tileSheet)
{
sprTileSheet = tileSheet;
location.clear();
}
olc::rcode TILE::Atlas::LoadFromFile(std::string filename)
{
return olc::FAIL;
}
olc::rcode TILE::Atlas::SaveToFile(std::string filename)
{
return olc::FAIL;
}
}