Codebase list gigalomania / a1ee6300-6dce-4084-a2dc-9c389b875749/main game.h
a1ee6300-6dce-4084-a2dc-9c389b875749/main

Tree @a1ee6300-6dce-4084-a2dc-9c389b875749/main (Download .tar.gz)

game.h @a1ee6300-6dce-4084-a2dc-9c389b875749/mainraw · history · blame

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
#pragma once

/** Main game file, mainly contains various setup functions.
*/

namespace Gigalomania {
	class Screen;
	class Image;
	class PanelPage;
	class Sample;
}

using Gigalomania::Sample;

using std::vector;
using std::stringstream;
using std::string;

class Invention;
class Weapon;
class Element;
class Sector;
class GameState;
class PlayingGameState;
class Player;
class Application;
class TextEffect;
class Map;
class Tutorial;

#include "common.h"
#include "image.h"
#include "TinyXML/tinyxml.h"

enum GameStateID {
	GAMESTATEID_UNDEFINED = -1,
	GAMESTATEID_CHOOSEGAMETYPE = 0,
	GAMESTATEID_CHOOSEDIFFICULTY,
	GAMESTATEID_CHOOSEPLAYER,
	GAMESTATEID_CHOOSETUTORIAL,
	GAMESTATEID_PLACEMEN,
	GAMESTATEID_PLAYING,
	GAMESTATEID_ENDISLAND,
	GAMESTATEID_GAMECOMPLETE
};

enum GameResult {
	GAMERESULT_UNDEFINED = 0,
	GAMERESULT_WON,
	GAMERESULT_QUIT,
	GAMERESULT_LOST
};

enum DifficultyLevel {
	// don't change the numbers, as will break saved state and saved game compatibility!
	DIFFICULTY_EASY = 0,
	DIFFICULTY_MEDIUM = 1,
	DIFFICULTY_HARD = 2,
	DIFFICULTY_ULTRA = 3,
	DIFFICULTY_N_LEVELS = 4
};

enum GameMode {
	GAMEMODE_SINGLEPLAYER = 0,
	GAMEMODE_MULTIPLAYER_SERVER = 1,
	GAMEMODE_MULTIPLAYER_CLIENT = 2
};

enum GameType {
	// don't change the numbers, as will break saved state compatibility!
	GAMETYPE_SINGLEISLAND = 0,
	GAMETYPE_ALLISLANDS = 1,
	GAMETYPE_TUTORIAL = 2
};

const int default_width_c = 320;
const int default_height_c = 240;

const int infinity_c = 31;
//const int end_epoch_c = 9; // use this to have the last epoch game
const int end_epoch_c = -1; // use this to have the last epoch as being 2100AD
const int cannon_epoch_c = 5;
const int biplane_epoch_c = 6;
const int jetplane_epoch_c = 7;
const int nuclear_epoch_c = 8;
const int spaceship_epoch_c = 9;
const int laser_epoch_c = 9;
const int n_shields_c = 4;
const int n_playershields_c = 16;
const int n_flag_frames_c = 4;
const int max_defender_frames_c = 11;
const int n_attacker_directions_c = 4;
const int max_attacker_frames_c = 9;
const int n_trees_c = 4;
const int n_tree_frames_c = 4;
const int n_nuke_frames_c = 2;
const int n_saucer_frames_c = 4;
const int n_death_flashes_c = 3;
const int n_blue_flashes_c = 7;
const int n_explosions_c = 59;
const int n_coast_c = 8;
const int n_map_sq_c = 16;
const int max_islands_per_epoch_c = 3;

class Game {
	float scale_factor_w; // how much the input graphics are scaled
	float scale_factor_h;
	float scale_width; // the scale of the logical resolution or graphics size wrt the default 320x240 coordinate system
	float scale_height;
	bool onemousebutton;
	bool mobile_ui;
	bool using_old_gfx;
	bool is_testing;

	Application *application;
	Gigalomania::Screen *screen;
	bool paused;
	GameState *gamestate;
	GameState *dispose_gamestate;
	unsigned int lastmousepress_time;

	int frame_counter;
	int time_rate; // time factor
	int real_time;
	int real_loop_time;
	int game_time;
	int loop_time;
	float accumulated_time;
	int mouseTime;

	bool pref_sound_on;
	bool pref_music_on;
	bool pref_disallow_nukes;

