Implemented grid. Modified map renderer so that it can render tiles that have a different size than the map tiles. (Note: this change is not tested yet).

This commit is contained in:
2016-12-06 00:29:43 +02:00
parent 0dc77aacb4
commit c12a8ede5a
42 changed files with 1090 additions and 288 deletions

27
src/utils/ICloneable.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* ICloneable.h
*
* Created on: Dec 2, 2016
* Author: tibi
*/
#ifndef BASE_ICLONEABLE_H_
#define BASE_ICLONEABLE_H_
namespace farmlands {
namespace utils {
template <typename T>
class ICloneable
{
public:
virtual ~ICloneable() { };
virtual T* clone() = 0;
};
}
}
#endif /* BASE_ICLONEABLE_H_ */

View File

@@ -0,0 +1,28 @@
/*
* INonAssignable.h
*
* Created on: Dec 2, 2016
* Author: tibi
*/
#ifndef BASE_INONASSIGNABLE_H_
#define BASE_INONASSIGNABLE_H_
namespace farmlands {
namespace utils {
class INonAssignable
{
public:
virtual ~INonAssignable() { };
INonAssignable() { }
INonAssignable(const INonAssignable&) = delete;
INonAssignable& operator=(const INonAssignable&) = delete;
};
}
}
#endif /* BASE_INONASSIGNABLE_H_ */

265
src/utils/QTree.h Normal file
View File

