-
Notifications
You must be signed in to change notification settings - Fork 0
/
Gameplay.cpp
302 lines (267 loc) · 8.48 KB
/
Gameplay.cpp
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
#include "Gameplay.h"
#include "Map.h"
#include "MapEditor.h"
#include "Tower.h"
#include "ArrowTower.h"
#include "IceTower.h"
#include "FireTower.h"
#include <conio.h>
#include "FireCritter.h"
#include "ArmorCritter.h"
#include "SpeedCritter.h"
#include "CritterFactory.h"
#include "CritterDisplay.h"
void welcome_message()
{
cout << "\n----------------------------------------------------" << endl;
cout << "Welcome to COMP345 Tower Defense!" << endl;
cout << "----------------------------------------------------\n" << endl;
system("PAUSE");
system("CLS");
//We will do display_session everytime we clear the screen
//This will update our info for gold, lives, etc.
}
//We will check if a new critter should be spawned
void check_for_spawn(Timer &timer, vector<Critter*> &critter_list, vector<Coordinate> &path, Map* &map, int &critter_count, int level, float spawn_rate, int &critter_type)
{
if (timer.getTime() >= spawn_rate && critter_count != 0)
{
Critter* critter = NULL;
CritterFactory Factory;
critter = Factory.getCritter(path, map, level, critter_type);
critter_list.push_back(critter); //spawn new critter
critter_type = (critter_type + 1) % 3; //change to next critter type
timer.reset();
critter_count--; //decrement the count (once 0 all monsters have spawned for the round)
}
}
//If a critter's HP has gone below 0, we must remove them from the list. This method checks that
// and removes the critter if applicable
void clean_critter_list(vector<Critter*> &critter_list, int path_size, Session &session)
{
Critter* temp = NULL;
for (int i = 0; i < critter_list.size(); i++)
{
if (critter_list.at(i)->getHP() <= 0)
{
session.reward(critter_list.at(i)->getValue()); //Add critter gold value
temp = critter_list.at(i);
critter_list.erase(critter_list.begin() + i);
}
else if (critter_list.at(i)->getLocation() == path_size)
{
session.loseLife();
if (session.getGold() >= critter_list.at(i)->getStrength())
session.loseGold(critter_list.at(i)->getStrength()); //reduces gold by strength
else
session.loseGold(session.getGold()); //brings down to 0 (avoid having (-) gold
temp = critter_list.at(i);
critter_list.erase(critter_list.begin() + i);
} //if critter reaches end, lose a life and gold based on strength
if (temp != NULL)
{
delete temp;
temp = NULL;
}
}
}
//Different levels have different quantity of critters. This method will return the
//quantity for that round
int get_spawn_quantity(int round)
{
switch (round)
{
case 1:
return LEVEL_1_QUANTITY;
case 2:
return LEVEL_2_QUANTITY;
case 3:
return LEVEL_3_QUANTITY;
case 4:
return LEVEL_4_QUANTITY;
case 5:
return LEVEL_5_QUANTITY;
case 6:
return LEVEL_6_QUANTITY;
case 7:
return LEVEL_7_QUANTITY;
case 8:
return LEVEL_8_QUANTITY;
case 9:
return LEVEL_9_QUANTITY;
case 10:
return LEVEL_10_QUANTITY;
}
}
int get_reward(int round)
{
switch (round)
{
case 1:
return ROUND_1_REWARD;
case 2:
return ROUND_2_REWARD;
case 3:
return ROUND_3_REWARD;
case 4:
return ROUND_4_REWARD;
case 5:
return ROUND_5_REWARD;
case 6:
return ROUND_6_REWARD;
case 7:
return ROUND_7_REWARD;
case 8:
return ROUND_8_REWARD;
case 9:
return ROUND_9_REWARD;
case 10:
return ROUND_10_REWARD;
}
}
//If user pauses the game will the round is in action, we will display the pause menu below and allow
//the user to buy, sell, upgrade towers
void pause_menu(Session &session, vector<Tower*> &tower_list, int &list_size, bool &start, Map* &map, vector<Critter*> &critter_list, ErrorHandling* &errorObj)
{
string option;
bool inputTest = false;
while (!inputTest)
{
system("CLS");
cout << "You have paused the game. Select an option below:" << endl;
cout << "--------------------------------------------------" << endl;
cout << "Tower Menu (1): " << endl;
cout << "Critter Interface (2): " << endl;
cout << "Resume Game (3): " << endl;
cout << "End Game (4): " << endl;
cout << "--------------------------------------------------" << endl;
cout << "\nPlease enter the action you would like to take: ";
cin >> option;
try
{
errorObj->testIntStringInput(option, 1, 4);
inputTest = true;
}
catch (string e)
{
system("CLS");
cout << endl << e << endl << endl;
}
if (option == "1")
{
system("CLS");
tower_menu(session, tower_list, list_size, start, map, "PAUSE", errorObj); //display tower menu
break;
}
else if (option == "2")
{
system("CLS");
critter_interface(critter_list);
system("PAUSE");
break;
}
else if (option == "3")
break; //return game
else if (option == "4")
{
system("CLS");
cout << "GAME OVER\n" << endl;
system("PAUSE");
exit(0);
}
}
}
//If user pauses game, we want to pause all the timers of our critters, towers, and spawn_rate
void pause_all_timers(vector<Critter*> &critter_list, vector<Tower*> &tower_list, Timer &spawn_timer)
{
for (int i = 0; i < critter_list.size(); i++)
critter_list.at(i)->pauseTimer();
for (int i = 0; i < tower_list.size(); i++)
tower_list.at(i)->pauseTimer();
spawn_timer.stop();
}
//Resume all our timers
void resume_all_timers(vector<Critter*> &critter_list, vector<Tower*> &tower_list, Timer &spawn_timer)
{
for (int i = 0; i < critter_list.size(); i++)
critter_list.at(i)->startTimer();
for (int i = 0; i < tower_list.size(); i++)
tower_list.at(i)->startTimer();
spawn_timer.start();
}
//This method will check if the user has run out of lives, if it has it will exit
void game_over(Session &session)
{
if (session.getLives() == 0)
{
system("CLS");
cout << "You have run out of lives." << endl;
cout << "\nGAME OVER" << endl;
system("PAUSE");
exit(0);
}
}
void critter_interface(vector<Critter*> &critter_list)
{
cout << "\nCritter Interface:" << endl;
cout << "---------------------------------------------------------" << endl;
for (int i = 0; i < critter_list.size(); i++)
{
cout << i << ": ";
displayCritter(critter_list.at(i));
}
cout << "---------------------------------------------------------" << endl;
}
//The main method of the gameplay. It will loop every 800ms and refresh the console will the updated display of the map. Through each loop
//the critters check if enough time has passed for them to move, the towers check if a critter is in range and we check if another critter should
//be spawned. We also display the critters and their health & speed as they traverse the path
void start_next_round(vector<Coordinate> &path, vector<Critter*> &critter_list, Map* &map, MapEditor* &display, vector<Tower*> &tower_list, Session &session, int &list_size, bool &start, ErrorHandling* &errorObj)
{
Timer spawn_timer; //timer used between spawning new critters
spawn_timer.start();
int critter_count = get_spawn_quantity(session.getRound()); //max number of critters
float spawn_rate = SPAWN_RATE;
int path_size = path.size();
int critter_type = 0;
while (1)
{
if (_kbhit()) //if true user has paused the game
{
pause_all_timers(critter_list, tower_list, spawn_timer);
pause_menu(session, tower_list, list_size, start, map, critter_list,errorObj);
resume_all_timers(critter_list, tower_list, spawn_timer);
}
Sleep(800);
system("CLS");
cout << red << "PRESS ANY KEY TO PAUSE THE GAME" << white << endl;
display_session(session);
display->drawMap();
for (int i = 0; i < critter_list.size(); i++)
critter_list.at(i)->check_for_update();
//Go through critter list and see if you can update
for (int i = 0; i < tower_list.size(); i++)
tower_list.at(i)->attackCritter(critter_list);
//Go through tower list and see if any towers can attack
check_for_spawn(spawn_timer, critter_list, path, map, critter_count, session.getRound(), spawn_rate, critter_type);
//check if time to spawn new critter
clean_critter_list(critter_list, path_size, session); //remove dead critters
//Critter Interface
critter_interface(critter_list);
game_over(session); //check if lives are 0
if (critter_count == 0 && critter_list.size() == 0)
break; //round is over
}
Coordinate endCoordinate = map->getPathVector()[map->getPathVector().size() - 1];
int endX = endCoordinate.getX();
int endY = endCoordinate.getY();
map->setEnd(endX, endY);
system("CLS");
display_session(session);
display->drawMap();
cout << "\nEnd of Round " << session.getRound() << "." << endl;
cout << "You have earned " << get_reward(session.getRound()) << " gold for completing the round!" << endl;
session.reward(get_reward(session.getRound()));
session.nextRound(); //brings us next round (increment)
system("PAUSE");
system("CLS");
}