Gamedev Framework (gf) 1.2.0
A C++17 framework for 2D games
Array2D.h
1/*
2 * Gamedev Framework (gf)
3 * Copyright (C) 2016-2022 Julien Bernard
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21#ifndef ARRAY2D_H
22#define ARRAY2D_H
23
24#include <cassert>
25#include <algorithm>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
30#include "CoreApi.h"
31#include "Math.h"
32#include "Range.h"
33#include "SerializationFwd.h"
34#include "Vector.h"
35
36namespace gf {
37#ifndef DOXYGEN_SHOULD_SKIP_THIS
38inline namespace v1 {
39#endif
40
49 template<typename I>
50 class Index2D {
51 public:
58 : m_size(0, 0)
59 {
60 }
61
68 : m_size(size)
69 {
70 }
71
75 Index2D(const Index2D&) = default;
76
80 Index2D& operator=(const Index2D&) = default;
81
85 Index2D(Index2D&&) = default;
86
90 Index2D& operator=(Index2D&&) = default;
91
97 void swap(Index2D& other) {
98 std::swap(m_size, other.m_size);
99 }
100
111 constexpr Vector<I, 2> getSize() const noexcept {
112 return m_size;
113 }
114
120 constexpr I getCols() const noexcept {
121 return m_size.col;
122 }
123
129 constexpr I getRows() const noexcept {
130 return m_size.row;
131 }
132
140 constexpr bool isValid(Vector<I, 2> pos) const noexcept {
141 return pos.col < m_size.col && pos.row < m_size.row && (std::is_unsigned<I>::value || (0 <= pos.col && 0 <= pos.row));
142 }
143
150 constexpr Vector<I, 2> toPosition(std::size_t index) const noexcept {
151 return { static_cast<I>(index % m_size.col), static_cast<I>(index / m_size.col) };
152 }
153
160 constexpr std::size_t toIndex(Vector<I, 2> pos) const noexcept {
161 return pos.row * m_size.col + pos.col;
162 }
163
176 constexpr RangeZ getIndexRange() const noexcept {
177 return { 0, static_cast<std::size_t>(m_size.col) * static_cast<std::size_t>(m_size.row) };
178 }
179
185 constexpr Range<I> getRowRange() const noexcept {
186 return { 0, m_size.row };
187 }
188
194 constexpr Range<I> getColRange() const noexcept {
195 return { 0, m_size.col };
196 }
197
203 constexpr PositionRange<I> getPositionRange() const noexcept {
204 return { getColRange(), getRowRange() };
205 }
206
214 return getNeighborSquareRange(pos, 1);
215 }
216
224 return getNeighborSquareRange(pos, 2);
225 }
226
234 return getNeighborDiamondRange(pos, 1);
235 }
236
244 return getNeighborDiamondRange(pos, 2);
245 }
246
249 private:
250 NeighborSquareRange<I> getNeighborSquareRange(Vector<I, 2> pos, I n) const noexcept {
251 assert(isValid(pos));
252
253 auto colMin = pos.col - std::min(pos.col, n);
254 auto colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
255 auto rowMin = pos.row - std::min(pos.row, n);
256 auto rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
257
258 return NeighborSquareRange<I>{ Range<I>{ colMin, colMax + 1 }, Range<I>{ rowMin, rowMax + 1 }, pos };
259 }
260
261 NeighborDiamondRange<I> getNeighborDiamondRange(Vector<I, 2> pos, I n) const noexcept {
262 assert(isValid(pos));
263
264 auto colMin = pos.col - std::min(pos.col, n);
265 auto colMax = pos.col + std::min(m_size.col - pos.col - 1, n);
266 auto rowMin = pos.row - std::min(pos.row, n);
267 auto rowMax = pos.row + std::min(m_size.row - pos.row - 1, n);
268
269 return NeighborDiamondRange<I>{ Range<I>{ colMin, colMax + 1 }, Range<I>{ rowMin, rowMax + 1 }, pos, n };
270 }
271
272 private:
273 Vector<I, 2> m_size;
274 };
275
276// MSVC does not like extern template
277#ifndef _MSC_VER
278 extern template class GF_CORE_API Index2D<unsigned>;
279 extern template class GF_CORE_API Index2D<int>;
280#endif
281
303 template<typename T, typename I = unsigned>
304 class Array2D : public Index2D<I> {
305 public:
312 : Index2D<I>()
313 {
314 }
315
322 : Index2D<I>(size)
323 , m_data(static_cast<std::size_t>(size.width) * static_cast<std::size_t>(size.height))
324 {
325 }
326
333 Array2D(Vector<I, 2> size, const T& value)
334 : Index2D<I>(size)
335 , m_data(static_cast<std::size_t>(size.width) * static_cast<std::size_t>(size.height), value)
336 {
337 }
338
342 Array2D(const Array2D&) = default;
343
347 Array2D& operator=(const Array2D&) = default;
348
352 Array2D(Array2D&&) = default;
353
357 Array2D& operator=(Array2D&&) = default;
358
364 void swap(Array2D& other) {
365 Index2D<I>::swap(other);
366 std::swap(m_data, other.m_data);
367 }
368
381
395 const T *getDataPtr() const noexcept {
396 return m_data.data();
397 }
398
404 std::size_t getDataSize() const noexcept {
405 return m_data.size();
406 }
407
416 constexpr bool isEmpty() const noexcept {
417 return m_data.empty();
418 }
419
433 return get(pos);
434 }
435
442 T& operator()(std::size_t index) {
443 return m_data[index];
444 }
445
451 const T& operator()(Vector<I, 2> pos) const {
452 return get(pos);
453 }
454
461 const T& operator()(std::size_t index) const {
462 return m_data[index];
463 }
464
479 const T *begin() const noexcept {
480 return m_data.data();
481 }
482
489 const T *end() const noexcept {
490 return m_data.data() + m_data.size();
491 }
492
499 T *begin() noexcept {
500 return m_data.data();
501 }
502
509 T *end() noexcept {
510 return m_data.data() + m_data.size();
511 }
512
515 private:
516 T& get(Vector<I, 2> pos) {
517 return m_data[toIndex(pos)];
518 }
519
520 const T& get(Vector<I, 2> pos) const {
521 return m_data[toIndex(pos)];
522 }
523
524 private:
525 std::vector<T> m_data;
526 };
527
532 template<typename T, typename I>
533 bool operator==(const Array2D<T,I>& lhs, const Array2D<T,I>& rhs) {
534 auto lhsSize = lhs.getSize();
535 auto rhsSize = rhs.getSize();
536
537 if (lhsSize.width != rhsSize.width || lhsSize.height != rhsSize.height) {
538 return false;
539 }
540
541 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
542 }
543
548 template<typename T, typename I>
550 auto size = array.getSize();
551 ar | size.width | size.height;
552
553 for (auto& item : array) {
554 ar | const_cast<T&>(item);
555 }
556
557 return ar;
558 }
559
564 template<typename T, typename I>
566 Vector<I, 2> size;
567 ar | size.width | size.height;
568
569 Array2D<T,I> tmp(size);
570
571 for (auto& item : tmp) {
572 ar | item;
573 }
574
575 array = std::move(tmp);
576 return ar;
577 }
578
579
580#ifndef DOXYGEN_SHOULD_SKIP_THIS
581}
582#endif
583}
584
585#endif // ARRAY2D_H
A two-dimensional array.
Definition: Array2D.h:304
std::size_t getDataSize() const noexcept
Get the raw data size.
Definition: Array2D.h:404
Array2D()
Default constructor.
Definition: Array2D.h:311
const T & operator()(std::size_t index) const
Get the element at a given 1D index.
Definition: Array2D.h:461
const T * getDataPtr() const noexcept
Get the pointer to raw data.
Definition: Array2D.h:395
Array2D(Vector< I, 2 > size)
Constructor with a size.
Definition: Array2D.h:321
T * end() noexcept
Get an iterator to the element following the last element of the array.
Definition: Array2D.h:509
Array2D & operator=(const Array2D &)=default
Default copy assignment.
T & operator()(std::size_t index)
Get the element at a given 1D index.
Definition: Array2D.h:442
Array2D & operator=(Array2D &&)=default
Default move assignement.
Serializer & operator|(Serializer &ar, const Array2D< T, I > &array)
Serialize a 2D array.
Definition: Array2D.h:549
void swap(Array2D &other)
Swap with another array.
Definition: Array2D.h:364
T & operator()(Vector< I, 2 > pos)
Get the element at a given 2D position.
Definition: Array2D.h:432
bool operator==(const Array2D< T, I > &lhs, const Array2D< T, I > &rhs)
Equality operator for 2D array.
Definition: Array2D.h:533
const T * end() const noexcept
Get an iterator to the element following the last element of the array.
Definition: Array2D.h:489
constexpr bool isEmpty() const noexcept
Check if the array is empty.
Definition: Array2D.h:416
T * begin() noexcept
Get an iterator to the first element of the array.
Definition: Array2D.h:499
const T & operator()(Vector< I, 2 > pos) const
Get the element at a given 2D position.
Definition: Array2D.h:451
Array2D(Vector< I, 2 > size, const T &value)
Constructor with a size and a value.
Definition: Array2D.h:333
Array2D(Array2D &&)=default
Default move constructor.
Array2D(const Array2D &)=default
Default copy constructor.
const T * begin() const noexcept
Get an iterator to the first element of the array.
Definition: Array2D.h:479
Deserializer & operator|(Deserializer &ar, Array2D< T, I > &array)
Deserialize a 2D array.
Definition: Array2D.h:565
A deserializer from a binary file.
Definition: Serialization.h:151
A two-dimensional array with no data.
Definition: Array2D.h:50
Index2D & operator=(const Index2D &)=default
Default copy assignment.
void swap(Index2D &other)
Swap with another array.
Definition: Array2D.h:97
constexpr Range< I > getColRange() const noexcept
Get the column range.
Definition: Array2D.h:194
constexpr RangeZ getIndexRange() const noexcept
Get the 1D index range of the array.
Definition: Array2D.h:176
constexpr Vector< I, 2 > getSize() const noexcept
Get the size of the array.
Definition: Array2D.h:111
constexpr Vector< I, 2 > toPosition(std::size_t index) const noexcept
Transform a 1D position into a 2D position.
Definition: Array2D.h:150
Index2D(const Index2D &)=default
Default copy constructor.
Index2D & operator=(Index2D &&)=default
Default move assignement.
NeighborDiamondRange< I > get12NeighborsRange(Vector< I, 2 > pos) const noexcept
Get a range for 12 neighbors (at most)
Definition: Array2D.h:243
NeighborDiamondRange< I > get4NeighborsRange(Vector< I, 2 > pos) const noexcept
Get a range for 4 neighbors (at most)
Definition: Array2D.h:233
constexpr PositionRange< I > getPositionRange() const noexcept
Get the position range.
Definition: Array2D.h:203
Index2D(Vector< I, 2 > size)
Constructor with a size.
Definition: Array2D.h:67
constexpr bool isValid(Vector< I, 2 > pos) const noexcept
Check if a position is valid.
Definition: Array2D.h:140
constexpr I getRows() const noexcept
Get the number of rows.
Definition: Array2D.h:129
constexpr I getCols() const noexcept
Get the number of columns.
Definition: Array2D.h:120
Index2D(Index2D &&)=default
Default move constructor.
Index2D()
Default constructor.
Definition: Array2D.h:57
constexpr Range< I > getRowRange() const noexcept
Get the row range.
Definition: Array2D.h:185
NeighborSquareRange< I > get8NeighborsRange(Vector< I, 2 > pos) const noexcept
Get a range for 8 neighbors (at most)
Definition: Array2D.h:213
NeighborSquareRange< I > get24NeighborsRange(Vector< I, 2 > pos) const noexcept
Get a range for 24 neighbors (at most)
Definition: Array2D.h:223
constexpr std::size_t toIndex(Vector< I, 2 > pos) const noexcept
Transform a 2D position into a 1D position.
Definition: Array2D.h:160
A serializer to a binary file.
Definition: Serialization.h:43
The namespace for gf classes.
template class GF_CORE_API Index2D< int >
template class GF_CORE_API Index2D< unsigned >
A 2D range.
Definition: Range.h:595
A 2D range.
Definition: Range.h:426
A 2D range.
Definition: Range.h:278
A half-open range of values.
Definition: Range.h:44