rm boost/{format,foreach}; reduce #includes; small fixes
[Tsunagari.git] / src / window.cpp
blobfb52b8b5d87e928ef56980ca736328da49b07c86
1 /***************************************
2 ** Tsunagari Tile Engine **
3 ** window.cpp **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
7 // **********
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // **********
27 #include <boost/foreach.hpp>
28 #include <Gosu/Graphics.hpp> // for Gosu::Graphics
29 #include <Gosu/Timing.hpp>
30 #include <Gosu/Utility.hpp>
32 #include "client-conf.h"
33 #include "reader.h"
34 #include "world.h"
35 #include "window.h"
37 #define ASSERT(x) if (!(x)) { return false; }
39 // Garbage collection called every X milliseconds
40 #define GC_CALL_PERIOD 10 * 1000
42 namespace Gosu {
43 /**
44 * Enable 1980s-style graphics scaling: nearest-neighbor filtering.
45 * Call this function before creating any Gosu::Image.
47 void enableUndocumentedRetrofication() {
48 extern bool undocumentedRetrofication;
49 undocumentedRetrofication = true;
53 static GameWindow* globalWindow = NULL;
55 GameWindow& GameWindow::instance()
57 return *globalWindow;
60 GameWindow::GameWindow()
61 // Gosu emulates the requested screen resolution on fullscreen,
62 // but this breaks our aspect ratio-correcting letterbox.
63 // Ergo we just make a window the size of the screen.
64 : Gosu::Window(
65 conf.fullscreen ? Gosu::screenWidth() :
66 (unsigned)conf.windowSize.x,
67 conf.fullscreen ? Gosu::screenHeight() :
68 (unsigned)conf.windowSize.y,
69 conf.fullscreen
71 now(Gosu::milliseconds()),
72 lastGCtime(0)
74 globalWindow = this;
75 Gosu::enableUndocumentedRetrofication();
78 GameWindow::~GameWindow()
82 bool GameWindow::init()
84 world.reset(new World());
85 return world->init();
88 int GameWindow::width() const
90 return (int)graphics().width();
93 int GameWindow::height() const
95 return (int)graphics().height();
98 void GameWindow::buttonDown(const Gosu::Button btn)
100 now = (int)Gosu::milliseconds();
101 if (btn == Gosu::kbEscape &&
102 (input().down(Gosu::kbLeftShift) ||
103 input().down(Gosu::kbRightShift))) {
104 exit(0);
106 else {
107 if (keystates.find(btn) == keystates.end()) {
108 keystate& state = keystates[btn];
109 state.since = now;
110 state.initiallyResolved = false;
111 state.consecutive = false;
113 // We process the initial buttonDown here so that it
114 // gets handled even if we receive a buttonUp before an
115 // update.
116 world->buttonDown(btn);
121 void GameWindow::buttonUp(const Gosu::Button btn)
123 keystates.erase(btn);
124 world->buttonUp(btn);
127 void GameWindow::draw()
129 world->draw();
132 bool GameWindow::needsRedraw() const
134 return world->needsRedraw();
137 void GameWindow::update()
139 now = Gosu::milliseconds();
141 if (conf.moveMode == TURN)
142 handleKeyboardInput(now);
143 world->update(now);
145 if (now > lastGCtime + GC_CALL_PERIOD) {
146 lastGCtime = now;
147 Reader::garbageCollect();
151 time_t GameWindow::time() const
153 return now;
156 void GameWindow::handleKeyboardInput(time_t now)
158 std::map<Gosu::Button, keystate>::iterator it;
160 // Persistent input handling code
161 for (it = keystates.begin(); it != keystates.end(); it++) {
162 Gosu::Button btn = it->first;
163 keystate& state = it->second;
165 // If there is persistCons milliseconds of latency
166 // between when a button is depressed and when we first look at
167 // it here, we'll incorrectly try to fire off a second round of
168 // input.
169 // This can happen if an intermediary function blocks the thread
170 // for a while.
171 if (!state.initiallyResolved) {
172 state.initiallyResolved = true;
173 continue;
176 time_t delay = state.consecutive ?
177 conf.persistCons : conf.persistInit;
178 if (now >= state.since + delay) {
179 state.since = now;
180 world->buttonDown(btn);
181 state.consecutive = true;