-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
442 lines (336 loc) · 11.2 KB
/
main.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
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
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <cstdio>
#include <unordered_set>
#include <string>
#include <random>
#include "Game.cpp"
// Window Dimensions
const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 500;
// Textures and SDL vars that we'll be constantly using
SDL_Window *gWindow = NULL;
SDL_Renderer *gRenderer = NULL;
SDL_Texture *bg = NULL;
SDL_Texture *spaceship = NULL;
SDL_Texture *asteroid = NULL;
SDL_Texture *lazer = NULL;
TTF_Font *Calibre = NULL;
// funciton to initialize everything in SDL
bool init();
// function to load all of our images to textures and our font
bool loadMedia();
// closes SDL, frees everything up
void close();
// checks if two entities collide
bool checkCollision(Entity *a, Entity *b);
// Main
int main(){
// Initialze all SDL Libraries we need, window and renderer
if(!init()){
printf("Error, Failed to initialize\n");
return -1;
}
// load all the images and our font
if(!loadMedia()){
printf("Error, Failed to load media\n");
return -1;
}
// make and initialize the player
Player player;
player.init( spaceship, gRenderer, SCREEN_WIDTH/2 - 30, SCREEN_HEIGHT-85, 30, 60);
// unordered_set to store all our entities on the screen
unordered_set<Entity* > entities;
// random number generator from <random>
default_random_engine generator;
// distribution ranges for generating random numbers in between
uniform_int_distribution<int> randomXpos(0,441);
uniform_int_distribution<int> randomYpos(100, 250);
uniform_int_distribution<int> randomAsteroidSize(20, 120);
// tmp entity pointer for allocating new entities
Entity* tmp;
// insert palyer into entities set
entities.insert(&player);
// generate 5 asteroids and insert into entities vector
for(int i=0; i<5; i++){
tmp = new Asteroid;
//tmp->init(asteroid, gRenderer, randomXpos(generator), 75, 75, 75);
tmp->init(asteroid, gRenderer, randomXpos(generator), 75, randomAsteroidSize(generator), randomAsteroidSize(generator) );
// insert into entities unordered_set
entities.insert(tmp);
}
// bool to quit out of game loop
bool quit = false;
// to handle keyboard events
SDL_Event e;
// score keeper from score keeper class, which outputs current score to screen
ScoreKeeper sk(Calibre);
while(!quit){
// user requests quit
while(SDL_PollEvent( &e ) != 0){
if(e.type == SDL_QUIT){
quit = true;
}
// else handle keyboard input
else if (e.type == SDL_KEYDOWN){
switch(e.key.keysym.sym){
// fire lazer
case SDLK_w:
case SDLK_f:
case SDLK_UP:
case SDLK_SPACE:
// create new lazer and initialize
tmp = new Lazer;
tmp->init(lazer, gRenderer, player.r.x+10, player.r.y+1, 10, 30);
// insert into entities
entities.insert(tmp);
break;
// move player left
case SDLK_a:
case SDLK_LEFT:
// move player pos left if it doesn't go out of bounds of screen
if(player.r.x != 0) player.r.x-=20;
break;
// move player right
case SDLK_d:
case SDLK_RIGHT:
if(player.r.x != 440) player.r.x+=20;
break;
// add to score for debugging/easy testing of difficulty
default:
sk.score+=100;
break;
}
}
}
// for adding more asteroids to the screen
int numAsteroids =0;
// check for collisions between entities
for(auto i : entities){
for(auto j : entities){
// entities are the same, don't do anything
if(i == j) continue;
// check for collision between lazers and asteroids
if(i->name == "lazer" && j->name == "asteroid"){
if(checkCollision(i, j)){
i->life=0;
j->life=0;
sk.score+=25;
numAsteroids++;
}
}
// check for collision between player and asteroids
else if( i->name == "player" && j->name == "asteroid") {
if(checkCollision(i, j)){
i->life=0;
j->life=0;
}
}
// for making the asteroids at bottom of screen dissapear better
int yCheck = i->r.y + i->r.h/2;
// increment numAsteroids to add new ones
// if(i->name == "asteroid" && i->r.y >= SCREEN_HEIGHT -85 && i->life != 0) numAsteroids++;
if(i->name == "asteroid" && yCheck >= SCREEN_HEIGHT -85 && i->life != 0) numAsteroids++;
// if(i->name == "asteroid" && i->r.y >= SCREEN_HEIGHT -85 && i->life != 0 && sk.score > 1000) numAsteroids++;
if(i->name == "asteroid" && yCheck >= SCREEN_HEIGHT -85 && i->life != 0 && sk.score > 1000) numAsteroids++;
// kill out of bounds asteroids
//if(i->r.y >= SCREEN_HEIGHT - 85 && i->name == "asteroid") i->life=0;
if(yCheck >= SCREEN_HEIGHT - 85 && i->name == "asteroid") i->life=0;
if(i->r.y <= 0 && i->name == "lazer") i->life=0;
}
}
// spawn new asteroids
for(int i=0; i<numAsteroids ; i++){
// 16 is max size of entities on the screen
if(entities.size() > 16) break;
// create new random asteroids
tmp = new Asteroid;
tmp->init(asteroid, gRenderer, randomXpos(generator), randomYpos(generator), randomAsteroidSize(generator), randomAsteroidSize(generator));
// set the difficulty based on the current score
if(sk.score < 1000 && sk.score > 0) tmp->difficulty=0;
else if(sk.score > 1000 && sk.score < 2000) tmp->difficulty=1;
else if(sk.score > 2000 && sk.score < 3000) tmp->difficulty=2;
else if(sk.score > 3000 && sk.score < 4000) tmp->difficulty=3;
else if(sk.score > 4000 && sk.score < 5000) tmp->difficulty=4;
else if(sk.score > 5000) tmp->difficulty=5;
// insert into entities
entities.insert(tmp);
}
// if little asteroids on screen, spawn more
if(entities.size() <= 4){
// create new random asteroids
tmp = new Asteroid;
tmp->init(asteroid, gRenderer, randomXpos(generator), randomYpos(generator), randomAsteroidSize(generator), randomAsteroidSize(generator));
// set the difficulty based on the current score
if(sk.score < 1000 && sk.score > 0) tmp->difficulty=0;
else if(sk.score > 1000 && sk.score < 2000) tmp->difficulty=1;
else if(sk.score > 2000 && sk.score < 3000) tmp->difficulty=2;
else if(sk.score > 3000 && sk.score < 4000) tmp->difficulty=3;
else if(sk.score > 4000 && sk.score < 5000) tmp->difficulty=4;
else if(sk.score > 5000) tmp->difficulty=5;
// insert into entities
entities.insert(tmp);
}
// clear Screen
SDL_RenderClear( gRenderer );
// render background
SDL_RenderCopy(gRenderer, bg, NULL, NULL);
// render score
sk.render(gRenderer, Calibre);
// go through entities
for(auto i = entities.begin(); i != entities.end();){
// get entity
Entity *e = *i;
// render to screen
e->update(gRenderer);
// if it is killed,
if(e->life == 0){
// if it is the player, dont delete it, iterate to next element
if(e->name == "player"){ ++i; continue;}
// erase entity from entities
i = entities.erase(i);
// delete allocated entity
delete e;
}
// else increment iterator
else ++i;
}
// Update Screen
SDL_RenderPresent( gRenderer );
// if player is dead, signal quit loop
if(! player.life ) quit = true;
// delay SDL 16ms
SDL_Delay(16);
}
// erase player from unordered_set we can delete rest of allocated entities
entities.erase(&player);
// deallocate rest or entities
for(auto i : entities) delete i;
// print final score to console
printf("GAME OVER\nFINAL SCORE: %d\n", sk.score);
// clear screen
SDL_RenderClear( gRenderer );
// render background
SDL_RenderCopy(gRenderer, bg, NULL, NULL);
// output players final score, game over screen
sk.gameOver(gRenderer, Calibre);
// update screen
SDL_RenderPresent( gRenderer );
// delay so player can see final score
SDL_Delay(4000);
// close SDL
close();
}
bool init(){
// success flag
bool success = true;
// init SDL video
if( SDL_Init(SDL_INIT_VIDEO) < 0 ){
printf("SDL INIT VIDEO COULD NOT INIT, SDL ERROR: %s\n", SDL_GetError());
success = false;
}
// set scaling
if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) ){
printf("WARNING: Linear texture filtering not enabled!\n");
}
// create window
gWindow = SDL_CreateWindow("SSG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
// error check window
if(gWindow == NULL){
printf("Window could not be created, SDL_ERROR: %s\n", SDL_GetError());
success = false;
}
// create renderer
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
if(gRenderer == NULL){
printf("Renderer could not be created, SDL_ERROR: %s\n", SDL_GetError());
success=false;
}
// init SDL image
int imgFlags = IMG_INIT_PNG;
if( !(IMG_Init(imgFlags) & imgFlags) ){
printf("SDL_image could not initialize, SDL_ERROR: %s\n", SDL_GetError());
success = false;
}
// init SDL TTF
if(TTF_Init() < 0){
printf("SDL_ttf could not initialize, SDL_ERROR: %s\n", SDL_GetError());
success = false;
}
return success;
}
bool loadMedia(){
bool success = true;
// tmp surface
SDL_Surface *tmpSurface = NULL;
// Load the background picture to texture
tmpSurface = IMG_Load("media/bg.png");
if(tmpSurface == NULL){ printf("Failed to load the background, SDL_ERROR: %s\n", SDL_GetError()); success = false; }
bg = SDL_CreateTextureFromSurface(gRenderer, tmpSurface);
SDL_FreeSurface(tmpSurface);
tmpSurface = NULL;
// Load the spaceship to texture
tmpSurface = IMG_Load("media/spaceship.png");
if(tmpSurface == NULL){ printf("Failed to load the spaceship, SDL_ERROR: %s\n", SDL_GetError()); success = false; }
spaceship = SDL_CreateTextureFromSurface(gRenderer, tmpSurface);
SDL_FreeSurface(tmpSurface);
tmpSurface = NULL;
// Load the media to texture
tmpSurface = IMG_Load("media/asteroid.png");
if(tmpSurface == NULL){ printf("Failed to load the asteroid, SDL_ERROR: %s\n", SDL_GetError()); success = false; }
asteroid = SDL_CreateTextureFromSurface(gRenderer, tmpSurface);
SDL_FreeSurface(tmpSurface);
tmpSurface = NULL;
// Load the lazer to texture
tmpSurface = IMG_Load("media/lazer.png");
if(tmpSurface == NULL){ printf("Failed to load the lazer, SDL_ERROR: %s\n", SDL_GetError()); success = false; }
lazer = SDL_CreateTextureFromSurface(gRenderer, tmpSurface);
// Load the font
Calibre = TTF_OpenFont("media/Calibre.ttf", 24);
if(Calibre == NULL ) printf("Could not load text, SDL_ERROR: %s\n", SDL_GetError());
// free the tmp surface
SDL_FreeSurface(tmpSurface);
return success;
}
// close
void close(){
// destroy window and renderer
SDL_DestroyRenderer( gRenderer );
SDL_DestroyWindow( gWindow );
// destroy all textures
SDL_DestroyTexture( bg );
SDL_DestroyTexture( lazer );
SDL_DestroyTexture( spaceship );
SDL_DestroyTexture( asteroid );
// close font
TTF_CloseFont(Calibre);
// quit all SDL systems
IMG_Quit();
SDL_Quit();
TTF_Quit();
}
// collision detection on 2 rectangles from Lazyfoo tutorials
bool checkCollision(Entity *a, Entity *b){
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;
leftA= a->r.x;
rightA = a->r.x + a->r.w;
topA=a->r.y;
bottomA = a->r.y + a->r.h;
leftB= b->r.x;
rightB = b->r.x + b->r.w;
topB=b->r.y;
bottomB = b->r.y + b->r.h;
if( bottomA <= topB )
return false;
if(topA >= bottomB )
return false;
if(rightA <= leftB)
return false;
if(leftA >= rightB)
return false;
return true;
}