@@ -0,0 +1,265 @@
/*
* QTree.h
*
* Created on: Dec 4, 2016
* Author: tibi
*/
#ifndef UTILS_QTREE_H_
#define UTILS_QTREE_H_
#include <utils/Assert.h>
#include <utils/INonAssignable.h>
#include <utils/Rect.h>
namespace farmlands {
namespace utils {
#if 0
// Commented because no longer needed.
template <typename T>
struct QTreeItem
{
T data;
float x, y;
};
/**
* Quad tree
*/
template <typename T, size_t Capacity>
class QTree : public INonAssignable
{
public:
typedef int iterator;
QTree(const RectF& bounds);
virtual ~QTree();
// Container operations
iterator begin();
iterator end();
bool empty() const;
size_t size() const;
void insert(T element, float x, float y);
void erase(iterator it);
void clear();
iterator find(T element);
iterator find(float x, float y);
iterator lower_bound(float x, float y);
iterator lower_bound(float x, float y, float distance);
iterator lower_bound(const RectF& area);
iterator upper_bound(float x, float y);
iterator upper_bound(float x, float y, float distance);
iterator upper_bound(const RectF& area);
private:
void subdivide();
void merge();
RectF m_bounds;
bool m_isSplit;
QTree* m_children[4];
QTreeItem m_items[Capacity];
size_t m_itemsCount;
};
template<typename T, size_t Capacity>
QTree<T, Capacity>::QTree(const RectF& bounds)
: m_bounds(bounds),
m_isSplit(false),
m_children(),
m_items(),
m_itemsCount(0)
{
}
template<typename T, size_t Capacity>
QTree<T, Capacity>::~QTree()
{
if (m_isSplit)
{
for (size_t i = 0; i < 4; i++)
delete m_children[i];
}
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::begin()
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::end()
{
}
template<typename T, size_t Capacity>
inline bool QTree<T, Capacity>::empty() const
{
return (m_itemsCount == 0);
}
template<typename T, size_t Capacity>
inline size_t QTree<T, Capacity>::size() const
{
return m_itemsCount;
}
template<typename T, size_t Capacity>
inline void QTree<T, Capacity>::insert(T element, float x, float y)
{
Assert(m_bounds.contains(x, y), "Can't add element outside bounds.");
// Not split case
if (!m_isSplit && m_itemsCount >= Capacity)
subdivide();
// If split, add element in one of the subtrees
if (m_isSplit)
{
for (size_t i = 0; i < 4; i++)
if (m_children[i]->m_bounds.contains(x, y))
{
m_children[i]->insert(element, x, y);
return;
}
}
else
{
QTreeItem<T> item =
{
.data = element,
.x = x,
.y = y
};
m_items[m_itemsCount] = item;
}
m_itemsCount++;
}
template<typename T, size_t Capacity>
inline void QTree<T, Capacity>::erase(iterator it)
{
}
template<typename T, size_t Capacity>
inline void QTree<T, Capacity>::clear()
{
if (m_isSplit)
{
for (size_t i = 0; i < 4; i++)
delete m_children[i];
m_isSplit = false;
}
m_itemsCount = 0;
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::find(T element)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::find(float x, float y)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::lower_bound(float x, float y)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::lower_bound(float x, float y, float distance)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::lower_bound(const RectF& area)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::upper_bound(float x, float y)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::upper_bound(float x, float y, float distance)
{
}
template<typename T, size_t Capacity>
inline QTree<T, Capacity>::iterator QTree<T, Capacity>::upper_bound(const RectF& area)
{
}
template<typename T, size_t Capacity>
void QTree<T, Capacity>::subdivide()
{
Assert(!m_isSplit, "Can't subdivide if already subdivided!");
float halfW = m_bounds.w / 2;
float halfH = m_bounds.h / 2;
RectF rects[4] =
{
{ m_bounds.x, m_bounds.y, halfW, halfH },
{ m_bounds.x + halfW, m_bounds.y, halfW, halfH },
{ m_bounds.x, m_bounds.y + halfH, halfW, halfH },
{ m_bounds.x + halfW, m_bounds.y + halfH, halfW, halfH },
};
// Allocate subtrees
for (size_t i = 0; i < 4; i++)
m_children[i] = new QTree<T, Capacity>(rects[i]);
// Set split flag
m_isSplit = true;
// Re-insert all the children
size_t itemsCount = m_itemsCount;
m_itemsCount = 0;
for (size_t i = 0; i < itemsCount; i++)
insert(m_items[i].data, m_items[i].x, m_items[i].y);
}
template<typename T, size_t Capacity>
void QTree<T, Capacity>::merge()
{
Assert(m_isSplit, "Can't merge if not subdivided!");
// Unset split flag
m_isSplit = false;
// Put all the children in their places
m_itemsCount = 0;
for (size_t i = 0; i < 4; i++)
{
Assert(!m_children[i].m_isSplit, "Cannot merge if children are split!!!");
for (size_t j = 0; j < m_children[i].m_itemsCount; j++)
insert(m_children[i].m_items[j].data, m_children[i].m_items[j].x, m_children[i].m_items[j].y);
delete m_children[i];
}
}
#endif
} /* namespace utils */
} /* namespace farmlands */
#endif /* UTILS_QTREE_H_ */

50
src/utils/Rect.h Normal file
View File

@@ -0,0 +1,50 @@
/*
* Rect.h
*
* Created on: Dec 4, 2016
* Author: tibi
*/
#ifndef UTILS_RECT_H_
#define UTILS_RECT_H_
namespace farmlands {
namespace utils {
template <typename T>
class Rect
{
public:
// Constructors
Rect()
: x(), y(), w(), h() { }
Rect(T x, T y, T w, T h)
: x(x), y(y), w(w), h(h) { }
bool contains(T px, T py)
{
bool containsX = (x <= px && px <= x + w);
bool containsY = (y <= px && px <= x + w);
return containsX && containsY;
}
bool intersects(const Rect<T> other)
{
bool intersectsX = (x <= other.x && other.x <= x + w) || (other.x <= x && other.x + other.w >= x);
bool intersectsY = (y <= other.y && other.y <= y + h) || (other.y <= y && other.y + other.h >= y);
return intersectsX && intersectsY;
}
// Values
T x, y, w, h;
};
typedef Rect<float> RectF;
} /* namespace utils */
} /* namespace farmlands */
#endif /* UTILS_RECT_H_ */