c++11: window.{h,cpp}
[Tsunagari.git] / src / window.cpp
blob7d7713d1256fe28041b77c68978f255fc97ed190
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 <Gosu/Graphics.hpp> // for Gosu::Graphics
28 #include <Gosu/Timing.hpp>
29 #include <Gosu/Utility.hpp>
31 #include "client-conf.h"
32 #include "reader.h"
33 #include "world.h"
34 #include "window.h"
36 #define ASSERT(x) if (!(x)) { return false; }
38 // Garbage collection called every X milliseconds
39 #define GC_CALL_PERIOD 10 * 1000
41 namespace Gosu {
42 /**
43 * Enable 1980s-style graphics scaling: nearest-neighbor filtering.
44 * Call this function before creating any Gosu::Image.
46 void enableUndocumentedRetrofication() {
47 extern bool undocumentedRetrofication;
48 undocumentedRetrofication = true;
52 static GameWindow* globalWindow = NULL;
54 GameWindow& GameWindow::instance()
56 return *globalWindow;
59 GameWindow::GameWindow()
60 // Gosu emulates the requested screen resolution on fullscreen,
61 // but this breaks our aspect ratio-correcting letterbox.
62 // Ergo we just make a window the size of the screen.
63 : Gosu::Window(
64 conf.fullscreen ? Gosu::screenWidth() :
65 (unsigned)conf.windowSize.x,
66 conf.fullscreen ? Gosu::screenHeight() :
67 (unsigned)conf.windowSize.y,
68 conf.fullscreen
70 now(Gosu::milliseconds()),
71 lastGCtime(0)
73 globalWindow = this;
74 Gosu::enableUndocumentedRetrofication();
77 GameWindow::~GameWindow()
81 bool GameWindow::init()
83 world.reset(new World());
84 return world->init();
87 int GameWindow::width() const
89 return (int)graphics().width();
92 int GameWindow::height() const
94 return (int)graphics().height();
97 void GameWindow::buttonDown(const Gosu::Button btn)
99 now = (int)Gosu::milliseconds();
100 if (btn == Gosu::kbEscape &&
101 (input().down(Gosu::kbLeftShift) ||
102 input().down(Gosu::kbRightShift))) {
103 exit(0);
105 else {
106 if (keystates.find(btn) == keystates.end()) {
107 keystate& state = keystates[btn];
108 state.since = now;
109 state.initiallyResolved = false;
110 state.consecutive = false;
112 // We process the initial buttonDown here so that it
113 // gets handled even if we receive a buttonUp before an
114 // update.
115 world->buttonDown(btn);
120 void GameWindow::buttonUp(const Gosu::Button btn)
122 keystates.erase(btn);
123 world->buttonUp(btn);
126 void GameWindow::draw()
128 world->draw();
131 bool GameWindow::needsRedraw() const
133 return world->needsRedraw();
136 void GameWindow::update()
138 now = Gosu::milliseconds();
140 if (conf.moveMode == TURN)
141 handleKeyboardInput(now);
142 world->update(now);
144 if (now > lastGCtime + GC_CALL_PERIOD) {
145 lastGCtime = now;
146 Reader::garbageCollect();
150 time_t GameWindow::time() const
152 return now;
155 void GameWindow::handleKeyboardInput(time_t now)
157 std::map<Gosu::Button, keystate>::iterator it;
159 // Persistent input handling code
160 for (it = keystates.begin(); it != keystates.end(); it++) {
161 Gosu::Button btn = it->first;
162 keystate& state = it->second;
164 // If there is persistCons milliseconds of latency
165 // between when a button is depressed and when we first look at
166 // it here, we'll incorrectly try to fire off a second round of
167 // input.
168 // This can happen if an intermediary function blocks the thread
169 // for a while.
170 if (!state.initiallyResolved) {
171 state.initiallyResolved = true;
172 continue;
175 time_t delay = state.consecutive ?
176 conf.persistCons : conf.persistInit;
177 if (now >= state.since + delay) {
178 state.since = now;
179 world->buttonDown(btn);
180 state.consecutive = true;