	GameMode gameMode;
	GameType gameType;
	DifficultyLevel difficulty_level;
	int human_player;
	Tutorial *tutorial;

	GameStateID gameStateID;
	bool state_changed;
	GameResult gameResult;

	int start_epoch;
	int n_sub_epochs;
	int selected_island;
	bool completed_island[max_islands_per_epoch_c];
	Map *maps[n_epochs_c][max_islands_per_epoch_c];
	Map *map;
	int n_men_store;
	int n_player_suspended;

	void calculateScale(const Gigalomania::Image *image);
	void convertToHiColor(Gigalomania::Image *image) const;
	void processImage(Gigalomania::Image *image, bool old_smooth = true) const;
	bool loadAttackersWalkingImages(const string &gfx_dir, int epoch);
	bool loadOldImages();
	void getDesktopResolution(int *user_width, int *user_height) const;

	const char *getFilename(int slot) const;
	bool readMapProcessLine(int *epoch, int *index, Map **l_map, char *line, const int MAX_LINE, const char *filename);
	bool readMap(const char *filename);
	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;
	bool loadGame(const char *filename);
	GameState *loadStateParseXMLNode(const TiXmlNode *parent);
	void copyFile(const char *src, const char *dst) const;

	bool testFindSoldiersBuildingNewTower(const Sector *sector, int *total, int *squares) const;

	void disposeGameState();

	int getMenPerEpoch() const;
	void updatedEpoch();
	void setEpoch(int epoch);
	void cleanupPlayers();
public:
	Gigalomania::Image *background;
	Gigalomania::Image *background_stars;
	Gigalomania::Image *player_heads_select[n_players_c];
	Gigalomania::Image *player_heads_alliance[n_players_c];
	Gigalomania::Image *grave;
	Gigalomania::Image *land[MAP_N_COLOURS];
	Gigalomania::Image *fortress[n_epochs_c];
	Gigalomania::Image *mine[n_epochs_c];
	Gigalomania::Image *factory[n_epochs_c];
	Gigalomania::Image *lab[n_epochs_c];
	Gigalomania::Image *men[n_epochs_c];
	Gigalomania::Image *unarmed_man;
	Gigalomania::Image *flags[n_players_c][n_flag_frames_c];
	Gigalomania::Image *panel_design;
	Gigalomania::Image *panel_lab;
	Gigalomania::Image *panel_factory;
	Gigalomania::Image *panel_shield;
	Gigalomania::Image *panel_defence;
	Gigalomania::Image *panel_attack;
	Gigalomania::Image *panel_bloody_attack;
	Gigalomania::Image *panel_twoattack;
	Gigalomania::Image *panel_build[N_BUILDINGS];
	Gigalomania::Image *panel_building[N_BUILDINGS];
	Gigalomania::Image *panel_knowndesigns;
	Gigalomania::Image *panel_bigdesign;
	Gigalomania::Image *panel_biglab;
	Gigalomania::Image *panel_bigfactory;
	Gigalomania::Image *panel_bigshield;
	Gigalomania::Image *panel_bigdefence;
	Gigalomania::Image *panel_bigattack;
	Gigalomania::Image *panel_bigbuild;
	Gigalomania::Image *panel_bigknowndesigns;
	Gigalomania::Image *numbers_blue[10];
	Gigalomania::Image *numbers_grey[10];
	Gigalomania::Image *numbers_white[10];
	Gigalomania::Image *numbers_orange[10];
	Gigalomania::Image *numbers_yellow[10];
	Gigalomania::Image *numbers_largegrey[10];
	Gigalomania::Image *numbers_largeshiny[10];
	Gigalomania::Image *numbers_small[n_players_c][10];
	Gigalomania::Image *numbers_half;
	Gigalomania::Image *letters_large[n_font_chars_c];
	Gigalomania::Image *letters_small[n_font_chars_c];
	Gigalomania::Image *mouse_pointers[n_players_c];
	Gigalomania::Image *playershields[n_playershields_c];
	Gigalomania::Image *building_health;
	Gigalomania::Image *dash_grey;
	Gigalomania::Image *icon_shield;
	Gigalomania::Image *icon_defence;
	Gigalomania::Image *icon_weapon;
	Gigalomania::Image *icon_shields[n_shields_c];
	Gigalomania::Image *icon_defences[n_epochs_c];
	Gigalomania::Image *icon_weapons[n_epochs_c];
	Gigalomania::Image *numbered_defences[n_epochs_c];
	Gigalomania::Image *numbered_weapons[n_epochs_c];
	Gigalomania::Image *icon_elements[N_ID];
	Gigalomania::Image *icon_clocks[13];
	Gigalomania::Image *icon_infinity;
	Gigalomania::Image *icon_bc;
	Gigalomania::Image *icon_ad;
	Gigalomania::Image *icon_ad_shiny;
	Gigalomania::Image *icon_towers[n_players_c];
	Gigalomania::Image *icon_armies[n_players_c];
	Gigalomania::Image *icon_nuke_hole;
	Gigalomania::Image *mine_gatherable_small;
	Gigalomania::Image *mine_gatherable_large;
	Gigalomania::Image *icon_ergo;
	Gigalomania::Image *icon_trash;
	Gigalomania::Image *coast_icons[n_coast_c];
	int map_sq_offset, map_sq_coast_offset;
	Gigalomania::Image *map_sq[MAP_N_COLOURS][n_map_sq_c];
	int n_defender_frames[n_epochs_c];
	Gigalomania::Image *defenders[n_players_c][n_epochs_c][max_defender_frames_c];
	Gigalomania::Image *nuke_defences[n_players_c];
	int n_attacker_frames[n_epochs_c+1][n_attacker_directions_c];
	Gigalomania::Image *attackers_walking[n_players_c][n_epochs_c+1][n_attacker_directions_c][max_attacker_frames_c]; // epochs 6-9 are special case!
	Gigalomania::Image *planes[n_players_c][n_epochs_c];
	Gigalomania::Image *nukes[n_players_c][n_nuke_frames_c];
	Gigalomania::Image *saucers[n_players_c][n_saucer_frames_c];
	Gigalomania::Image *attackers_ammo[n_epochs_c][N_ATTACKER_AMMO_DIRS];
	Gigalomania::Image *icon_openpitmine;
	Gigalomania::Image *icon_trees[n_trees_c][n_tree_frames_c];
	vector<Gigalomania::Image *> icon_clutter;
	vector<Gigalomania::Image *> icon_clutter_nuked;
	Gigalomania::Image *flashingmapsquare;
	Gigalomania::Image *mapsquare;
	Gigalomania::Image *arrow_left;
	Gigalomania::Image *arrow_right;
	Gigalomania::Image *death_flashes[n_death_flashes_c];
	Gigalomania::Image *blue_flashes[n_blue_flashes_c];
	Gigalomania::Image *explosions[n_explosions_c];
	Gigalomania::Image *icon_mice[2];
	Gigalomania::Image *icon_speeds[3];
	Gigalomania::Image *smoke_image;
	Gigalomania::Image *background_islands;

