1 #pragma once 2 3 /** Main game file, mainly contains various setup functions. 4 */ 5 6 namespace Gigalomania { 7 class Screen; 8 class Image; 9 class PanelPage; 10 class Sample; 11 } 12 13 using namespace Gigalomania; 14 15 using std::vector; 16 using std::stringstream; 17 using std::string; 18 19 class Invention; 20 class Weapon; 21 class Element; 22 class Sector; 23 class GameState; 24 class PlayingGameState; 25 class Player; 26 class Application; 27 class TextEffect; 28 class Map; 29 class Tutorial; 30 31 #include "common.h" 32 #include "image.h" 33 #include "TinyXML/tinyxml.h" 34 35 enum GameStateID { 36 GAMESTATEID_UNDEFINED = -1, 37 GAMESTATEID_CHOOSEGAMETYPE = 0, 38 GAMESTATEID_CHOOSEDIFFICULTY, 39 GAMESTATEID_CHOOSEPLAYER, 40 GAMESTATEID_CHOOSETUTORIAL, 41 GAMESTATEID_PLACEMEN, 42 GAMESTATEID_PLAYING, 43 GAMESTATEID_ENDISLAND, 44 GAMESTATEID_GAMECOMPLETE 45 }; 46 47 enum GameResult { 48 GAMERESULT_UNDEFINED = 0, 49 GAMERESULT_WON, 50 GAMERESULT_QUIT, 51 GAMERESULT_LOST 52 }; 53 54 enum DifficultyLevel { 55 // don't change the numbers, as will break saved state and saved game compatibility! 56 DIFFICULTY_EASY = 0, 57 DIFFICULTY_MEDIUM = 1, 58 DIFFICULTY_HARD = 2, 59 DIFFICULTY_ULTRA = 3, 60 DIFFICULTY_N_LEVELS = 4 61 }; 62 63 enum GameMode { 64 GAMEMODE_SINGLEPLAYER = 0, 65 GAMEMODE_MULTIPLAYER_SERVER = 1, 66 GAMEMODE_MULTIPLAYER_CLIENT = 2 67 }; 68 69 enum GameType { 70 // don't change the numbers, as will break saved state compatibility! 71 GAMETYPE_SINGLEISLAND = 0, 72 GAMETYPE_ALLISLANDS = 1, 73 GAMETYPE_TUTORIAL = 2 74 }; 75 76 const int default_width_c = 320; 77 const int default_height_c = 240; 78 79 const int infinity_c = 31; 80 //const int end_epoch_c = 9; // use this to have the last epoch game 81 const int end_epoch_c = -1; // use this to have the last epoch as being 2100AD 82 const int cannon_epoch_c = 5; 83 const int biplane_epoch_c = 6; 84 const int jetplane_epoch_c = 7; 85 const int nuclear_epoch_c = 8; 86 const int spaceship_epoch_c = 9; 87 const int laser_epoch_c = 9; 88 const int n_shields_c = 4; 89 const int n_playershields_c = 16; 90 const int n_flag_frames_c = 4; 91 const int max_defender_frames_c = 11; 92 const int n_attacker_directions_c = 4; 93 const int max_attacker_frames_c = 9; 94 const int n_trees_c = 4; 95 const int n_tree_frames_c = 4; 96 const int n_nuke_frames_c = 2; 97 const int n_saucer_frames_c = 4; 98 const int n_death_flashes_c = 3; 99 const int n_blue_flashes_c = 7; 100 const int n_explosions_c = 59; 101 const int n_coast_c = 8; 102 const int n_map_sq_c = 16; 103 const int max_islands_per_epoch_c = 3; 104 105 class Game { 106 float scale_factor_w; // how much the input graphics are scaled 107 float scale_factor_h; 108 float scale_width; // the scale of the logical resolution or graphics size wrt the default 320x240 coordinate system 109 float scale_height; 110 bool onemousebutton; 111 bool mobile_ui; 112 bool using_old_gfx; 113 bool is_testing; 114 115 Application *application; 116 Screen *screen; 117 bool paused; 118 GameState *gamestate; 119 GameState *dispose_gamestate; 120 unsigned int lastmousepress_time; 121 122 int frame_counter; 123 int time_rate; // time factor 124 int real_time; 125 int real_loop_time; 126 int game_time; 127 int loop_time; 128 float accumulated_time; 129 int mouseTime; 130 131 bool pref_sound_on; 132 bool pref_music_on; 133 bool pref_disallow_nukes; 134 135 GameMode gameMode; 136 GameType gameType; 137 DifficultyLevel difficulty_level; 138 int human_player; 139 Tutorial *tutorial; 140 141 GameStateID gameStateID; 142 bool state_changed; 143 GameResult gameResult; 144 145 int start_epoch; 146 int n_sub_epochs; 147 int selected_island; 148 bool completed_island[max_islands_per_epoch_c]; 149 Map *maps[n_epochs_c][max_islands_per_epoch_c]; 150 Map *map; 151 int n_men_store; 152 int n_player_suspended; 153 154 void calculateScale(const Image *image); 155 void convertToHiColor(Image *image) const; 156 void processImage(Image *image, bool old_smooth = true) const; 157 bool loadAttackersWalkingImages(const string &gfx_dir, int epoch); 158 bool loadOldImages(); 159 void getDesktopResolution(int *user_width, int *user_height) const; 160 161 const char *getFilename(int slot) const; 162 bool readMapProcessLine(int *epoch, int *index, Map **l_map, char *line, const int MAX_LINE, const char *filename); 163 bool readMap(const char *filename); 164 bool loadGameInfo(DifficultyLevel *difficulty, int *player, int *n_men, int suspended[n_players_c], int *epoch, bool completed[max_islands_per_epoch_c], const char *filename) const; 165 bool loadGame(const char *filename); 166 GameState *loadStateParseXMLNode(const TiXmlNode *parent); 167 void copyFile(const char *src, const char *dst) const; 168 169 bool testFindSoldiersBuildingNewTower(const Sector *sector, int *total, int *squares) const; 170 171 void disposeGameState(); 172 173 int getMenPerEpoch() const; 174 void updatedEpoch(); 175 void setEpoch(int epoch); 176 void cleanupPlayers(); 177 public: 178 Image *background; 179 Image *player_heads_select[n_players_c]; 180 Image *player_heads_alliance[n_players_c]; 181 Image *grave; 182 Image *land[MAP_N_COLOURS]; 183 Image *fortress[n_epochs_c]; 184 Image *mine[n_epochs_c]; 185 Image *factory[n_epochs_c]; 186 Image *lab[n_epochs_c]; 187 Image *men[n_epochs_c]; 188 Image *unarmed_man; 189 Image *flags[n_players_c][n_flag_frames_c]; 190 Image *panel_design; 191 Image *panel_lab; 192 Image *panel_factory; 193 Image *panel_shield; 194 Image *panel_defence; 195 Image *panel_attack; 196 Image *panel_bloody_attack; 197 Image *panel_twoattack; 198 Image *panel_build[N_BUILDINGS]; 199 Image *panel_building[N_BUILDINGS]; 200 Image *panel_knowndesigns; 201 Image *panel_bigdesign; 202 Image *panel_biglab; 203 Image *panel_bigfactory; 204 Image *panel_bigshield; 205 Image *panel_bigdefence; 206 Image *panel_bigattack; 207 Image *panel_bigbuild; 208 Image *panel_bigknowndesigns; 209 Image *numbers_blue[10]; 210 Image *numbers_grey[10]; 211 Image *numbers_white[10]; 212 Image *numbers_orange[10]; 213 Image *numbers_yellow[10]; 214 Image *numbers_largegrey[10]; 215 Image *numbers_largeshiny[10]; 216 Image *numbers_small[n_players_c][10]; 217 Image *numbers_half; 218 Image *letters_large[n_font_chars_c]; 219 Image *letters_small[n_font_chars_c]; 220 Image *mouse_pointers[n_players_c]; 221 Image *playershields[n_playershields_c]; 222 Image *building_health; 223 Image *dash_grey; 224 Image *icon_shield; 225 Image *icon_defence; 226 Image *icon_weapon; 227 Image *icon_shields[n_shields_c]; 228 Image *icon_defences[n_epochs_c]; 229 Image *icon_weapons[n_epochs_c]; 230 Image *numbered_defences[n_epochs_c]; 231 Image *numbered_weapons[n_epochs_c]; 232 Image *icon_elements[N_ID]; 233 Image *icon_clocks[13]; 234 Image *icon_infinity; 235 Image *icon_bc; 236 Image *icon_ad; 237 Image *icon_ad_shiny; 238 Image *icon_towers[n_players_c]; 239 Image *icon_armies[n_players_c]; 240 Image *icon_nuke_hole; 241 Image *mine_gatherable_small; 242 Image *mine_gatherable_large; 243 Image *icon_ergo; 244 Image *icon_trash; 245 Image *coast_icons[n_coast_c]; 246 int map_sq_offset, map_sq_coast_offset; 247 Image *map_sq[MAP_N_COLOURS][n_map_sq_c]; 248 int n_defender_frames[n_epochs_c]; 249 Image *defenders[n_players_c][n_epochs_c][max_defender_frames_c]; 250 Image *nuke_defences[n_players_c]; 251 int n_attacker_frames[n_epochs_c+1][n_attacker_directions_c]; 252 Image *attackers_walking[n_players_c][n_epochs_c+1][n_attacker_directions_c][max_attacker_frames_c]; // epochs 6-9 are special case! 253 Image *planes[n_players_c][n_epochs_c]; 254 Image *nukes[n_players_c][n_nuke_frames_c]; 255 Image *saucers[n_players_c][n_saucer_frames_c]; 256 Image *attackers_ammo[n_epochs_c][N_ATTACKER_AMMO_DIRS]; 257 Image *icon_openpitmine; 258 Image *icon_trees[n_trees_c][n_tree_frames_c]; 259 vector<Image *> icon_clutter; 260 vector<Image *> icon_clutter_nuked; 261 Image *flashingmapsquare; 262 Image *mapsquare; 263 Image *arrow_left; 264 Image *arrow_right; 265 Image *death_flashes[n_death_flashes_c]; 266 Image *blue_flashes[n_blue_flashes_c]; 267 Image *explosions[n_explosions_c]; 268 Image *icon_mice[2]; 269 Image *icon_speeds[3]; 270 Image *smoke_image; 271 Image *background_islands; 272 273 // speech 274 Sample *s_design_is_ready; 275 Sample *s_ergo; 276 Sample *s_advanced_tech; 277 Sample *s_fcompleted; 278 Sample *s_on_hold; 279 Sample *s_running_out_of_elements; 280 Sample *s_tower_critical; 281 Sample *s_sector_destroyed; 282 Sample *s_mine_destroyed; 283 Sample *s_factory_destroyed; 284 Sample *s_lab_destroyed; 285 Sample *s_itis_all_over; 286 Sample *s_conquered; 287 Sample *s_won; 288 Sample *s_weve_nuked_them; 289 Sample *s_weve_been_nuked; 290 Sample *s_alliance_yes[n_players_c]; 291 Sample *s_alliance_no[n_players_c]; 292 Sample *s_alliance_ask[n_players_c]; 293 Sample *s_quit[n_players_c]; 294 Sample *s_cant_nuke_ally; 295 296 // effects 297 Sample *s_explosion; 298 Sample *s_scream; 299 Sample *s_buildingdestroyed; 300 Sample *s_guiclick; 301 Sample *s_biplane; 302 Sample *s_jetplane; 303 Sample *s_spaceship; 304 305 Sample *music; 306 307 Invention *invention_shields[n_epochs_c]; 308 Invention *invention_defences[n_epochs_c]; 309 Weapon *invention_weapons[n_epochs_c]; 310 Element *elements[N_ID]; 311 Player *players[n_players_c]; 312 313 Game(); 314 ~Game(); 315 316 bool loadImages(); 317 bool loadSamples(); 318 bool createMaps(); 319 getScaleWidth()320 float getScaleWidth() const { 321 return this->scale_width; 322 } getScaleHeight()323 float getScaleHeight() const { 324 return this->scale_height; 325 } setOneMouseButton(bool onemousebutton)326 void setOneMouseButton(bool onemousebutton) { 327 this->onemousebutton = onemousebutton; 328 } isOneMouseButton()329 bool isOneMouseButton() const { 330 return this->onemousebutton; 331 } 332 bool oneMouseButtonMode() const; setMobileUI(bool mobile_ui)333 void setMobileUI(bool mobile_ui) { 334 this->mobile_ui = mobile_ui; 335 } isMobileUI()336 bool isMobileUI() const { 337 return this->mobile_ui; 338 } isUsingOldGfx()339 bool isUsingOldGfx() const { 340 return this->using_old_gfx; 341 } setTesting(bool is_testing)342 void setTesting(bool is_testing) { 343 this->is_testing = is_testing; 344 } isTesting()345 bool isTesting() const { 346 return this->is_testing; 347 } 348 349 bool createApplication(); getApplication()350 Application *getApplication() { 351 return this->application; 352 } getApplication()353 const Application *getApplication() const { 354 return this->application; 355 } 356 bool openScreen(bool fullscreen); getScreen()357 Screen *getScreen() { 358 return this->screen; 359 } getScreen()360 const Screen *getScreen() const { 361 return this->screen; 362 } 363 bool isPaused() const; 364 cycleTimeRate()365 void cycleTimeRate() { 366 time_rate++; 367 if( time_rate > 3 ) 368 time_rate = 1; 369 } increaseTimeRate()370 void increaseTimeRate() { 371 if( time_rate > 1 ) 372 time_rate--; 373 } decreaseTimeRate()374 void decreaseTimeRate() { 375 if( time_rate < 3 ) 376 time_rate++; 377 } 378 void setTimeRate(int time_rate); getTimeRate()379 int getTimeRate() const { 380 return this->time_rate; 381 } 382 void setRealTime(int real_time); 383 int getRealTime() const; 384 int getRealLoopTime() const; 385 void setGameTime(int game_time); 386 int getGameTime() const; 387 int getLoopTime() const; getFrameCounter()388 int getFrameCounter() const { 389 return this->frame_counter; 390 } 391 void updateTime(int time); 392 void resetMouseClick(); 393 int getNClicks(); 394 setGameMode(GameMode gameMode)395 void setGameMode(GameMode gameMode) { 396 this->gameMode = gameMode; 397 } getGameMode()398 GameMode getGameMode() const { 399 return this->gameMode; 400 } setGameType(GameType gameType)401 void setGameType(GameType gameType) { 402 this->gameType = gameType; 403 } getGameType()404 GameType getGameType() const { 405 return this->gameType; 406 } setDifficultyLevel(DifficultyLevel difficulty_level)407 void setDifficultyLevel(DifficultyLevel difficulty_level) { 408 this->difficulty_level = difficulty_level; 409 } getDifficultyLevel()410 DifficultyLevel getDifficultyLevel() const { 411 return this->difficulty_level; 412 } 413 void setGameStateID(GameStateID state, GameState *new_gamestate = NULL); getGameStateID()414 GameStateID getGameStateID() const { 415 return this->gameStateID; 416 } setStateChanged(bool state_changed)417 void setStateChanged(bool state_changed) { 418 this->state_changed = state_changed; 419 } isStateChanged()420 bool isStateChanged() const { 421 return this->state_changed; 422 } setGameResult(GameResult gameResult)423 void setGameResult(GameResult gameResult) { 424 this->gameResult = gameResult; 425 } getGameResult()426 GameResult getGameResult() const { 427 return this->gameResult; 428 } 429 void setupTutorial(const string &id); getTutorial()430 const Tutorial *getTutorial() const { 431 return this->tutorial; 432 } getTutorial()433 Tutorial *getTutorial() { 434 return this->tutorial; 435 } setCurrentMap()436 void setCurrentMap() { 437 map = maps[start_epoch][selected_island]; 438 } 439 void setCurrentIsand(int start_epoch, int selected_island); 440 const Map *getMap() const; 441 Map *getMap(); getMap(int i,int j)442 const Map *getMap(int i, int j) const { 443 return this->maps[i][j]; 444 } getStartEpoch()445 int getStartEpoch() const { 446 return this->start_epoch; 447 } getNSubEpochs()448 int getNSubEpochs() const { 449 return this->n_sub_epochs; 450 } setPrefSoundOn(bool pref_sound_on)451 void setPrefSoundOn(bool pref_sound_on) { 452 this->pref_sound_on = pref_sound_on; 453 } isPrefSoundOn()454 bool isPrefSoundOn() const { 455 return this->pref_sound_on; 456 } setPrefMusicOn(bool pref_music_on)457 void setPrefMusicOn(bool pref_music_on) { 458 this->pref_music_on = pref_music_on; 459 } isPrefMusicOn()460 bool isPrefMusicOn() const { 461 return this->pref_music_on; 462 } setPrefDisallowNukes(bool pref_disallow_nukes)463 void setPrefDisallowNukes(bool pref_disallow_nukes) { 464 this->pref_disallow_nukes = pref_disallow_nukes; 465 } isPrefDisallowNukes()466 bool isPrefDisallowNukes() const { 467 return this->pref_disallow_nukes; 468 } 469 getMapSqOffset()470 int getMapSqOffset() const { 471 return map_sq_offset; 472 } getMapSqCoastOffset()473 int getMapSqCoastOffset() const { 474 return map_sq_coast_offset; 475 } 476 void loadPrefs(); 477 void savePrefs() const; 478 bool isDemo() const; 479 480 void deleteState() const; 481 void saveState() const; 482 bool loadState(); 483 484 int getMenAvailable() const; 485 int getNSuspended() const; 486 void nextEpoch(); 487 void nextIsland(); 488 void startIsland(); 489 void endIsland(); 490 void returnToChooseIsland(); 491 void startNewGame(); 492 void placeTower(); 493 void newGame(); 494 void setClientPlayer(int set_client_player); 495 bool validPlayer(int player) const; 496 void requestQuit(bool force_quit); 497 void keypressReturn(); 498 void togglePause(); 499 void activate(); 500 void deactivate(); 501 void mouseClick(int m_x, int m_y, bool m_left, bool m_middle, bool m_right, bool click); 502 void updateGame(); 503 void drawGame() const; 504 void addTextEffect(TextEffect *effect); 505 void drawProgress(int percentage) const; 506 507 bool readLineFromRWOps(bool &ok, SDL_RWops *file, char *buffer, char *line, int MAX_LINE, int &buffer_offset, int &newline_index, bool &reached_end); 508 bool loadGameInfo(DifficultyLevel *difficulty, int *player, int *n_men, int suspended[n_players_c], int *epoch, bool completed[max_islands_per_epoch_c], int slot); 509 bool loadGame(int slot); 510 void saveGame(int slot) const; 511 512 void stopMusic(); 513 void fadeMusic(int duration_ms) const; 514 void playMusic(); 515 516 void setupPlayers(); 517 void setupInventions(); 518 void setupElements(); 519 bool playerAlive(int player) const; 520 521 void runTests(); 522 }; 523 524 extern Game *game_g; 525 526 void startIsland_g(); 527 void endIsland_g(); 528 void returnToChooseIsland_g(); 529 void startNewGame_g(); 530 531 extern const char *maps_dirname; 532 #if !defined(__ANDROID__) && defined(__DragonFly__) 533 extern const char *alt_maps_dirname; 534 #endif 535 536 extern const int epoch_dates[]; 537 extern const char *epoch_names[]; 538 539 enum PlayerMode { 540 PLAYER_DEMO = -2, 541 PLAYER_NONE = -1 542 }; 543 544 class Map { 545 string name; 546 string filename; 547 MapColour colour; 548 int n_opponents; 549 Sector *sectors[map_width_c][map_height_c]; 550 bool sector_at[map_width_c][map_height_c]; 551 bool reserved[map_width_c][map_height_c]; // if true, don't use for starting players - used for testing 552 553 public: 554 555 Map(MapColour colour,int n_opponents,const char *name); 556 ~Map(); 557 getColour()558 MapColour getColour() const { 559 return this->colour; 560 } getNOpponents()561 int getNOpponents() const { 562 return this->n_opponents; 563 } 564 const Sector *getSector(int x, int y) const; 565 Sector *getSector(int x, int y); 566 bool isSectorAt(int x, int y) const; 567 568 void newSquareAt(int x,int y); 569 void createSectors(PlayingGameState *gamestate, int epoch); 570 #if 0 571 void checkSectors() const; 572 #endif 573 void freeSectors(); getName()574 const char *getName() const { 575 return name.c_str(); 576 } getFilename()577 const char *getFilename() const { 578 return filename.c_str(); 579 } setFilename(const char * filename)580 void setFilename(const char *filename) { 581 this->filename = filename; 582 } 583 int getNSquares() const; 584 void draw(int offset_x, int offset_y) const; 585 void findRandomSector(int *rx,int *ry) const; isReserved(int x,int y)586 bool isReserved(int x, int y) const { 587 return this->reserved[x][y]; 588 } setReserved(int x,int y,bool r)589 void setReserved(int x, int y, bool r) { 590 this->reserved[x][y] = r; 591 } 592 void canMoveTo(bool temp[map_width_c][map_height_c], int sx,int sy,int player) const; 593 void calculateStats() const; 594 595 void saveStateSectors(stringstream &stream) const; 596 }; 597 598 void playGame(int n_args, char *args[]); 599 600 #if defined(__ANDROID__) 601 602 // JNI for Android 603 604 void launchUrl(string url); 605 606 #endif 607 608 // game constants 609 610 const int SHORT_DELAY = 4000; 611 const int nuke_delay_c = 250; 612 613 const int gameticks_per_hour_c = 200; 614 const int hours_per_day_c = 12; 615 616 const int mine_epoch_c = 3; 617 const int factory_epoch_c = 4; 618 const int lab_epoch_c = 5; 619 //const int air_epoch_c = 6; 620 621 const int DESIGNTIME_M3 = 20; 622 const int DESIGNTIME_M2 = 30; 623 const int DESIGNTIME_M1 = 40; 624 const int DESIGNTIME_0 = 50; 625 const int DESIGNTIME_1 = 100; 626 const int DESIGNTIME_2 = 200; 627 const int DESIGNTIME_3 = 400; 628 629 const int MANUFACTURETIME_0 = 15; 630 const int MANUFACTURETIME_1 = 30; 631 const int MANUFACTURETIME_2 = 45; 632 const int MANUFACTURETIME_3 = 60; 633 634 const int BUILDTIME_TOWER = 80; 635 const int BUILDTIME_MINE = 40; 636 const int BUILDTIME_FACTORY = 40; 637 const int BUILDTIME_LAB = 40; 638 639 const int ticks_per_frame_c = 100; // game time ticks per frame rate (used for various animated sprites) 640 const float time_ratio_c = 0.15f; // game time ticks per time ticks 641