Move clipping and drawing to base class and fix int<->float warnings.
This commit is contained in:
parent
c8920ea997
commit
5da4cef4a5
8 changed files with 159 additions and 22 deletions
|
@ -6,7 +6,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/include")
|
|||
include(TargetArch)
|
||||
include(FindPkgConfig)
|
||||
|
||||
set(common_gcc_flags "-Wall -Wextra -pedantic")
|
||||
set(common_gcc_flags "-Wall -Wextra -pedantic -Wconversion")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${common_gcc_flags}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${common_gcc_flags}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${common_gcc_flags}")
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#include "gamescenebase.hpp"
|
||||
#include "inputbag.hpp"
|
||||
#include "sdlmain.hpp"
|
||||
#include "rect_to_sdl.hpp"
|
||||
#include "rect.hpp"
|
||||
#include "texture.hpp"
|
||||
#include <cassert>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <algorithm>
|
||||
#include <ciso646>
|
||||
|
||||
namespace curry {
|
||||
namespace {
|
||||
|
@ -38,12 +43,56 @@ namespace curry {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------
|
||||
///Adjustes parSrc and parDest so that parDest will fit into parClip and
|
||||
///parSrc to be the relevant part of the source texture to be drawn.
|
||||
///Returns true if such operation was possible and parSrc and parDest
|
||||
///got set to a valid value, otherwise false.
|
||||
///----------------------------------------------------------------------
|
||||
bool clip_rect (Rect<float>& parSrc, Rect<float>& parDest, const Rect<float>& parClip) {
|
||||
typedef Rect<float> RectFloat;
|
||||
assert(parSrc.is_valid());
|
||||
assert(parDest.is_valid());
|
||||
|
||||
//If the dest rect is completely out of the clipping region, there
|
||||
//is nothing to do at all.
|
||||
if (parDest.to <= parClip.from or parDest.from >= parClip.to)
|
||||
return false;
|
||||
|
||||
{
|
||||
const RectFloat clip(vec2f(0.0f), vec2f(1.0f));
|
||||
const vec2f srcWidthHeight(parSrc.width_height());
|
||||
const vec2f scaledOffs((parDest.from - parClip.from) / parClip.width_height());
|
||||
parSrc.from -= vec2f(std::min(0.0f, scaledOffs.x() * srcWidthHeight.x()), std::min(0.0f, scaledOffs.y() * srcWidthHeight.y()));
|
||||
const vec2f scaledCrop((parClip.to - parDest.to) / parClip.width_height());
|
||||
parSrc.to += vec2f(std::min(0.0f, scaledCrop.x() * srcWidthHeight.x()), std::min(0.0f, scaledCrop.y() * srcWidthHeight.y()));
|
||||
assert(parSrc.is_valid());
|
||||
}
|
||||
|
||||
RectFloat dst(parDest.from - parClip.from, parDest.to - parClip.from);
|
||||
dst.from.x() = std::max(dst.from.x(), parClip.from.x());
|
||||
dst.from.y() = std::max(dst.from.y(), parClip.from.y());
|
||||
dst.to.x() = std::min(dst.to.x(), parClip.to.x());
|
||||
dst.to.y() = std::min(dst.to.y(), parClip.to.y());
|
||||
|
||||
if (not dst.is_valid())
|
||||
return false;
|
||||
|
||||
parDest.from += parClip.from;
|
||||
parDest.to += parClip.from;
|
||||
|
||||
assert(parDest.is_valid());
|
||||
return true;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
GameSceneBase::GameSceneBase (cloonel::SDLMain* parSdlMain) :
|
||||
m_time0(std::chrono::steady_clock::now()),
|
||||
m_input(std::make_unique<cloonel::InputBag>()),
|
||||
m_sdlmain(parSdlMain),
|
||||
m_screen_width(static_cast<float>(m_sdlmain->WidthHeight().x())),
|
||||
m_screen_height(static_cast<float>(m_sdlmain->WidthHeight().y())),
|
||||
m_wants_to_quit(false)
|
||||
{
|
||||
assert(m_sdlmain);
|
||||
|
@ -82,6 +131,7 @@ namespace curry {
|
|||
const float delta = std::chrono::duration<float>(time1 - m_time0).count();
|
||||
m_time0 = time1;
|
||||
this->on_update(delta);
|
||||
SDL_RenderPresent(this->sdl_main()->GetRenderer());
|
||||
}
|
||||
|
||||
cloonel::SDLMain* GameSceneBase::sdl_main() {
|
||||
|
@ -91,4 +141,14 @@ namespace curry {
|
|||
cloonel::InputBag& GameSceneBase::input_bag() {
|
||||
return *m_input;
|
||||
}
|
||||
|
||||
void GameSceneBase::draw_clipped (Texture& parTexture, Rect<float> parSrc, Rect<float> parDest) {
|
||||
const vec2f lefttop(0.0f);
|
||||
const vec2f rightbottom(m_screen_width, m_screen_height);
|
||||
clip_rect(parSrc, parDest, Rect<float>(lefttop, rightbottom));
|
||||
|
||||
auto src = make_sdlrect(parSrc);
|
||||
auto dst = make_sdlrect(parDest);
|
||||
SDL_RenderCopy(m_sdlmain->GetRenderer(), parTexture.texture(), &src, &dst);
|
||||
}
|
||||
} //namespace curry
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace cloonel {
|
|||
} //namespace cloonel
|
||||
|
||||
namespace curry {
|
||||
class Texture;
|
||||
template <typename T> class Rect;
|
||||
|
||||
class GameSceneBase {
|
||||
public:
|
||||
explicit GameSceneBase (cloonel::SDLMain* parSdlMain);
|
||||
|
@ -28,11 +31,14 @@ namespace curry {
|
|||
virtual void on_update (float parDeltaT) = 0;
|
||||
cloonel::SDLMain* sdl_main();
|
||||
cloonel::InputBag& input_bag();
|
||||
void draw_clipped (Texture& parTexture, Rect<float> parSrc, Rect<float> parDest);
|
||||
|
||||
private:
|
||||
std::chrono::time_point<std::chrono::steady_clock> m_time0;
|
||||
std::unique_ptr<cloonel::InputBag> m_input;
|
||||
cloonel::SDLMain* m_sdlmain;
|
||||
float m_screen_width;
|
||||
float m_screen_height;
|
||||
bool m_wants_to_quit;
|
||||
};
|
||||
} //namespace curry
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "worldgrid.hpp"
|
||||
#include "worldviewport.hpp"
|
||||
#include "texture.hpp"
|
||||
#include "rect.hpp"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -18,22 +19,12 @@ namespace curry {
|
|||
ActionRight,
|
||||
ActionDown
|
||||
};
|
||||
|
||||
void clip (SDL_Rect& parSource, SDL_Rect& parDest, const vec2i& parTopLeft, const vec2i& parBotRight) {
|
||||
if (parDest.x < parTopLeft.x()) {
|
||||
const auto diff = parTopLeft.x() - parDest.x;
|
||||
parDest.x = parTopLeft.x();
|
||||
parDest.w -= diff;
|
||||
parSource.x += diff;
|
||||
parSource.w -= diff;
|
||||
}
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
struct IngameScene::LocalData {
|
||||
LocalData (const vec2us& parTileSize, const vec2us& parTileCount, cloonel::SDLMain* parSDLMain) :
|
||||
world(parTileSize, parTileCount),
|
||||
viewport(&world, vec2i(parSDLMain->WidthHeight())),
|
||||
viewport(&world, vec2f(parSDLMain->WidthHeight())),
|
||||
player(parTileSize)
|
||||
{
|
||||
}
|
||||
|
@ -82,18 +73,17 @@ namespace curry {
|
|||
if (cloonel::IsPressed(input_bag(), ActionDown))
|
||||
viewport.set_position(viewport.position() + vec2f(0, speed));
|
||||
|
||||
const auto tilesize(world.tile_size());
|
||||
const auto tilesize(static_cast<vec2f>(world.tile_size()));
|
||||
for (auto tile : viewport) {
|
||||
vec2us idx(tile.index & 1, (tile.index >> 1) & 1);
|
||||
vec2us src_rect_xy = idx * tilesize;
|
||||
vec2f idx(static_cast<float>(tile.index & 1), static_cast<float>((tile.index >> 1) & 1));
|
||||
vec2f src_rect_xy = idx * tilesize;
|
||||
vec2f pixel_pos = vector_cast<vec2f>(tile.pixel_pos);
|
||||
|
||||
//std::cout << "Drawing src " << src_rect_xy << " dst " << tile.pixel_pos << '\n';
|
||||
SDL_Rect src{src_rect_xy.x(), src_rect_xy.y(), tilesize.x(), tilesize.y()};
|
||||
SDL_Rect dst{tile.pixel_pos.x(), tile.pixel_pos.y(), tilesize.x(), tilesize.y()};
|
||||
clip(src, dst, vec2i(0), sdl_main()->WidthHeight());
|
||||
SDL_RenderCopy(this->sdl_main()->GetRenderer(), m_local_data->worldtiles.texture(), &src, &dst);
|
||||
Rect<float> src_rect(src_rect_xy, src_rect_xy + tilesize);
|
||||
Rect<float> dst_rect(pixel_pos, pixel_pos + tilesize);
|
||||
this->draw_clipped(m_local_data->worldtiles, src_rect, dst_rect);
|
||||
}
|
||||
SDL_RenderPresent(this->sdl_main()->GetRenderer());
|
||||
}
|
||||
|
||||
void IngameScene::on_destroy() noexcept {
|
||||
|
|
62
src/rect.hpp
Normal file
62
src/rect.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
#include "vector.hpp"
|
||||
#if !defined(NDEBUG)
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
namespace curry {
|
||||
template <typename T>
|
||||
class Rect {
|
||||
public:
|
||||
typedef vwr::Vec<std::array<T, 2>> VecType;
|
||||
|
||||
Rect (T parLeft, T parTop, T parRight, T parBottom);
|
||||
template <typename V1, typename V2>
|
||||
Rect (const vwr::Vec<V1>& parLeftTop, const vwr::Vec<V2>& parBottomRight);
|
||||
|
||||
T left() const { return from.x(); }
|
||||
T top() const { return from.y(); }
|
||||
T right() const { return to.x(); }
|
||||
T bottom() const { return to.y(); }
|
||||
T& left() { return from.x(); }
|
||||
T& top() { return from.y(); }
|
||||
T& right() { return to.x(); }
|
||||
T& bottom() { return to.y(); }
|
||||
T width() const { return right() - left(); }
|
||||
T height() const { return bottom() - top(); }
|
||||
VecType width_height() const { return VecType(width(), height()); }
|
||||
|
||||
bool is_valid() const;
|
||||
|
||||
VecType from;
|
||||
VecType to;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Rect<T>::Rect (T parLeft, T parTop, T parRight, T parBottom) :
|
||||
from(parLeft, parTop),
|
||||
to(parRight, parBottom)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename V1, typename V2>
|
||||
Rect<T>::Rect (const vwr::Vec<V1>& parLeftTop, const vwr::Vec<V2>& parBottomRight) :
|
||||
Rect(parLeftTop.x(), parLeftTop.y(), parBottomRight.x(), parBottomRight.y())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool Rect<T>::is_valid() const {
|
||||
return from <= to;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
template <typename T>
|
||||
std::ostream& operator<< (std::ostream& parStream, const Rect<T>& parRect) {
|
||||
parStream << '{' << parRect.from << '-' << parRect.to << '}';
|
||||
return parStream;
|
||||
}
|
||||
#endif
|
||||
} //namespace curry
|
19
src/rect_to_sdl.hpp
Normal file
19
src/rect_to_sdl.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "rect.hpp"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <utility>
|
||||
|
||||
namespace curry {
|
||||
template <typename T>
|
||||
inline SDL_Rect make_sdlrect (const Rect<T>& parOther) {
|
||||
typedef decltype(std::declval<SDL_Rect>().w) ValueType;
|
||||
|
||||
return SDL_Rect{
|
||||
static_cast<ValueType>(parOther.left()),
|
||||
static_cast<ValueType>(parOther.top()),
|
||||
static_cast<ValueType>(parOther.width()),
|
||||
static_cast<ValueType>(parOther.height())
|
||||
};
|
||||
}
|
||||
} //namespace curry
|
|
@ -3,7 +3,7 @@
|
|||
#include <cassert>
|
||||
|
||||
namespace curry {
|
||||
WorldViewport::WorldViewport (WorldGrid* parWorld, vec2i parSize) :
|
||||
WorldViewport::WorldViewport (WorldGrid* parWorld, vec2f parSize) :
|
||||
m_position(0),
|
||||
m_size(parSize),
|
||||
m_world(parWorld)
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace curry {
|
|||
public:
|
||||
typedef TileIterator iterator;
|
||||
|
||||
WorldViewport (WorldGrid* parWorld, vec2i parSize);
|
||||
WorldViewport (WorldGrid* parWorld, vec2f parSize);
|
||||
const WorldGrid* world() const;
|
||||
const vec2f& position() const;
|
||||
const vec2f& size() const;
|
||||
|
|
Loading…
Reference in a new issue