	// speech
	Sample *s_design_is_ready;
	Sample *s_ergo;
	Sample *s_advanced_tech;
	Sample *s_fcompleted;
	Sample *s_on_hold;
	Sample *s_running_out_of_elements;
	Sample *s_tower_critical;
	Sample *s_sector_destroyed;
	Sample *s_mine_destroyed;
	Sample *s_factory_destroyed;
	Sample *s_lab_destroyed;
	Sample *s_itis_all_over;
	Sample *s_conquered;
	Sample *s_won;
	Sample *s_weve_nuked_them;
	Sample *s_weve_been_nuked;
	Sample *s_alliance_yes[n_players_c];
	Sample *s_alliance_no[n_players_c];
	Sample *s_alliance_ask[n_players_c];
	Sample *s_quit[n_players_c];
	Sample *s_cant_nuke_ally;

	// effects
	Sample *s_explosion;
	Sample *s_scream;
	Sample *s_buildingdestroyed;
	Sample *s_guiclick;
	Sample *s_biplane;
	Sample *s_jetplane;
	Sample *s_spaceship;

	Sample *music;

	Invention *invention_shields[n_epochs_c];
	Invention *invention_defences[n_epochs_c];
	Weapon *invention_weapons[n_epochs_c];
	Element *elements[N_ID];
	Player *players[n_players_c];

	Game();
	~Game();

	bool loadImages();
	bool loadSamples();
	bool createMaps();

