Final Submission. I have read and agreed with Statement of Academic Integrity.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Spaceship.cpp Source File

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 }