diff --git a/CMakeLists.txt b/CMakeLists.txt
index ddae753..cd07e60 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,7 @@ add_executable(${PROJECT_NAME}
src/worldsizenotifiable.cpp
src/worlditems.cpp
src/moveable.cpp
+ src/singlecoordinate.cpp
)
target_include_directories(${PROJECT_NAME} SYSTEM
diff --git a/src/coordinates.hpp b/src/coordinates.hpp
new file mode 100644
index 0000000..d4d0b7a
--- /dev/null
+++ b/src/coordinates.hpp
@@ -0,0 +1,53 @@
+/*
+ Copyright 2016, 2017 Michele "King_DuckZ" Santullo
+
+ This file is part of MyCurry.
+
+ MyCurry is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MyCurry is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MyCurry. If not, see .
+*/
+
+#pragma once
+
+#include "vector.hpp"
+#include "singlecoordinate.hpp"
+
+namespace vwr {
+ template <>
+ struct VectorWrapperInfo> {
+ enum { dimensions = 2 };
+ typedef ::curry::SingleCoordinate scalar_type;
+ typedef std::array vector_type;
+ static scalar_type& get_at (size_t parIndex, vector_type& parVector) {
+ return parVector[parIndex];
+ }
+ };
+} //namespace vwr
+
+namespace curry {
+ using vec2c = vwr::Vec>;
+
+ inline vec2i to_screen_coordinates (vec2c parVec, const vec2i& parWorldOffset, vec2us parTileSize) {
+ return vec2i(
+ parVec.x().screen_coordinate(parWorldOffset.x(), parTileSize.x()),
+ parVec.y().screen_coordinate(parWorldOffset.y(), parTileSize.y())
+ );
+ }
+
+ inline vec2us to_tiles (vec2c parVec) {
+ return vec2us(
+ parVec.x().tile(),
+ parVec.y().tile()
+ );
+ }
+} //namespace curry
diff --git a/src/singlecoordinate.cpp b/src/singlecoordinate.cpp
new file mode 100644
index 0000000..781d3dc
--- /dev/null
+++ b/src/singlecoordinate.cpp
@@ -0,0 +1,26 @@
+/*
+ Copyright 2016, 2017 Michele "King_DuckZ" Santullo
+
+ This file is part of MyCurry.
+
+ MyCurry is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MyCurry is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MyCurry. If not, see .
+*/
+
+#include "singlecoordinate.hpp"
+#include "coordinates.hpp"
+
+namespace curry {
+ static_assert(implem::Log2<256>::result == 8, "Wrong logarithm result");
+ static_assert(implem::Log2<255>::result == 7, "Wrong logarithm result");
+} //namespace curry
diff --git a/src/singlecoordinate.hpp b/src/singlecoordinate.hpp
new file mode 100644
index 0000000..2ca9460
--- /dev/null
+++ b/src/singlecoordinate.hpp
@@ -0,0 +1,110 @@
+/*
+ Copyright 2016, 2017 Michele "King_DuckZ" Santullo
+
+ This file is part of MyCurry.
+
+ MyCurry is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ MyCurry is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with MyCurry. If not, see .
+*/
+
+#pragma once
+
+#include "vector.hpp"
+#include
+#include
+#include
+
+namespace curry {
+ namespace implem {
+ template 0)>
+ struct Log2;
+
+ template
+ struct Log2 {
+ static constexpr const uint32_t b[5] = {0x2, 0xc, 0xf0, 0xff00, 0xffff0000};
+ static constexpr const uint32_t S[5] = {1, 2, 4, 8, 16};
+ enum {
+ result = Log2<(V & b[I - 1] ? V >> S[I - 1] : V), (V & b[I - 1] ? R | S[I - 1] : R), I - 1>::result
+ };
+ };
+ template
+ struct Log2 {
+ enum {
+ result = R
+ };
+ };
+
+ template
+ struct NextPow2 {
+ static_assert(V > 0, "V must be greater than zero");
+ enum {
+ result = (1U << Log2::result) + 1
+ };
+ };
+ } //namespace implem
+
+ class SingleCoordinate {
+ public:
+ SingleCoordinate() = default;
+ SingleCoordinate (const SingleCoordinate&) = default;
+ explicit SingleCoordinate (uint32_t parTile);
+ SingleCoordinate (uint32_t parTile, uint32_t parOffset);
+ ~SingleCoordinate() noexcept = default;
+
+ int32_t screen_coordinate (int32_t parWorldOffset, uint32_t parTileSize) const;
+ uint32_t tile() const;
+
+ private:
+ static constexpr const auto MaxTileSize = 128U;
+ static constexpr const auto OffsetBits = implem::Log2::result;
+ static constexpr const auto OffsetMask = implem::NextPow2::result - 1;
+
+ uint32_t m_data;
+ };
+
+ inline int32_t SingleCoordinate::screen_coordinate (int32_t parWorldOffset, uint32_t parTileSize) const {
+ assert(parTileSize <= MaxTileSize);
+ return ((m_data - parWorldOffset) & OffsetMask) +
+ (static_cast(m_data - parWorldOffset) >> OffsetBits) * parTileSize;
+ }
+
+ inline uint32_t SingleCoordinate::tile() const {
+ int beyond_tile;
+ const int offset = m_data & OffsetMask;
+ asm(
+ "xorl %%eax,%%eax\n\t"
+ "subl %1,%%eax\n\t"
+ "xorl %%eax,%%eax\n\t"
+ "adcl %%eax,0\n\t"
+ "movl %%eax,%0"
+ :"=r"(beyond_tile)
+ :"r"(offset)
+ :"%eax"
+ );
+ assert(0 == beyond_tile or 1 == beyond_tile);
+ return (m_data >> OffsetBits) + beyond_tile;
+ }
+
+ SingleCoordinate::SingleCoordinate (uint32_t parTile) :
+ m_data(parTile << OffsetBits)
+ {
+ assert(this->tile() == parTile);
+ }
+
+ SingleCoordinate::SingleCoordinate (uint32_t parTile, uint32_t parOffset) :
+ m_data((parTile << OffsetBits) + (parOffset & OffsetMask))
+ {
+ assert((not parOffset and this->tile() == parTile) or (this->tile() == parTile + 1));
+ assert((m_data bitand OffsetMask) == parOffset);
+ }
+} //namespace curry