1 /*
2 Copyright (C) 2005 Matthias Braun <matze@braunis.de>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 #include <config.h>
19
20 #include "Game.hpp"
21
22 #include "gui/TextureManager.hpp"
23 #include "gui/ComponentLoader.hpp"
24 #include "gui/Component.hpp"
25 #include "gui/Desktop.hpp"
26 #include "gui/Event.hpp"
27 #include "gui/Button.hpp"
28 #include "gui/callback/Callback.hpp"
29 #include "lincity/fileutil.h"
30
31 #include "MainLincity.hpp"
32 #include <iostream>
33 #include <physfs.h>
34 #include "Util.hpp"
35 #include "lincity/lin-city.h"
36 #include "GameView.hpp"
37 #include "HelpWindow.hpp"
38 #include "ButtonPanel.hpp"
39 #include "Dialog.hpp"
40 #include "EconomyGraph.hpp"
41
42 extern int lincitySpeed;
43
44 Game* gameptr = 0;
45
getGame()46 Game* getGame(){
47 return gameptr;
48 }
49
Game()50 Game::Game()
51 {
52 gui.reset(loadGUIFile("gui/app.xml"));
53 gui->resize(SDL_GetVideoSurface()->w, SDL_GetVideoSurface()->h);
54
55 Button* gameMenu = getButton( *gui, "GameMenuButton" );
56 gameMenu->clicked.connect( makeCallback(*this, &Game::gameButtonClicked ));
57
58 Button* helpButton = getButton( *gui, "HelpButton" );
59 helpButton->clicked.connect( makeCallback(*this, &Game::gameButtonClicked ));
60
61 Button* statButton = getButton( *gui, "StatButton" );
62 statButton->clicked.connect( makeCallback(*this, &Game::gameButtonClicked ));
63
64 Desktop* desktop = dynamic_cast<Desktop*> (gui.get());
65 if(desktop == 0)
66 throw std::runtime_error("Game UI is not a Desktop Component");
67 helpWindow.reset(new HelpWindow(desktop));
68 gameptr = this;
69 }
70
~Game()71 Game::~Game()
72 {
73 if( gameptr == this ){
74 gameptr = 0;
75 }
76 }
77
showHelpWindow(std::string topic)78 void Game::showHelpWindow( std::string topic ){
79 helpWindow->showTopic( topic );
80 }
81
backToMainMenu()82 void Game::backToMainMenu(){
83 closeAllDialogs();
84 getButtonPanel()->selectQueryTool();
85 saveCityNG( "9_currentGameNG.scn" );
86 running = false;
87 quitState = MAINMENU;
88 }
89
gameButtonClicked(Button * button)90 void Game::gameButtonClicked( Button* button ){
91 std::string name = button->getName();
92 if( name == "GameMenuButton" ) {
93 backToMainMenu();
94 } else if( name == "HelpButton" ) {
95 helpWindow->showTopic("help");
96 } else if( name == "StatButton" ) {
97 if( !blockingDialogIsOpen ){
98 new Dialog( GAME_STATS );
99 }
100 } else {
101 std::cerr << " Game::gameButtonClicked unknown button '" << name << "'.\n";
102 }
103 }
104
quickLoad()105 void Game::quickLoad(){
106 closeAllDialogs();
107
108 //load file
109 getGameView()->printStatusMessage( "quick load...");
110 std::string filename;
111 filename.append( "quicksave.scn" );
112 if( loadCityNG( filename ) ){
113 getGameView()->printStatusMessage( "quick load successful.");
114 } else {
115 getGameView()->printStatusMessage( "quick load failed!");
116 }
117 }
118
quickSave()119 void Game::quickSave(){
120 //save file
121 getGameView()->printStatusMessage( "quick save...");
122 saveCityNG( "quicksave.scn" );
123 }
124
testAllHelpFiles()125 void Game::testAllHelpFiles(){
126 getGameView()->printStatusMessage( "Testing Help Files...");
127
128 std::string filename;
129 std::string directory = "help/en";
130 std::string fullname;
131 char **rc = PHYSFS_enumerateFiles( directory.c_str() );
132 char **i;
133 size_t pos;
134 for (i = rc; *i != NULL; i++) {
135 fullname = directory;
136 fullname.append( *i );
137 filename.assign( *i );
138
139 if(PHYSFS_isDirectory(fullname.c_str()))
140 continue;
141
142 pos = filename.rfind( ".xml" );
143 if( pos != std::string::npos ){
144 filename.replace( pos, 4 ,"");
145 std::cerr << "--- Examining " << filename << "\n";
146 helpWindow->showTopic( filename );
147 std::cerr << "\n";
148 }
149 }
150 PHYSFS_freeList(rc);
151 }
152
153 MainState
run()154 Game::run()
155 {
156 SDL_Event event;
157 running = true;
158 Uint32 fpsTicks = SDL_GetTicks();
159 Uint32 lastticks = fpsTicks;
160 Desktop* desktop = dynamic_cast<Desktop*> (gui.get());
161 if(!desktop)
162 throw std::runtime_error("Toplevel component is not a Desktop");
163
164 int frame = 0;
165 while(running) {
166 getGameView()->scroll();
167 while(SDL_PollEvent(&event)) {
168 switch(event.type) {
169 case SDL_VIDEORESIZE:
170 initVideo(event.resize.w, event.resize.h);
171 gui->resize(event.resize.w, event.resize.h);
172 break;
173 case SDL_KEYUP: {
174 Event gui_event(event);
175 if( gui_event.keysym.sym == SDLK_ESCAPE ){
176 getButtonPanel()->selectQueryTool();
177 break;
178 }
179 if( gui_event.keysym.sym == SDLK_b ){
180 getButtonPanel()->toggleBulldozeTool();
181 break;
182 }
183 if( gui_event.keysym.sym == SDLK_F1 ){
184 helpWindow->showTopic("help");
185 break;
186 }
187 if( gui_event.keysym.sym == SDLK_F12 ){
188 quickSave();
189 break;
190 }
191 if( gui_event.keysym.sym == SDLK_F9 ){
192 quickLoad();
193 break;
194 }
195 #ifdef DEBUG
196 if( gui_event.keysym.sym == SDLK_F5 ){
197 testAllHelpFiles();
198 break;
199 }
200 #endif
201 gui->event(gui_event);
202 break;
203 }
204 case SDL_MOUSEMOTION:
205 case SDL_MOUSEBUTTONUP:
206 case SDL_MOUSEBUTTONDOWN:
207 case SDL_KEYDOWN: {
208 Event gui_event(event);
209 gui->event(gui_event);
210 break;
211 }
212 case SDL_ACTIVEEVENT:
213 if( event.active.gain == 1 ){
214 gui->resize( gui->getWidth(), gui->getHeight() );
215 }
216 break;
217 case SDL_VIDEOEXPOSE:
218 gui->resize( gui->getWidth(), gui->getHeight() );
219 break;
220 case SDL_QUIT:
221 saveCityNG( "9_currentGameNG.scn" );
222 running = false;
223 quitState = QUIT;
224 break;
225 default:
226 break;
227 }
228 }
229
230 // create update Event
231 Uint32 ticks = SDL_GetTicks();
232 float elapsedTime = ((float) (ticks - lastticks)) / 1000.0;
233 gui->event(Event(elapsedTime));
234 lastticks = ticks;
235
236 helpWindow->update();
237 if(desktop->needsRedraw()) {
238 desktop->draw(*painter);
239 flipScreenBuffer();
240 }
241 frame++;
242
243 // Slow down cpu consumption in pause mode
244 if(ticks - fpsTicks > 1000 && lincitySpeed) {
245 #ifdef DEBUG_FPS
246 printf("FPS: %d.\n", (frame*1000) / (ticks - fpsTicks));
247 #endif
248 getEconomyGraph()->newFPS( frame );
249 frame = 0;
250 fpsTicks = ticks;
251 } else if(!lincitySpeed)
252 frame = 0;
253 /* SDL_Delay is done in execute_timestep , which is called by doLincityStep */
254 doLincityStep();
255 }
256
257 return quitState;
258 }
259