Final Submission. I have read and agreed with Statement of Academic Integrity.
Embed:
(wiki syntax)
Show/hide line numbers
Spaceship.cpp
00001 #include "Spaceship.h" 00002 00003 void Spaceship::turn_CW() { 00004 orientation -= turn_rate; 00005 //a variable turn rate makes the gameplay less repetitive 00006 00007 if (orientation < 0) orientation += 6.2832f; 00008 else if (orientation >= 6.2832f)orientation -= 6.2832f; 00009 } 00010 00011 void Spaceship::turn_CCW() { 00012 orientation += turn_rate; 00013 00014 if (orientation >= 6.2832f) orientation -= 6.2832f; 00015 else if (orientation < 0) orientation += 6.2832f; 00016 } 00017 00018 void Spaceship::accelerate() { 00019 v_x += acceleration * cos(orientation); 00020 v_y += acceleration * sin(orientation); 00021 //this function integrates acceleration into velocity in 2D 00022 00023 while (sqrt(v_x * v_x + v_y * v_y) > top_speed) { 00024 v_x -= (v_x / abs(v_y + v_x)) * 0.5f * acceleration; 00025 v_y -= (v_y / abs(v_y + v_x)) * 0.5f * acceleration; 00026 } 00027 //this while loop makes turning more intuitive 00028 //by effectively rotating your heading when the top speed is reached 00029 } 00030 00031 void Spaceship::deccelerate() { 00032 v_x -= acceleration * cos(orientation); 00033 v_y -= acceleration * sin(orientation); 00034 00035 while (sqrt(v_x * v_x + v_y * v_y) > top_speed) { 00036 v_x -= (v_x / abs(v_y + v_x)) * 0.5f * acceleration; 00037 v_y -= (v_y / abs(v_y + v_x)) * 0.5f * acceleration; 00038 } 00039 //entirely identical to accelerate() except direction 00040 } 00041 00042 void Spaceship::update_position() { 00043 pos_x += v_x; 00044 pos_y += v_y; 00045 //this function integrates velocity to position 00046 } 00047 00048 void Spaceship::machine_gun(float x, float y) { 00049 if (x == y && (clock() - reload_timer) > 15) {//this is the case for forward fire 00050 bullet[chamber][0] = pos_x + 3 * cos(orientation); 00051 bullet[chamber][1] = pos_y + 3 * sin(orientation); 00052 bullet[chamber][2] = cos(orientation) + v_x * 0.25f; 00053 bullet[chamber][3] = sin(orientation) + v_y * 0.25f; 00054 //storing the x and y velocity in an array is more efficient 00055 //than doing expensive calculations each frame 00056 00057 chamber++; 00058 chamber = chamber % 5; 00059 //"chamber" limits the number of particles to 5 00060 reload_timer = clock(); 00061 //"reload_timer" will be compared to clock 00062 //next time the function is called, to determine fire rate 00063 gun_FX = 1; 00064 //used to identify when the sound effect should play 00065 } 00066 else if ((clock() - reload_timer) > 30) {//this is the case for turret fire 00067 float angle =- atan(x / y) + 1.5708f; 00068 if (y > 0) angle += 3.1416f; 00069 bullet[chamber][0] = pos_x + 3 * cos(orientation); 00070 bullet[chamber][1] = pos_y + 3 * sin(orientation); 00071 bullet[chamber][2] = cos(orientation - angle) + v_x * 0.25f; 00072 bullet[chamber][3] = sin(orientation - angle) + v_y * 0.25f; 00073 //above adds the ship's velocity to the bullet, Physics! 00074 00075 chamber++; 00076 chamber = chamber % 5; 00077 reload_timer = clock(); 00078 gun_FX = 3; 00079 //a different sound effect 00080 } 00081 } 00082 00083 void Spaceship::cannon() { 00084 //largely similar to machine_gun() 00085 //except fire rate and projectile speed 00086 if ((clock() - reload_timer) > 60) { 00087 bullet[chamber][0] = pos_x + 3 * cos(orientation); 00088 bullet[chamber][1] = pos_y + 3 * sin(orientation); 00089 bullet[chamber][2] = 0.7f * cos(orientation) + v_x * 0.25f; 00090 bullet[chamber][3] = 0.7f * sin(orientation) + v_y * 0.25f; 00091 00092 chamber++; 00093 chamber = chamber % 5; 00094 reload_timer = clock(); 00095 gun_FX = 3; 00096 } 00097 } 00098 00099 void Spaceship::update_bullets() { 00100 //integrates velocity into position 00101 00102 for (int inc2 = 0; inc2 < 5; inc2++) { 00103 bullet[inc2][0] += 4 * bullet[inc2][2]; 00104 bullet[inc2][1] +=4 * bullet[inc2][3]; 00105 } 00106 } 00107 00108 void Spaceship::update() { 00109 //a public function that makes sure 00110 //both the ship and its particles update at once 00111 00112 update_position(); 00113 update_bullets(); 00114 } 00115 00116 void Spaceship::controls(bool player_ship_type, 00117 bool Y, bool A, bool X, bool B, float x, float y) { 00118 //calls the private functions all at once 00119 //with instructions from main 00120 00121 if (Y) turn_CW(); 00122 if (A) turn_CCW(); 00123 if (X) accelerate(); 00124 if (B) deccelerate(); 00125 if (abs(x) > 0.1f || abs(y) > 0.1f) { 00126 if (player_ship_type == 0) machine_gun(x, y); 00127 else cannon(); 00128 } 00129 #ifdef DEBUG_controls 00130 sprintf(g_buffer, "%1.1f,%1.1f", x, y); 00131 lcd.printString(g_buffer, 0, 4); 00132 printf("Joystick val: %1.1f,%1.1f\n", x, y); 00133 #endif 00134 update(); 00135 } 00136 00137 void Spaceship::AI_controls(float target_x, float target_y, float target_orientation) { 00138 float diff_x = target_x - pos_x; 00139 if (abs(diff_x) < 0.001f) diff_x = 0.001f; 00140 00141 float angle_to_target = atan((target_y - pos_y) / diff_x) + 3.1416f; 00142 if (diff_x > 0) angle_to_target += 3.1416f; 00143 00144 float diff_angle = orientation - angle_to_target; 00145 if (diff_angle > 6.1831f) diff_angle -= 6.2831f; 00146 if (diff_angle < -6.1831f) diff_angle += 6.2831f; 00147 //above maths finds if a CW or CCW turn is needed 00148 //to point the enemy ships towards the player 00149 00150 if (diff_angle > 0.10f && diff_angle < 3.25f || diff_angle < -3.25f) turn_CW(); 00151 else if (diff_angle < -0.10 || diff_angle > 3.25f) turn_CCW(); 00152 else if (sqrt((target_y - pos_y) * (target_y - pos_y) + diff_x * diff_x) < 40) { 00153 machine_gun(0,0); 00154 } 00155 //if no adjustment is needed, fire away 00156 00157 accelerate(); 00158 //always accelerating makes the enemies fly more naturally 00159 00160 #ifdef DEBUG_AI 00161 sprintf(g_buffer, "%1.3f", diff_x); 00162 lcd.printString(g_buffer, 0, 4); 00163 sprintf(g_buffer, "%1.2f,%1.2f", pos_x, pos_y); 00164 lcd.printString(g_buffer, 0, 5); 00165 printf("Enemy position: %3.1f,%3.1f\n", pos_x, pos_y); 00166 #endif 00167 } 00168 00169 void Spaceship::init_ship(float x, float y, float direction, 00170 float turn, float acc, float top, int health) { 00171 pos_x = x; pos_y = y; 00172 v_x = 0; v_y= 0; 00173 00174 if (x == 1 && y == 0) v_x = 0.1;//drft the player forwars, that looks cool 00175 acceleration = acc; 00176 orientation = direction; 00177 top_speed = top; 00178 turn_rate = turn; 00179 if (turn_rate > 0.10f) turn_rate = 0.10f; 00180 chamber = 0; 00181 reload_timer = 0; 00182 HP = health; 00183 explosion_FX = 8; 00184 // sets all ship parameters to the declaration from main 00185 00186 for (int inc = 0; inc < 5; inc++) { 00187 bullet[inc][0] = 50; 00188 bullet[inc][1] = 50; 00189 bullet[inc][2] = 4; 00190 bullet[inc][3] = 4; 00191 } 00192 // make sure the projectiles are at known positions 00193 // and won't appear on screen 00194 } 00195 00196 bool Spaceship::check_bullets(int temp1, int temp2) { 00197 for (int inc1 = 0; inc1 < 5; inc1++) { 00198 if (temp1 == int(bullet[inc1][0]) && temp2 == int(bullet[inc1][1]) 00199 || temp1 == int(bullet[inc1][0] + bullet[inc1][2]) 00200 && temp2 == int(bullet[inc1][1] + bullet[inc1][3]) 00201 || temp1 == int(bullet[inc1][0] + 2 * bullet[inc1][2]) 00202 && temp2 == int(bullet[inc1][1] + 2 * bullet[inc1][3]) 00203 || temp1 == int(bullet[inc1][0] + 3 * bullet[inc1][2]) 00204 && temp2 == int(bullet[inc1][1] + 3 * bullet[inc1][3]) 00205 || temp1 == int(bullet[inc1][0] + 4 * bullet[inc1][2]) 00206 && temp2 == int(bullet[inc1][1] + 4 * bullet[inc1][3]) 00207 || temp1 == int(bullet[inc1][0] + 5 * bullet[inc1][2]) 00208 && temp2 == int(bullet[inc1][1] + 5 * bullet[inc1][3]) 00209 || temp1 == int(bullet[inc1][0] + 6 * bullet[inc1][2]) 00210 && temp2 == int(bullet[inc1][1] + 6 * bullet[inc1][3]) 00211 || temp1 == int(bullet[inc1][0] + 7 * bullet[inc1][2]) 00212 && temp2 == int(bullet[inc1][1] + 7 * bullet[inc1][3])) { 00213 return 1; 00214 // this function allows a much simpler way to check 00215 // if an area of space contains a bullet for rendering purposes 00216 } 00217 } 00218 return 0; 00219 // 0 is returned if no bullets are present 00220 } 00221 00222 bool Spaceship::check_hitbox(int target_x, int target_y, int radius) { 00223 float distance_x, distance_y; 00224 00225 for (int inc = 0; inc < 5; inc++) { 00226 distance_x = bullet[inc][0] - target_x; 00227 distance_y = bullet[inc][1] - target_y; 00228 // above converts absolute position to relative distance 00229 00230 if (sqrt(distance_x * distance_x + distance_y * distance_y) < radius) { 00231 // calculates if the distance is short enough 00232 // to the centre of a target for a hit 00233 00234 bullet[inc][0] += 60 * bullet[inc][2];//bullets that land on target 00235 bullet[inc][1] += 60 * bullet[inc][3];//are moved out of the screen 00236 return 1; 00237 } 00238 } 00239 return 0; 00240 // return a 0 when no hits are detected 00241 }
Generated on Tue Jul 12 2022 17:30:57 by
1.7.2