MyCurry/src/gamelib/tileiterator.cpp

108 lines
3.2 KiB
C++

/*
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 <http://www.gnu.org/licenses/>.
*/
#include "tileiterator.hpp"
#include "worldviewport.hpp"
#include "worldgrid.hpp"
#include "compatibility.h"
#include <cassert>
#include <ciso646>
namespace curry {
namespace {
const uint16_t g_invalid_index = 0xFFFF;
vec2i first_col_starting_pixel (const vec2i& parViewportPos, const vec2i& parTileSize) a_pure;
vec2i first_col_starting_pixel (const vec2i& parViewportPos, const vec2i& parTileSize) {
const auto& pos = parViewportPos;
const auto& ts = parTileSize;
return vec2i(
(pos.x() > 0 ? -pos.x() % ts.x() : -pos.x()),
(pos.y() > 0 ? -pos.y() % ts.y() : -pos.y())
);
}
} //unnamed namespace
TileIterator::TileIterator (WorldViewport* parViewport, bool parEnd) :
m_viewport(parViewport),
m_index(parEnd ? g_invalid_index : 0)
{
assert(m_viewport);
m_pixel_pos = first_col_starting_pixel(
vector_cast<vec2i>(m_viewport->position()),
m_viewport->world()->tile_size()
);
}
void TileIterator::increment() {
assert(m_index != vec2i(g_invalid_index));
const WorldGrid& world = *m_viewport->world();
vec2i tile_size(world.tile_size());
auto first_tile_pos = first_col_starting_pixel(
vector_cast<vec2i>(m_viewport->position()),
m_viewport->world()->tile_size()
);
vec2i pos(tile_size * vector_cast<vec2i>(m_index) + first_tile_pos);
assert(pos.x() > -tile_size.x() and pos.x() < m_viewport->size().x());
assert(pos.y() > -tile_size.y() and pos.y() < m_viewport->size().y());
const float right_border = std::min(
m_viewport->size().x(),
static_cast<float>(world_size_pixel(world).x()) - m_viewport->position().x()
);
const float bottom_border = std::min(
m_viewport->size().y(),
static_cast<float>(world_size_pixel(world).y()) - m_viewport->position().y()
);
if (static_cast<float>(pos.x() + tile_size.x()) < right_border) {
++m_index.x();
}
else if (static_cast<float>(pos.y() + tile_size.y()) < bottom_border) {
m_index.x() = 0;
++m_index.y();
m_pixel_pos.x() = first_tile_pos.x();
m_pixel_pos.y() += tile_size.y();
}
else {
m_index = vec2us(g_invalid_index);
}
//std::cout << "got index " << m_index << " pixel " <<
//m_index * tile_size - m_viewport->position() << '\n';
m_pixel_pos = tile_size * vector_cast<vec2i>(m_index) + first_tile_pos;
}
ScreenTile TileIterator::dereference() const {
auto index = vector_cast<vec2us>(m_index);
return ScreenTile {
m_viewport->tile(index),
m_pixel_pos
};
}
bool TileIterator::equal (const TileIterator& parOther) const {
return m_viewport == parOther.m_viewport and
m_index == parOther.m_index
;
}
} //namespace curry