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(TargetArch)
|
||||||
include(FindPkgConfig)
|
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_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${common_gcc_flags}")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${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}")
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${common_gcc_flags}")
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
#include "gamescenebase.hpp"
|
#include "gamescenebase.hpp"
|
||||||
#include "inputbag.hpp"
|
#include "inputbag.hpp"
|
||||||
#include "sdlmain.hpp"
|
#include "sdlmain.hpp"
|
||||||
|
#include "rect_to_sdl.hpp"
|
||||||
|
#include "rect.hpp"
|
||||||
|
#include "texture.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ciso646>
|
||||||
|
|
||||||
namespace curry {
|
namespace curry {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -38,12 +43,56 @@ namespace curry {
|
||||||
}
|
}
|
||||||
return false;
|
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
|
} //unnamed namespace
|
||||||
|
|
||||||
GameSceneBase::GameSceneBase (cloonel::SDLMain* parSdlMain) :
|
GameSceneBase::GameSceneBase (cloonel::SDLMain* parSdlMain) :
|
||||||
m_time0(std::chrono::steady_clock::now()),
|
m_time0(std::chrono::steady_clock::now()),
|
||||||
m_input(std::make_unique<cloonel::InputBag>()),
|
m_input(std::make_unique<cloonel::InputBag>()),
|
||||||
m_sdlmain(parSdlMain),
|
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)
|
m_wants_to_quit(false)
|
||||||
{
|
{
|
||||||
assert(m_sdlmain);
|
assert(m_sdlmain);
|
||||||
|
@ -82,6 +131,7 @@ namespace curry {
|
||||||
const float delta = std::chrono::duration<float>(time1 - m_time0).count();
|
const float delta = std::chrono::duration<float>(time1 - m_time0).count();
|
||||||
m_time0 = time1;
|
m_time0 = time1;
|
||||||
this->on_update(delta);
|
this->on_update(delta);
|
||||||
|
SDL_RenderPresent(this->sdl_main()->GetRenderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
cloonel::SDLMain* GameSceneBase::sdl_main() {
|
cloonel::SDLMain* GameSceneBase::sdl_main() {
|
||||||
|
@ -91,4 +141,14 @@ namespace curry {
|
||||||
cloonel::InputBag& GameSceneBase::input_bag() {
|
cloonel::InputBag& GameSceneBase::input_bag() {
|
||||||
return *m_input;
|
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
|
} //namespace curry
|
||||||
|
|
|
@ -9,6 +9,9 @@ namespace cloonel {
|
||||||
} //namespace cloonel
|
} //namespace cloonel
|
||||||
|
|
||||||
namespace curry {
|
namespace curry {
|
||||||
|
class Texture;
|
||||||
|
template <typename T> class Rect;
|
||||||
|
|
||||||
class GameSceneBase {
|
class GameSceneBase {
|
||||||
public:
|
public:
|
||||||
explicit GameSceneBase (cloonel::SDLMain* parSdlMain);
|
explicit GameSceneBase (cloonel::SDLMain* parSdlMain);
|
||||||
|
@ -28,11 +31,14 @@ namespace curry {
|
||||||
virtual void on_update (float parDeltaT) = 0;
|
virtual void on_update (float parDeltaT) = 0;
|
||||||
cloonel::SDLMain* sdl_main();
|
cloonel::SDLMain* sdl_main();
|
||||||
cloonel::InputBag& input_bag();
|
cloonel::InputBag& input_bag();
|
||||||
|
void draw_clipped (Texture& parTexture, Rect<float> parSrc, Rect<float> parDest);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::chrono::time_point<std::chrono::steady_clock> m_time0;
|
std::chrono::time_point<std::chrono::steady_clock> m_time0;
|
||||||
std::unique_ptr<cloonel::InputBag> m_input;
|
std::unique_ptr<cloonel::InputBag> m_input;
|
||||||
cloonel::SDLMain* m_sdlmain;
|
cloonel::SDLMain* m_sdlmain;
|
||||||
|
float m_screen_width;
|
||||||
|
float m_screen_height;
|
||||||
bool m_wants_to_quit;
|
bool m_wants_to_quit;
|
||||||
};
|
};
|
||||||
} //namespace curry
|
} //namespace curry
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "worldgrid.hpp"
|
#include "worldgrid.hpp"
|
||||||
#include "worldviewport.hpp"
|
#include "worldviewport.hpp"
|
||||||
#include "texture.hpp"
|
#include "texture.hpp"
|
||||||
|
#include "rect.hpp"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -18,22 +19,12 @@ namespace curry {
|
||||||
ActionRight,
|
ActionRight,
|
||||||
ActionDown
|
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
|
} //unnamed namespace
|
||||||
|
|
||||||
struct IngameScene::LocalData {
|
struct IngameScene::LocalData {
|
||||||
LocalData (const vec2us& parTileSize, const vec2us& parTileCount, cloonel::SDLMain* parSDLMain) :
|
LocalData (const vec2us& parTileSize, const vec2us& parTileCount, cloonel::SDLMain* parSDLMain) :
|
||||||
world(parTileSize, parTileCount),
|
world(parTileSize, parTileCount),
|
||||||
viewport(&world, vec2i(parSDLMain->WidthHeight())),
|
viewport(&world, vec2f(parSDLMain->WidthHeight())),
|
||||||
player(parTileSize)
|
player(parTileSize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -82,18 +73,17 @@ namespace curry {
|
||||||
if (cloonel::IsPressed(input_bag(), ActionDown))
|
if (cloonel::IsPressed(input_bag(), ActionDown))
|
||||||
viewport.set_position(viewport.position() + vec2f(0, speed));
|
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) {
|
for (auto tile : viewport) {
|
||||||
vec2us idx(tile.index & 1, (tile.index >> 1) & 1);
|
vec2f idx(static_cast<float>(tile.index & 1), static_cast<float>((tile.index >> 1) & 1));
|
||||||
vec2us src_rect_xy = idx * tilesize;
|
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';
|
//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()};
|
Rect<float> src_rect(src_rect_xy, src_rect_xy + tilesize);
|
||||||
SDL_Rect dst{tile.pixel_pos.x(), tile.pixel_pos.y(), tilesize.x(), tilesize.y()};
|
Rect<float> dst_rect(pixel_pos, pixel_pos + tilesize);
|
||||||
clip(src, dst, vec2i(0), sdl_main()->WidthHeight());
|
this->draw_clipped(m_local_data->worldtiles, src_rect, dst_rect);
|
||||||
SDL_RenderCopy(this->sdl_main()->GetRenderer(), m_local_data->worldtiles.texture(), &src, &dst);
|
|
||||||
}
|
}
|
||||||
SDL_RenderPresent(this->sdl_main()->GetRenderer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IngameScene::on_destroy() noexcept {
|
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>
|
#include <cassert>
|
||||||
|
|
||||||
namespace curry {
|
namespace curry {
|
||||||
WorldViewport::WorldViewport (WorldGrid* parWorld, vec2i parSize) :
|
WorldViewport::WorldViewport (WorldGrid* parWorld, vec2f parSize) :
|
||||||
m_position(0),
|
m_position(0),
|
||||||
m_size(parSize),
|
m_size(parSize),
|
||||||
m_world(parWorld)
|
m_world(parWorld)
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace curry {
|
||||||
public:
|
public:
|
||||||
typedef TileIterator iterator;
|
typedef TileIterator iterator;
|
||||||
|
|
||||||
WorldViewport (WorldGrid* parWorld, vec2i parSize);
|
WorldViewport (WorldGrid* parWorld, vec2f parSize);
|
||||||
const WorldGrid* world() const;
|
const WorldGrid* world() const;
|
||||||
const vec2f& position() const;
|
const vec2f& position() const;
|
||||||
const vec2f& size() const;
|
const vec2f& size() const;
|
||||||
|
|
Loading…
Reference in a new issue