	float getScaleWidth() const {
		return this->scale_width;
	}
	float getScaleHeight() const {
		return this->scale_height;
	}
	void setOneMouseButton(bool onemousebutton) {
		this->onemousebutton = onemousebutton;
	}
	bool isOneMouseButton() const {
		return this->onemousebutton;
	}
	bool oneMouseButtonMode() const;
	void setMobileUI(bool mobile_ui) {
		this->mobile_ui = mobile_ui;
	}
	bool isMobileUI() const {
		return this->mobile_ui;
	}
	bool isUsingOldGfx() const {
		return this->using_old_gfx;
	}
	void setTesting(bool is_testing) {
		this->is_testing = is_testing;
	}
	bool isTesting() const {
		return this->is_testing;
	}
	
	bool createApplication();
	Application *getApplication() {
		return this->application;
	}
	const Application *getApplication() const {
		return this->application;
	}
	bool openScreen(bool fullscreen);
	Gigalomania::Screen *getScreen() {
		return this->screen;
	}
	const Gigalomania::Screen *getScreen() const {
		return this->screen;
	}
	bool isPaused() const;

	void cycleTimeRate() {
		time_rate++;
		if( time_rate > 3 )
			time_rate = 1;
	}
	void increaseTimeRate() {
		if( time_rate > 1 )
			time_rate--;
	}
	void decreaseTimeRate() {
		if( time_rate < 3 )
			time_rate++;
	}
	void setTimeRate(int time_rate);
	int getTimeRate() const {
		return this->time_rate;
	}
	void setRealTime(int real_time);
	int getRealTime() const;
	int getRealLoopTime() const;
	void setGameTime(int game_time);
	int getGameTime() const;
	int getLoopTime() const;
	int getFrameCounter() const {
		return this->frame_counter;
	}
	void updateTime(int time);
	void resetMouseClick();
	int getNClicks();

	void setGameMode(GameMode gameMode) {
		this->gameMode = gameMode;
	}
	GameMode getGameMode() const {
		return this->gameMode;
	}
	void setGameType(GameType gameType) {
		this->gameType = gameType;
	}
	GameType getGameType() const {
		return this->gameType;
	}
	void setDifficultyLevel(DifficultyLevel difficulty_level) {
		this->difficulty_level = difficulty_level;
	}
	DifficultyLevel getDifficultyLevel() const {
		return this->difficulty_level;
	}
	void setGameStateID(GameStateID state, GameState *new_gamestate = NULL);
	GameStateID getGameStateID() const {
		return this->gameStateID;
	}
	void setStateChanged(bool state_changed) {
		this->state_changed = state_changed;
	}
	bool isStateChanged() const {
		return this->state_changed;
	}
	void setGameResult(GameResult gameResult) {
		this->gameResult = gameResult;
	}
	GameResult getGameResult() const {
		return this->gameResult;
	}
	void setupTutorial(const string &id);
	const Tutorial *getTutorial() const {
		return this->tutorial;
	}
	Tutorial *getTutorial() {
		return this->tutorial;
	}
	void setCurrentMap() {
		map = maps[start_epoch][selected_island];
	}
	void setCurrentIsand(int start_epoch, int selected_island);
	const Map *getMap() const;
	Map *getMap();
	const Map *getMap(int i, int j) const {
		return this->maps[i][j];
	}
	int getStartEpoch() const {
		return this->start_epoch;
	}
	int getNSubEpochs() const {
		return this->n_sub_epochs;
	}
	void setPrefSoundOn(bool pref_sound_on) {
		this->pref_sound_on = pref_sound_on;
	}
	bool isPrefSoundOn() const {
		return this->pref_sound_on;
	}
	void setPrefMusicOn(bool pref_music_on) {
		this->pref_music_on = pref_music_on;
	}
	bool isPrefMusicOn() const {
		return this->pref_music_on;
	}
	void setPrefDisallowNukes(bool pref_disallow_nukes) {
		this->pref_disallow_nukes = pref_disallow_nukes;
	}
	bool isPrefDisallowNukes() const {
		return this->pref_disallow_nukes;
	}

	int getMapSqOffset() const {
		return map_sq_offset;
	}
	int getMapSqCoastOffset() const {
		return map_sq_coast_offset;
	}
	void loadPrefs();
	void savePrefs() const;
	bool isDemo() const;

	void deleteState() const;
	void saveState() const;
	bool loadState();

