remove +x from source
[Tsunagari.git] / src / viewport.cpp
blob31722ff2e64ea0375e6f61efadb553f8d4a5699d
1 /*********************************
2 ** Tsunagari Tile Engine **
3 ** viewport.cpp **
4 ** Copyright 2011-2012 OmegaSDG **
5 *********************************/
7 #include <Gosu/Graphics.hpp> // for Gosu::screenWidth/Height()
8 #include <Gosu/Math.hpp>
10 #include "area.h"
11 #include "vec.h"
12 #include "viewport.h"
13 #include "window.h"
16 Viewport::Viewport(icoord vsize)
17 : off(0, 0),
18 virtRes(vsize.x, vsize.y),
19 mode(TM_MANUAL),
20 area(NULL)
22 double width = (double)Gosu::screenWidth();
23 double height = (double)Gosu::screenHeight();
24 aspectRatio = width / height;
27 Viewport::~Viewport()
32 void Viewport::tick(unsigned long)
34 update();
37 void Viewport::turn()
39 update();
42 rvec2 Viewport::getMapOffset() const
44 return off;
47 rvec2 Viewport::getLetterboxOffset() const
49 return addLetterboxOffset(rvec2(0.0, 0.0));
52 rvec2 Viewport::getScale() const
54 const GameWindow& window = GameWindow::instance();
55 rvec2 letterbox = getLetterbox();
56 rvec2 physRes = rvec2(
57 (double)window.width(),
58 (double)window.height()
61 return rvec2(
62 physRes.x / virtRes.x * (1 - letterbox.x),
63 physRes.y / virtRes.y * (1 - letterbox.y)
67 rvec2 Viewport::getPhysRes() const
69 const GameWindow& window = GameWindow::instance();
70 return rvec2(
71 (double)window.width(),
72 (double)window.height()
76 rvec2 Viewport::getVirtRes() const
78 return virtRes;
81 // Immediatly center render offset. Stop any tracking.
82 void Viewport::jumpToPt(ivec2 pt)
84 jumpToPt(rvec2((double)pt.x, (double)pt.y));
87 void Viewport::jumpToPt(rvec2 pt)
89 mode = TM_MANUAL;
90 off = offsetForPt(pt);
93 void Viewport::jumpToEntity(const Entity* e)
95 mode = TM_MANUAL; // API implies mode change.
96 _jumpToEntity(e);
100 // Continuously follow.
101 void Viewport::trackEntity(const Entity* e)
103 mode = TM_FOLLOW_ENTITY;
104 targete = e;
108 void Viewport::setArea(const Area* a)
110 area = a;
114 void Viewport::update()
116 switch (mode) {
117 case TM_MANUAL:
118 // Do nothing.
119 break;
120 case TM_FOLLOW_ENTITY:
121 _jumpToEntity(targete);
122 break;
126 void Viewport::_jumpToEntity(const Entity* e)
128 rcoord pos = e->getPixelCoord();
129 ivec2 td = area->getTileDimensions();
130 rvec2 center = rvec2(
131 pos.x + td.x/2,
132 pos.y + td.y/2
134 off = offsetForPt(center);
138 rvec2 Viewport::getLetterbox() const
140 rvec2 physRes = getPhysRes();
141 double physAspect = physRes.x / physRes.y;
142 double virtAspect = virtRes.x / virtRes.y;
144 if (physAspect > virtAspect) {
145 // Letterbox cuts off left-right.
146 double cut = 1 - virtAspect / physAspect;
147 return rvec2(cut, 0);
149 else {
150 // Letterbox cuts off top-bottom.
151 double cut = 1 - physAspect / virtAspect;
152 return rvec2(0, cut);
156 rvec2 Viewport::offsetForPt(rvec2 pt) const
158 return boundToArea(centerOn(pt));
161 rvec2 Viewport::centerOn(rvec2 pt) const
163 return pt - virtRes / 2;
166 rvec2 Viewport::boundToArea(rvec2 pt) const
168 icoord ad = area->getDimensions();
169 ivec2 td = area->getTileDimensions();
170 double areaWidth = ad.x * td.x;
171 double areaHeight = ad.y * td.y;
172 bool loopX = area->loopsInX();
173 bool loopY = area->loopsInY();
175 return rvec2(
176 boundDimension(virtRes.x, areaWidth, pt.x, loopX),
177 boundDimension(virtRes.y, areaHeight, pt.y, loopY)
181 double Viewport::boundDimension(double screen, double area, double pt,
182 bool loop) const
184 // Since looping areas continue without bound, this is a no-op.
185 if (loop)
186 return pt;
188 // If the Area is smaller than the screen, center the Area. Otherwise,
189 // allow the screen to move to the edge of the Area, but not past.
190 double wiggleRoom = area - screen;
191 return wiggleRoom <= 0 ?
192 wiggleRoom/2 :
193 Gosu::boundBy(pt, 0.0, wiggleRoom);
196 rvec2 Viewport::addLetterboxOffset(rvec2 pt) const
198 rvec2 physRes = getPhysRes();
199 rvec2 letterbox = getLetterbox();
200 return pt - letterbox * physRes / 2;