diff options
Diffstat (limited to 'source/rendering/StarWorldCamera.hpp')
-rw-r--r-- | source/rendering/StarWorldCamera.hpp | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/source/rendering/StarWorldCamera.hpp b/source/rendering/StarWorldCamera.hpp new file mode 100644 index 0000000..fe1dbeb --- /dev/null +++ b/source/rendering/StarWorldCamera.hpp @@ -0,0 +1,117 @@ +#ifndef STAR_WORLD_CAMERA_HPP +#define STAR_WORLD_CAMERA_HPP + +#include "StarWorldGeometry.hpp" +#include "StarGameTypes.hpp" + +namespace Star { + +class WorldCamera { +public: + void setScreenSize(Vec2U screenSize); + Vec2U screenSize() const; + + void setPixelRatio(unsigned pixelRatio); + unsigned pixelRatio() const; + + void setWorldGeometry(WorldGeometry geometry); + WorldGeometry worldGeometry() const; + + // Set the camera center position (in world space) to as close to the given + // location as possible while keeping the screen within world bounds. + // Returns the actual camera position. + void setCenterWorldPosition(Vec2F const& position); + Vec2F centerWorldPosition() const; + + // Transforms world coordinates into one set of screen coordinates. Since + // the world is non-euclidean, one world coordinate can transform to + // potentially an infinite number of screen coordinates. This will retrun + // the closest to the center of the screen. + Vec2F worldToScreen(Vec2F const& worldCoord) const; + + // Assumes top left corner of screen is (0, 0) in screen coordinates. + Vec2F screenToWorld(Vec2F const& screen) const; + + // Returns screen dimensions in world space. + RectF worldScreenRect() const; + + // Returns tile dimensions of the tiles that overlap with the screen + RectI worldTileRect() const; + + // Returns the position of the lower left corner of the lower left tile of + // worldTileRect, in screen coordinates. + Vec2F tileMinScreen() const; + +private: + WorldGeometry m_worldGeometry; + Vec2U m_screenSize; + unsigned m_pixelRatio = 1; + Vec2F m_worldCenter; +}; + +inline void WorldCamera::setScreenSize(Vec2U screenSize) { + m_screenSize = screenSize; +} + +inline Vec2U WorldCamera::screenSize() const { + return m_screenSize; +} + +inline void WorldCamera::setPixelRatio(unsigned pixelRatio) { + m_pixelRatio = pixelRatio; +} + +inline unsigned WorldCamera::pixelRatio() const { + return m_pixelRatio; +} + +inline void WorldCamera::setWorldGeometry(WorldGeometry geometry) { + m_worldGeometry = move(geometry); +} + +inline WorldGeometry WorldCamera::worldGeometry() const { + return m_worldGeometry; +} + +inline Vec2F WorldCamera::centerWorldPosition() const { + return Vec2F(m_worldCenter); +} + +inline Vec2F WorldCamera::worldToScreen(Vec2F const& worldCoord) const { + Vec2F wrappedCoord = m_worldGeometry.nearestTo(Vec2F(m_worldCenter), worldCoord); + return Vec2F( + (wrappedCoord[0] - m_worldCenter[0]) * (TilePixels * m_pixelRatio) + m_screenSize[0] / 2.0, + (wrappedCoord[1] - m_worldCenter[1]) * (TilePixels * m_pixelRatio) + m_screenSize[1] / 2.0 + ); +} + +inline Vec2F WorldCamera::screenToWorld(Vec2F const& screen) const { + return Vec2F( + (screen[0] - m_screenSize[0] / 2.0) / (TilePixels * m_pixelRatio) + m_worldCenter[0], + (screen[1] - m_screenSize[1] / 2.0) / (TilePixels * m_pixelRatio) + m_worldCenter[1] + ); +} + +inline RectF WorldCamera::worldScreenRect() const { + // screen dimensions in world space + float w = (float)m_screenSize[0] / (TilePixels * m_pixelRatio); + float h = (float)m_screenSize[1] / (TilePixels * m_pixelRatio); + return RectF::withSize(Vec2F(m_worldCenter[0] - w / 2, m_worldCenter[1] - h / 2), Vec2F(w, h)); +} + +inline RectI WorldCamera::worldTileRect() const { + RectF screen = worldScreenRect(); + Vec2I min = Vec2I::floor(screen.min()); + Vec2I size = Vec2I::ceil(Vec2F(m_screenSize) / (TilePixels * m_pixelRatio) + (screen.min() - Vec2F(min))); + return RectI::withSize(min, size); +} + +inline Vec2F WorldCamera::tileMinScreen() const { + RectF screenRect = worldScreenRect(); + RectI tileRect = worldTileRect(); + return (Vec2F(tileRect.min()) - screenRect.min()) * (TilePixels * m_pixelRatio); +} + +} + +#endif |