	int getMenAvailable() const;
	int getNSuspended() const;
	void nextEpoch();
	void nextIsland();
	void startIsland();
	void endIsland();
	void returnToChooseIsland();
	void startNewGame();
	void placeTower();
	void newGame();
	void setClientPlayer(int set_client_player);
	bool validPlayer(int player) const;
	void requestQuit(bool force_quit);
	void keypressReturn();
	void togglePause();
	void activate();
	void deactivate();
	void mouseClick(int m_x, int m_y, bool m_left, bool m_middle, bool m_right, bool click);
	void updateGame();
	void drawGame() const;
	void addTextEffect(TextEffect *effect);
	void drawProgress(int percentage) const;

	bool readLineFromRWOps(bool &ok, SDL_RWops *file, char *buffer, char *line, int MAX_LINE, int &buffer_offset, int &newline_index, bool &reached_end);
	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);
	bool loadGame(int slot);
	void saveGame(int slot) const;

	void stopMusic();
	void fadeMusic(int duration_ms) const;
	void playMusic();

	void setupPlayers();
	void setupInventions();
	void setupElements();
	bool playerAlive(int player) const;

	void runTests();
};

extern Game *game_g;

void startIsland_g();
void endIsland_g();
void returnToChooseIsland_g();
void startNewGame_g();

// DATADIR is place to look if data not present in application's folder
//#define DATADIR "C:/temp/glmdata" // test on Windows

extern string maps_dirname;
#ifdef DATADIR
extern string alt_maps_dirname;
#endif

extern const int epoch_dates[];
extern const char *epoch_names[];

enum PlayerMode {
	PLAYER_DEMO = -2,
	PLAYER_NONE = -1
};

class Map {
	string name;
	string filename;
	MapColour colour;
	int n_opponents;
	Sector *sectors[map_width_c][map_height_c];
	bool sector_at[map_width_c][map_height_c];
	bool reserved[map_width_c][map_height_c]; // if true, don't use for starting players - used for testing

public:

	Map(MapColour colour,int n_opponents,const char *name);
	~Map();

	MapColour getColour() const {
		return this->colour;
	}
	int getNOpponents() const {
		return this->n_opponents;
	}
	const Sector *getSector(int x, int y) const;
	Sector *getSector(int x, int y);
	bool isSectorAt(int x, int y) const;

	void newSquareAt(int x,int y);
	void createSectors(PlayingGameState *gamestate, int epoch);
#if 0
	void checkSectors() const;
#endif
	void freeSectors();
	const char *getName() const {
		return name.c_str();
	}
	const char *getFilename() const {
		return filename.c_str();
	}
	void setFilename(const char *filename) {
		this->filename = filename;
	}
	int getNSquares() const;
	void draw(int offset_x, int offset_y) const;
	void findRandomSector(int *rx,int *ry) const;
	bool isReserved(int x, int y) const {
		return this->reserved[x][y];
	}
	void setReserved(int x, int y, bool r) {
		this->reserved[x][y] = r;
	}
	void canMoveTo(bool temp[map_width_c][map_height_c], int sx,int sy,int player) const;
	void calculateStats() const;

	void saveStateSectors(stringstream &stream) const;
};

void playGame(int n_args, char *args[]);

#if defined(__ANDROID__)

// JNI for Android

void launchUrl(string url);

#endif

// game constants

const int SHORT_DELAY = 4000;
const int nuke_delay_c = 250;

const int gameticks_per_hour_c = 200;
const int hours_per_day_c = 12;

const int mine_epoch_c = 3;
const int factory_epoch_c = 4;
const int lab_epoch_c = 5;
//const int air_epoch_c = 6;

const int DESIGNTIME_M3 = 20;
const int DESIGNTIME_M2 = 30;
const int DESIGNTIME_M1 = 40;
const int DESIGNTIME_0 = 50;
const int DESIGNTIME_1 = 100;
const int DESIGNTIME_2 = 200;
const int DESIGNTIME_3 = 400;

const int MANUFACTURETIME_0 = 15;
const int MANUFACTURETIME_1 = 30;
const int MANUFACTURETIME_2 = 45;
const int MANUFACTURETIME_3 = 60;

const int BUILDTIME_TOWER = 80;
const int BUILDTIME_MINE = 40;
const int BUILDTIME_FACTORY = 40;
const int BUILDTIME_LAB = 40;

const int ticks_per_frame_c = 100; // game time ticks per frame rate (used for various animated sprites)
const float time_ratio_c = 0.15f; // game time ticks per time ticks