Advancing in the design of Tyler.

Iterating through tiles in viewports now works fine.
You can pass in a custom device as the data source for the tile map.
This commit is contained in:
King_DuckZ 2014-12-29 16:17:59 +01:00
parent d5c199f3b9
commit c9381a4585
12 changed files with 268 additions and 54 deletions

View file

@ -2,10 +2,12 @@
#define idD3EDC396AA314474B3D909559FFC0247
#include "primitivetypes.hpp"
#include "components/tilestreamer.hpp"
#include "components/tileiterator.hpp"
#include "components/tilemapdata.hpp"
#include "implem/helpers.hpp"
#include <algorithm>
#include <vector>
#include <memory>
namespace dk {
template <size_t D>
@ -21,11 +23,14 @@ namespace dk {
virtual void preload ( const coords& parFrom, const coords& parTo ) = 0;
coords count ( void ) const { return m_mastersize / m_tilesize * m_count; }
const coords& mapSize ( void ) const { return m_count; }
protected:
coords m_count;
coords m_tilesize;
coords m_mastersize;
private:
};
template <typename T, size_t D>
@ -34,12 +39,11 @@ namespace dk {
public:
typedef typename LayerBase<D>::coords coords;
typedef TileStreamer<T, D> streamer_type;
typedef TileIterator<T, D> iterator;
Layer ( const Layer& ) = delete;
Layer ( Layer&& ) = default;
Layer ( const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize, streamer_type&& parStreamer );
Layer ( const coords& parTileSize, const coords& parMasterTileSize, TileMapData<T, D>& parTilemap );
virtual ~Layer ( void ) noexcept = default;
Layer& operator= ( const Layer& ) = delete;
@ -49,14 +53,9 @@ namespace dk {
virtual void preload ( const coords& parFrom, const coords& parTo );
private:
streamer_type m_streamer;
std::vector<T> m_tiles;
TileMapData<T, D>& m_tilemap;
};
namespace implem {
template <size_t D>
typename LayerBase<D>::coords::value_type area ( const typename LayerBase<D>::coords& parVec ) a_pure;
}
} //namespace dk
#include "implem/layer.inl"

View file

@ -0,0 +1,67 @@
#ifndef id8F5106DFABC14263ADF235C56E434207
#define id8F5106DFABC14263ADF235C56E434207
#include "primitivetypes.hpp"
#include "implem/compatibility.h"
#include "implem/vector.hpp"
#include "implem/helpers.hpp"
#include <cstddef>
#include <type_traits>
#include <iterator>
namespace dk {
namespace implem {
template <typename T>
class HasMapDimensions {
class yes { char m; };
class nope { yes m[2]; };
static yes deduce ( int a, int b = T::MapDimensions );
static nope deduce ( ... );
public:
enum {
result = (sizeof(yes) == sizeof(deduce(1)))
};
};
template <std::size_t D, typename Device>
typename std::enable_if<Device::MapDimensions == D, std::size_t>::type err_mismatching_dimension ( const Device* ) noexcept a_pure;
template <std::size_t D, typename Device>
typename std::enable_if<HasMapDimensions<Device>::result == false, std::size_t>::type err_mismatching_dimension ( const Device* ) noexcept a_pure;
template <std::size_t D, typename Device>
typename std::enable_if<Device::MapDimensions == D, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device ( Device* parDevice );
template <std::size_t D, typename Device>
typename std::enable_if<HasMapDimensions<Device>::result == false, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device ( Device* parDevice );
} //namespace implem
//Customization point - specialize to enable map size retrieval for Device
template <std::size_t D, typename Device>
typename Device::coords get_map_size_from_device ( const Device* parDevice );
template <typename T, std::size_t D>
class TileMapData {
public:
typedef Vector<CoordinateScalarType, D> coords;
TileMapData ( void ) = delete;
template <typename Device>
explicit TileMapData ( Device& parDevice );
//TODO: add an overload to initialize a TileMapData from a universal reference to std::istream
~TileMapData ( void ) noexcept = default;
bool streamHasDimensionInfo ( void ) const { return m_deviceHasDim; }
void fetch ( std::vector<T>& parOut, const coords& parFrom, const coords& parTo );
const coords& mapSize ( void ) const;
private:
std::istream m_stream;
const coords m_mapSize;
const bool m_deviceHasDim;
};
} //namespace dk
#include "implem/tilemapdata.inl"
#endif

View file

@ -8,6 +8,9 @@
#include <memory>
namespace dk {
template <typename T, size_t D>
class TileMapData;
template <size_t D>
class Tyler {
typedef std::unique_ptr<LayerBase<D>> LayerPtr;
@ -23,9 +26,9 @@ namespace dk {
const coords& map_size ( void ) const { return m_size; }
template <typename T>
Layer<T, D>& push_layer ( typename Layer<T, D>::streamer_type&& parStreamer );
Layer<T, D>& push_layer ( TileMapData<T, D>& parTilemap );
template <typename T>
Layer<T, D>& push_layer ( typename Layer<T, D>::streamer_type&& parStreamer, const coords& parSubdiv );
Layer<T, D>& push_layer ( TileMapData<T, D>& parTilemap, const coords& parSubdiv );
void preload ( const coords& parFrom, const coords& parTo );

View file

@ -26,6 +26,7 @@ namespace dk {
void setSize ( const coords& parSize );
void setFrom ( const coords& parFrom );
void setFromSize ( const coords& parFrom, const coords& parSize );
const coords& count ( void ) const { return m_size; }
template <typename T>
typename Layer<T, D>::iterator begin ( Layer<T, D>& parLayer ) const;

View file

@ -5,5 +5,6 @@
#include "components/tyler.hpp"
#include "components/viewport.hpp"
#include "components/layer.hpp"
#include "components/tilemapdata.hpp"
#endif

View file

@ -0,0 +1,13 @@
#ifndef id61F9FA08290643D0A947EC0E51060BEA
#define id61F9FA08290643D0A947EC0E51060BEA
namespace dk {
namespace implem {
template <size_t D>
CoordinateScalarType area ( const Vector<CoordinateScalarType, D>& parVec ) a_pure;
} //namespace implem
} //namespace dk
#include "implem/helpers.inl"
#endif

View file

@ -0,0 +1,15 @@
namespace dk {
namespace implem {
///----------------------------------------------------------------------
///----------------------------------------------------------------------
template <size_t D>
CoordinateScalarType area (const Vector<CoordinateScalarType, D>& parVec) {
CoordinateScalarType retval(1);
for (size_t d = 0; d < D; ++d) {
retval *= parVec[d];
}
return retval;
}
} //namespake implem
} //namespake dk

View file

@ -1,22 +1,9 @@
namespace dk {
namespace implem {
///----------------------------------------------------------------------
///----------------------------------------------------------------------
template <size_t D>
typename LayerBase<D>::coords::value_type area (const typename LayerBase<D>::coords& parVec) {
typename LayerBase<D>::coords::value_type retval(1);
for (size_t d = 0; d < D; ++d) {
retval *= parVec[d];
}
return retval;
}
}
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <size_t D>
LayerBase<D>::LayerBase (const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize) :
m_count(parCount),
m_count(parCount / (parMasterTileSize / parTileSize)),
m_tilesize(parTileSize),
m_mastersize(parMasterTileSize)
{
@ -26,11 +13,10 @@ namespace dk {
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
template <typename T, size_t D>
Layer<T, D>::Layer (const coords& parCount, const coords& parTileSize, const coords& parMasterTileSize, streamer_type&& parStreamer) :
LayerBase<D>(parCount, parTileSize, parMasterTileSize),
m_streamer(std::move(parStreamer))
Layer<T, D>::Layer (const coords& parTileSize, const coords& parMasterTileSize, TileMapData<T, D>& parTilemap) :
LayerBase<D>(parTilemap.mapSize(), parTileSize, parMasterTileSize),
m_tilemap(parTilemap)
{
DK_ASSERT(m_streamer.tilesCount() == this->m_count);
}
///--------------------------------------------------------------------------
@ -52,8 +38,10 @@ namespace dk {
template <typename T, size_t D>
void Layer<T, D>::preload (const coords& parFrom, const coords& parTo) {
m_tiles.clear();
const auto area = implem::area<D>(parTo - parFrom);
std::cout << "Asking to fetch from " << parFrom << " to " << parTo << "\n";
const auto area = implem::area(parTo - parFrom);
m_tiles.reserve(area);
m_streamer.copy(m_tiles, parFrom, parTo);
m_tilemap.fetch(m_tiles, parFrom, parTo);
//m_streamer->copy(m_tiles, parFrom, parTo);:w
}
}

View file

@ -0,0 +1,71 @@
namespace dk {
namespace implem {
///---------------------------------------------------------------------
///Only enabled if Device::MapDimensions is defined and is the same
///as D. The function's name is set to give a hint to the user as to
///why the error has occurred (they are trying to construct a
///TileMapData with a set dimension that is different from the one
///hardcoded in the device being passed in). The actual name could be
///something like get_device_dimensions().
///---------------------------------------------------------------------
template <std::size_t D, typename Device>
typename std::enable_if<Device::MapDimensions == D, std::size_t>::type err_mismatching_dimension (const Device*) noexcept {
return Device::MapDimensions;
}
///---------------------------------------------------------------------
///Only enabled if Device::MapDimensions is not defined. The function's
///name is set to give a hint to the user as to why the error has
///occurred (they are trying to construct a TileMapData with a set
///dimension that is different from the one hardcoded in the device
///being passed in). The actual name could be something like
///get_device_dimensions().
///---------------------------------------------------------------------
template <std::size_t D, typename Device>
typename std::enable_if<HasMapDimensions<Device>::result == false, std::size_t>::type err_mismatching_dimension (const Device*) noexcept {
return 0;
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <std::size_t D, typename Device>
typename std::enable_if<Device::MapDimensions == D, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device (Device* parDevice) {
return parDevice->mapSize();
}
///---------------------------------------------------------------------
///---------------------------------------------------------------------
template <std::size_t D, typename Device>
typename std::enable_if<HasMapDimensions<Device>::result == false, Vector<CoordinateScalarType, D>>::type retrieve_map_size_from_device (Device* parDevice) {
return get_map_size_from_device<D>(parDevice);
}
} //namespace implem
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, std::size_t D>
template <typename Device>
TileMapData<T, D>::TileMapData (Device& parDevice) :
m_stream(&parDevice),
m_mapSize(implem::retrieve_map_size_from_device<D>(&parDevice)),
m_deviceHasDim(D == implem::err_mismatching_dimension<D>(&parDevice))
{
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, std::size_t D>
void TileMapData<T, D>::fetch (std::vector<T>& parOut, const coords& parFrom, const coords& parTo) {
//TODO: implement
std::cout << "Would fetch data from " << parFrom << " to " << parTo << "\n";
const auto count = implem::area(parTo - parFrom);
std::fill_n(std::back_inserter(parOut), count, T());
}
///-------------------------------------------------------------------------
///-------------------------------------------------------------------------
template <typename T, std::size_t D>
const typename TileMapData<T, D>::coords& TileMapData<T, D>::mapSize() const {
return m_mapSize;
}
} //namespace dk

View file

@ -24,8 +24,10 @@ namespace dk {
///--------------------------------------------------------------------------
template <size_t D>
template <typename T>
Layer<T, D>& Tyler<D>::push_layer (typename Layer<T, D>::streamer_type&& parStreamer) {
auto newLayer = new Layer<T, D>(m_size, m_tilesize, m_tilesize, std::move(parStreamer));
Layer<T, D>& Tyler<D>::push_layer (TileMapData<T, D>& parTilemap) {
auto newLayer = new Layer<T, D>(m_tilesize, m_tilesize, parTilemap);
DK_ASSERT(newLayer->mapSize() == m_size);
DK_ASSERT(newLayer->count() == m_size);
m_layers.push_back(LayerPtr(newLayer));
return *newLayer;
}
@ -34,8 +36,10 @@ namespace dk {
///--------------------------------------------------------------------------
template <size_t D>
template <typename T>
Layer<T, D>& Tyler<D>::push_layer (typename Layer<T, D>::streamer_type&& parStreamer, const coords& parSubdiv) {
auto newLayer = new Layer<T, D>(m_size * parSubdiv, m_tilesize / parSubdiv, m_tilesize, std::move(parStreamer));
Layer<T, D>& Tyler<D>::push_layer (TileMapData<T, D>& parTilemap, const coords& parSubdiv) {
auto newLayer = new Layer<T, D>(m_tilesize / parSubdiv, m_tilesize, parTilemap);
DK_ASSERT(newLayer->mapSize() == m_size);
DK_ASSERT(newLayer->count() == m_size * parSubdiv);
m_layers.push_back(LayerPtr(newLayer));
return *newLayer;
}
@ -44,6 +48,7 @@ namespace dk {
///--------------------------------------------------------------------------
template <size_t D>
void Tyler<D>::preload (const coords& parFrom, const coords& parTo) {
std::cout << "Looping through layers askin' for " << parFrom << " to " << parTo << "\n";
for (auto& layer : m_layers) {
layer->preload(parFrom, parTo);
}

View file

@ -11,6 +11,8 @@ namespace dk {
m_position(parPos),
m_tyler(parTyler)
{
DK_ASSERT(parPos <= parPos + parSize);
DK_ASSERT(parSize + parPos <= parTyler.map_size());
m_tyler.preload(m_position, m_position + m_size);
}
@ -33,18 +35,24 @@ namespace dk {
template <size_t D>
void Viewport<D>::setSize (const coords& parSize) {
DK_ASSERT(m_position <= m_position + parSize);
DK_ASSERT(parSize + m_position <= m_tyler.map_size());
m_size = parSize;
m_tyler.preload(m_position, m_position + m_size);
}
template <size_t D>
void Viewport<D>::setFrom (const coords& parFrom) {
DK_ASSERT(parFrom <= parFrom + m_size);
DK_ASSERT(m_size + parFrom <= m_tyler.map_size());
m_position = parFrom;
m_tyler.preload(m_position, m_position + m_size);
}
template <size_t D>
void Viewport<D>::setFromSize (const coords& parFrom, const coords& parSize) {
DK_ASSERT(parFrom <= parFrom + parSize);
DK_ASSERT(parSize + parFrom <= m_tyler.map_size());
m_position = parFrom;
m_size = parSize;
m_tyler.preload(m_position, m_position + m_size);

View file

@ -1,37 +1,53 @@
#include "doorkeeper.hpp"
#include "doorkeeperConfig.h"
#include "doorkeepertestConfig.h"
#include "platform.h"
#include "platformstrings.h"
#include "helpers/asciimapsource.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <memory>
template <typename Device, typename Tile>
struct LayerWithData {
std::unique_ptr<dk::TileMapData<Tile, 2>> tilemap;
std::unique_ptr<Device> device;
dk::Layer<Tile, 2>* layer;
std::string path;
};
namespace {
template <typename Device, typename Tile>
void createLayer ( dk::Tyler<2>& parTiler, LayerWithData<Device, Tile>& parOut );
void printWelcome ( void );
} //unnamed namespace
int main() {
typedef dk::Tyler<2> Tiler;
typedef std::unique_ptr<std::ifstream> ifstreamptr;
typedef dk::Tyler<2>::coords coords2;
using dk::TileMapData;
using dkh::AsciiMapSource;
std::cout << "Welcome to " << APP_NAME << ' ' << DK_DEVICE_STRING << " version for " << DK_OS_STRING << ' ' << DK_ARCH_STRING << ' ' << DK_BIT_STRING;
#if defined(DK_ARM)
std::cout << ' ' << DK_ARM_FAMILY_STRING << ' ' << DK_ARM_ARCH_STRING;
#endif
std::cout << '\n';
printWelcome();
Tiler tiler(Tiler::coords(10, 6), Tiler::coords(64));
dk::Tyler<2> tiler(coords2(10, 6), coords2(64));
const std::string map1(DATA_PATH"/test.map");
const std::string map2(DATA_PATH"/test_2.map");
LayerWithData<AsciiMapSource, int> bottomLayer;
bottomLayer.path = DATA_PATH"/test.map";
bottomLayer.device = std::unique_ptr<AsciiMapSource>(new AsciiMapSource(bottomLayer.path));
bottomLayer.tilemap = std::unique_ptr<TileMapData<int, 2>>(new TileMapData<int, 2>(*bottomLayer.device));
bottomLayer.layer = &tiler.push_layer(*bottomLayer.tilemap);
std::cout << "Loading " << map1 << '\n';
auto bottom_layer = &tiler.push_layer<int>(dk::Layer<int, 2>::streamer_type(ifstreamptr(new std::ifstream(map1))));
//std::cout << "Loading " << map2 << '\n';
//tiler.push_layer<char>(dk::Layer<char, 2>::streamer_type(ifstreamptr(new std::ifstream(map2))), dk::Vector<int, 2>(2));
LayerWithData<AsciiMapSource, int> topLayer;
topLayer.path = DATA_PATH"/test_2.map";
topLayer.device = std::unique_ptr<AsciiMapSource>(new AsciiMapSource(topLayer.path));
topLayer.tilemap = std::unique_ptr<TileMapData<int, 2>>(new TileMapData<int, 2>(*topLayer.device));
topLayer.layer = &tiler.push_layer(*topLayer.tilemap);
dk::Viewport<2> viewport(tiler, Tiler::coords(0), Tiler::coords(10, 6));
dk::Viewport<2> viewport_small(tiler, Tiler::coords(1), Tiler::coords(9, 5));
dk::Viewport<2> viewport(tiler, coords2(10, 6), coords2(0));
{
int col = 0;
const auto tilecount = bottom_layer->count();
for (auto tile : *bottom_layer) {
const auto tilecount = bottomLayer.layer->count();
for (auto tile : *bottomLayer.layer) {
std::cout << tile;
++col;
if (col == tilecount.x()) {
@ -40,6 +56,19 @@ int main() {
}
}
}
dk::Viewport<2> viewport_small(tiler, coords2(4, 4), coords2(0));
{
int col = 0;
const auto tilecount = viewport_small.count();
for (auto itTile = viewport_small.begin(*bottomLayer.layer), itTileEND = viewport_small.end(*bottomLayer.layer); itTile != itTileEND; ++itTile) {
std::cout << *itTile;
++col;
if (col == tilecount.x()) {
col = 0;
std::cout << '\n';
}
}
}
#if !defined(NDEBUG)
std::cout << "Map size: " << tiler.map_size() << '\n';
@ -47,3 +76,17 @@ int main() {
std::cout << "Total tiles: " << tiler.tiles_count() << '\n';
return 0;
}
namespace {
template <typename Device, typename Tile>
void createLayer (dk::Tyler<2>& parTiler, LayerWithData<Device, Tile>& parOut) {
}
void printWelcome() {
std::cout << "Welcome to " << APP_NAME << ' ' << DK_DEVICE_STRING << " version for " << DK_OS_STRING << ' ' << DK_ARCH_STRING << ' ' << DK_BIT_STRING;
#if defined(DK_ARM)
std::cout << ' ' << DK_ARM_FAMILY_STRING << ' ' << DK_ARM_ARCH_STRING;
#endif
std::cout << '\n';
}
} //unnamed namespace