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