-
Notifications
You must be signed in to change notification settings - Fork 0
/
collisions.cpp
198 lines (176 loc) · 8.08 KB
/
collisions.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
#include "declarations.h"
#include "prototype.h"
extern Application app;
/// This function is the main function for collision detection
/// Need to pass all the interacting structs and the number of collisions
/// Int return type
int collisionsMain(Character &mainCharacter, Rocks fallingRocks[], int &numberOfCollisions, Lives userLives[], PowerUp fallingPowerUps[]) {
// Declare variables
bool timerRunning;
int returnCode;
// Check for collision between rocks and user
bool checkCollisionRocks = true;
for (int i = 0; i < NUMBER_OF_ROCKS; i++) {
if (checkCollision(mainCharacter, fallingRocks[i], fallingPowerUps[i], checkCollisionRocks)) {
// Check if the player is invincible
timerRunning = al_get_timer_started(app.invincibleTimer);
if (!timerRunning) {
numberOfCollisions ++;
userLives[NUMBER_OF_LIVES - numberOfCollisions].usable = false;
al_start_timer(app.invincibleTimer);
}
}
}
// Check for collision between user and power ups
checkCollisionRocks = false;
for (int i = 0; i < NUMBER_OF_POWERUPS; i++) {
if (checkCollision(mainCharacter, fallingRocks[i], fallingPowerUps[i], checkCollisionRocks)) {
returnCode = activatePowerUp(fallingPowerUps[i], mainCharacter);
}
}
// Informing the user if they are invincible
timerRunning = al_get_timer_started(app.invincibleTimer);
if (timerRunning) {
al_draw_text(app.arial, RED, 310, 775, ALLEGRO_ALIGN_CENTER, "You are invincible");
}
// Draw a flicking collision image
returnCode = drawInvinciblity(timerRunning, mainCharacter);
if (returnCode != 0) {
return returnCode;
}
return 0;
}
/// This function obtains the bounding box coordinates
/// Need to pass the interacting object structs
/// No return type
void obtainBoundingBoxes(Character &a, Rocks b[], PowerUp c[]) {
// Declare variables
int object;
// Calculate bounding boxes
object = CHARACTER;
calcBoundingBoxes(a, b[0], c[0], object);
object = ROCKS;
for (int i = 0; i < NUMBER_OF_ROCKS; i++) {
calcBoundingBoxes(a, b[i], c[i], object);
}
object = POWER_UPS;
for (int i = 0; i < NUMBER_OF_POWERUPS; i++) {
calcBoundingBoxes(a, b[i], c[i], object);
}
}
/// This function calculates the bounding box coordinates
/// Need to pass the interacting objects and a flag to know for which object to calculate the bounding boxes for
/// No return type
void calcBoundingBoxes(Character &a, Rocks &b, PowerUp &c, int object) {
switch(object) {
case CHARACTER:
// Bounding box formula for calculations
a.bbLeft = a.characterPositionX;
a.bbTop = a.characterPositionY;
a.bbRight = a.bbLeft + al_get_bitmap_width(a.bitmap);
a.bbBottom = a.bbTop + al_get_bitmap_height(a.bitmap);
break;
case ROCKS:
b.bbLeft = b.rockPositionX;
b.bbTop = b.rockPositionY;
b.bbRight = b.bbLeft + al_get_bitmap_width(b.bitmap);
b.bbBottom = b.bbTop + al_get_bitmap_height(b.bitmap);
break;
case POWER_UPS:
c.bbLeft = c.powerupXCoordinate;
c.bbTop = c.powerupYCoordinate;
c.bbRight = c.bbLeft + al_get_bitmap_width(c.bitmap);
c.bbBottom = c.bbTop + al_get_bitmap_height(c.bitmap);
break;
}
}
/// This function draws the bounding boxes in red if the user presses 'B'
/// Need to pass movable objects and the keyboard
/// No return type
void drawBoundingBox(Character &image, Rocks object[], Keyboard &userKeyboard, PowerUp powerUpImg[]) {
if (userKeyboard.keyB) {
al_draw_line(image.bbLeft, image.bbTop, image.bbRight, image.bbTop, RED, 1);
al_draw_line(image.bbLeft, image.bbBottom, image.bbRight, image.bbBottom, RED, 1);
al_draw_line(image.bbLeft, image.bbTop, image.bbLeft, image.bbBottom, RED, 1);
al_draw_line(image.bbRight, image.bbTop, image.bbRight, image.bbBottom, RED,1);
for (int i = 0; i < NUMBER_OF_ROCKS; i++) {
al_draw_line(object[i].bbLeft, object[i].bbTop, object[i].bbRight, object[i].bbTop, RED, 1);
al_draw_line(object[i].bbLeft, object[i].bbBottom, object[i].bbRight, object[i].bbBottom, RED, 1);
al_draw_line(object[i].bbLeft, object[i].bbTop, object[i].bbLeft, object[i].bbBottom, RED, 1);
al_draw_line(object[i].bbRight, object[i].bbTop, object[i].bbRight, object[i].bbBottom, RED,1);
}
for (int i = 0; i < NUMBER_OF_POWERUPS; i++) {
al_draw_line(powerUpImg[i].bbLeft, powerUpImg[i].bbTop, powerUpImg[i].bbRight, powerUpImg[i].bbTop, RED, 1);
al_draw_line(powerUpImg[i].bbLeft, powerUpImg[i].bbBottom, powerUpImg[i].bbRight, powerUpImg[i].bbBottom, RED, 1);
al_draw_line(powerUpImg[i].bbLeft, powerUpImg[i].bbTop, powerUpImg[i].bbLeft, powerUpImg[i].bbBottom, RED, 1);
al_draw_line(powerUpImg[i].bbRight, powerUpImg[i].bbTop, powerUpImg[i].bbRight, powerUpImg[i].bbBottom, RED,1);
}
}
al_flip_display();
}
/// This function checks for if collisions are occurring with the interacting objects
/// Need to pass the interacting objects and a flag to know which object collision to check for
/// Bool return type. True if there is a collision
bool checkCollision(Character &a, Rocks &b, PowerUp &c, bool checkCollisionRocks) {
// Basically this function runs through a checklist. If it goes through the checklist without returning a false
// Then the objects are colliding, thus returning a true.
if (checkCollisionRocks) {
if (a.bbBottom < b.bbTop) {
return false;
} else if (a.bbTop > b.bbBottom) {
return false;
} else if (a.bbRight < b.bbLeft) {
return false;
} else if (a.bbLeft > b.bbRight) {
return false;
}
al_play_sample(app.collision, 1.0, 0, 10.0, ALLEGRO_PLAYMODE_ONCE, 0);
return true;
} else {
if (a.bbBottom < c.bbTop) {
return false;
} else if (a.bbTop > c.bbBottom) {
return false;
} else if (a.bbRight < c.bbLeft) {
return false;
} else if (a.bbLeft > c.bbRight) {
return false;
}
al_play_sample(app.collision, 1.0, 0, 10.0, ALLEGRO_PLAYMODE_ONCE, 0);
return true;
}
}
/// This function draws the character being invincible, flickering between a red and normal version of the character
/// Need to pass a bool containing if the invincible timer is running. Need to also pass the character struct
/// Int return type
int drawInvinciblity(bool &timerRunning, Character &mainCharacter){
if (timerRunning || (!mainCharacter.drawCharacterHit && !timerRunning)) {
if (!al_get_timer_started(app.miniTimer)) {
if (mainCharacter.drawCharacterHit) {
// Load the picture based on if the bool is true or false
mainCharacter.bitmap = al_load_bitmap("mainCharacterHit.bmp");
} else {
mainCharacter.bitmap = al_load_bitmap("mainCharacter.bmp");
}
// If the user is currently mini and is invincible
} else {
if (mainCharacter.drawCharacterHit) {
// Load the mini picture of the haracter
mainCharacter.bitmap = al_load_bitmap("miniMainCharacterHit.bmp");
} else {
mainCharacter.bitmap = al_load_bitmap("miniMainCharacter.bmp");
}
}
// Check for loading error
if (!mainCharacter.bitmap) {
al_show_native_message_box(app.display, "Error", "Error", "Failed to load image!", nullptr, ALLEGRO_MESSAGEBOX_ERROR);
al_destroy_display(app.display);
return ERROR_CHARACTER_IMG;
}
//Remove Pink Mask
al_convert_mask_to_alpha(mainCharacter.bitmap, PINK);
// Switch the bool so that next time this function is called it draws the opposite e.g. the character red
mainCharacter.drawCharacterHit = !mainCharacter.drawCharacterHit;
}
return 0;
}