-#include <cstring>
-#include <math.h>
-#include <unistd.h>
-#include "assteroids.h"
-#include "powerups.hpp"
-#include "vectormath.hpp"
-
-void show_death_stats();
-void show_instructions();
-
-Vector2 flatten(Vector4 pV){
- Vector2 stan = {pV.x, pV.y};
- return stan;
-}
-
-Vector4 translate(Vector4 v1, Vector4 v2) {
- Vector4 translation = {v1.x+v2.x, v1.y+v2.y, v1.y+v2.y, v1.z+v2.z};
- return translation;
-}
-
-bool onscreen(Vector2 v) {
- // Ensure v is still onscreen
- return CheckCollisionPointRec(v, screenspace);
-}
-
-void init_ship(){
- ship_alive = true;
- throttle = false;
- score = 0;
- nose.z = 270;
- port.z = 55;
- starboard.z = 125;
- active_powerups = 0;
-
- nose.x = 0; nose.y = -15;
- port.x = -10; port.y = 15;
- starboard.x = 10; starboard.y = 15;
- center.x = scrW/2; center.y = scrH/2;
- ship_bearing = 0;
-
- memset(bullets, 0, sizeof(Vector4) * MAX_BULLETS);
- memset(asteroids, 0, sizeof(Vector4) * MAX_ASTEROIDS);
- memset(dead_ship, 0, sizeof(Vector4) * SHIP_DEBRIS);
- init_shotgun();
- memset(&shotgun_box, 0, sizeof(Vector4));
- memset(dead_astr, 0, sizeof(Vector4) * SHIP_DEBRIS * MAX_ASTEROIDS);
- memset(&shield_pickup, 0, sizeof(Vector4));
- memset(&bomb_proj, 0, sizeof(Vector4));
- bomb_proj.w = -1;
-
- bomb_kills = shotgun_kills = deaths_avoided = time_alive = 0;
-}
-
-void die(){
- ship_alive = false;
- disable_shield();
- for(int i = 0; i < SHIP_DEBRIS; i++) {
- if (!onscreen(flatten(dead_ship[i])))
- continue;
- dead_ship[i].x = center.x; dead_ship[i].y = center.y;
- dead_ship[i].z = (360/SHIP_DEBRIS) * (i + 1);
- dead_ship[i].w = 6;
- }
- disable_shotgun();
-
-}
-
-void spin_ship(int az_delta){
- nose.z += az_delta; port.z += az_delta; starboard.z += az_delta;
- nose.x = cos(nose.z * (PI/180)) * 15;
- nose.y = sin(nose.z * (PI/180)) * 15;
-
- port.x = cos(port.z * (PI/180)) * 15;
- port.y = sin(port.z * (PI/180)) * 15;
-
- starboard.x = cos(starboard.z * (PI/180)) * 15;
- starboard.y = sin(starboard.z * (PI/180)) * 15;
-
-}
-
-void update_v4(Vector4* origin, Vector4* v_body, int speed){
- Vector2 heading = v2_normal(flatten(*origin));
- v_body->x += heading.x * (speed*throttle);
- v_body->y += heading.y * (speed*throttle);
-}
-
-void shoot(){
- if(time(NULL) <= last_fire)
- return;
- for(int s = 0; s < 1 + (4 * (active_powerups & SHOTGUN)); s++) {
- for(int i = 0; i < MAX_BULLETS; i++){
- // find available bullet
- if(bullets[i].w == 0) {
- bullets[i].x = center.x;
- bullets[i].y = center.y;
- bullets[i].z = nose.z + bullet_offsets[s];
- bullets[i].w = 1;
- PlaySound(sfx_shoot);
- break;
- }
- }
- }
- if(active_powerups & SHOTGUN)
- shotgun_blasts--;
- if(shotgun_blasts == 0 && active_powerups & SHOTGUN)
- disable_shotgun();
- time(&last_fire);
-}
-
-void update_bullets(){
- Vector4* b;
- for(int i = 0; i < MAX_BULLETS; i++){
- if(!onscreen(flatten(bullets[i])))
- bullets[i].w = 0;
-
- if(bullets[i].w == 1) {
- b = &bullets[i];
- b->x += cos(b->z * (PI/180)) * 15;
- b->y += sin(b->z * (PI/180)) * 15;
- DrawCircleV(flatten(bullets[i]), 2, WHITE);
- for(int a = 0; a < MAX_ASTEROIDS; a++) {
- if(CheckCollisionPointCircle(flatten(bullets[i]), flatten(asteroids[a]), asteroids[a].w)) {
- asteroids[a].w = 0;
- bullets[i].w = 0;
- score++;
- explode_asteroid(&asteroids[a]);
- if((score%15 == 0) && score > 0 && bomb_proj.w == -1) {
- active_powerups |= BOMB;
- }
- if(active_powerups & SHOTGUN) {
- shotgun_kills++;
- }
- break;
- }
- }
- }
- }
-}
-
-void spawn_astr() {
- int heading = rand() % 360;
- for(int i = 0; i < MAX_ASTEROIDS; i++){
- // find available asteroid
- // no size means you're fuckin dead, gyro
- if(asteroids[i].w == 0) {
- asteroids[i].z = heading;
- asteroids[i].w = rand() % 34 + 30;
- asteroids[i].x = (heading > 90 && heading < 270) ? scrW : 0;
- asteroids[i].y = (heading > 180 && heading < 360) ? scrH : 0;
- break;
- }
- }
-}
-
-void explode_ship() {
- for (int i = 0; i < SHIP_DEBRIS; i++) {
- DrawCircleLines(dead_ship[i].x, dead_ship[i].y, dead_ship[i].w, RED);
- dead_ship[i].x += cos(dead_ship[i].z * (PI/180)) *3;
- dead_ship[i].y += sin(dead_ship[i].z * (PI/180)) *3;
- }
-}
-
-bool ship_collision(Vector4* body) {
- return (
- CheckCollisionPointCircle(flatten(translate(nose, center)), flatten(*body), body->w * 0.9f) ||
- CheckCollisionPointCircle(flatten(translate(port, center)), flatten(*body), body->w * 0.9f) ||
- CheckCollisionPointCircle(flatten(translate(starboard, center)), flatten(*body), body->w * 0.9f)
- );
-
-}
-
-void update_astrs() {
- Vector4* astr;
- for(int i = 0; i < MAX_ASTEROIDS; i++) {
- astr = &asteroids[i];
- if(astr->w != 0) {
- astr->x += cos(astr->z * (PI/180)) *3;
- astr->y += sin(astr->z * (PI/180)) *3;
- DrawPolyLines(flatten(*astr), 7, astr->w, 0, RAYWHITE);
- }
- if(!onscreen(flatten(*astr))) {
- astr->w = 0;
- }
- if(CheckCollisionCircles(flatten(*astr), astr->w, flatten(bomb_proj), bomb_proj.w) && bomb_proj.w >= 16 && astr->w != 0 && ship_alive) {
- astr->w = 0;
- bomb_proj.z = -1; //stop moving the bomb and explode
- bomb_proj.w +=16;
- explode_asteroid(astr);
- bomb_kills++;
- }
-
- if(ship_collision(astr) && ship_alive){
- if((active_powerups & GOD) || debug_nodie) {
- deaths_avoided++;
- continue;
- }
- die();
- }
- }
-
-}
-
-int main(int argc, char** argv) {
- int opts;
-
- while((opts = getopt(argc, argv, "fsgb")) != -1) {
- switch(opts) {
- case 'f':
- printf("turned on fps counter\n");
- enable_fps = true;
- break;
- case 's':
- debug_nodie = true;
- break;
- case 'g':
- debug_shotgun = true;
- break;
- case 'b':
- debug_bomb = true;
- break;
- case '?':
- default:
- break;
- }
-
- }
-
- InitAudioDevice();
- if(IsAudioDeviceReady()) {
- sfx_shoot = LoadSound(SFX_SHOOT_FILE);
- sfx_music = LoadSound(SFX_BGM_FILE);
- }
- asteroids = (Vector4*)malloc(sizeof(Vector4)*MAX_ASTEROIDS);
- bullets = (Vector4*)malloc(sizeof(Vector4)*MAX_BULLETS);
- dead_ship = (Vector4*)malloc(sizeof(Vector4) * SHIP_DEBRIS);
-
- srand(time(NULL));
- InitWindow(scrW, scrH, "Randy's Rowdy Rocket Roundup");
- SetTargetFPS(50);
- init_ship();
- spin_ship(0);
- while(!WindowShouldClose()){
- BeginDrawing();
- ClearBackground(Space);
-
- if(IsKeyPressed('H')) {
- paused = !paused;
- }
- if(paused) {
- show_instructions();
- PauseSound(sfx_music);
- EndDrawing();
- continue;
- }
-
- if((IsKeyDown('J') || IsKeyDown(KEY_LEFT)) && ship_alive) {
- spin_ship(-4);
- }
- if((IsKeyDown('L') || IsKeyDown(KEY_RIGHT)) && ship_alive) {
- spin_ship(4);
- }
- if((IsKeyPressed('I') || IsKeyPressed(KEY_UP)) && ship_alive) {
- throttle = true;
- SetSoundVolume(sfx_music, 0.5f);
- }
- if(IsKeyPressed('S') && ship_alive) {
- shoot();
- }
- if(IsKeyPressed('R') && !ship_alive) {
- init_ship();
- spin_ship(0);
- StopSound(sfx_music);
- }
- if(IsKeyPressed('A') && ((active_powerups & BOMB) || debug_bomb)) {
- active_powerups ^= BOMB;
- launch_bomb();
- }
-
- if(!onscreen(flatten(center)) && ship_alive)
- die();
-
- if(ship_alive) {
- time_alive++;
- update_v4(&nose, ¢er, 3);
- DrawTriangleLines(
- flatten(translate(nose, center)),
- flatten(translate(port, center)),
- flatten(translate(starboard, center)),
- RAYWHITE);
- astr_spawner = rand() & 1000 + 1;
- if(active_powerups & GOD) {
- DrawCircleSectorLines(flatten(center), 3*shield_hp, 0, 360, 6, SKYBLUE);
- DrawCircleSectorLines(flatten(center), 2*shield_hp, 0, 360, 6, SKYBLUE);
- if(time(NULL) > shield_spawn_time) {
- time(&shield_spawn_time);
- shield_hp--;
- }
- if(shield_hp <= 0)
- disable_shield();
- }
- if(bomb_proj.w >= 0)
- update_bomb();
- if(!throttle) {
- DrawText("KILL TO LIVE", (scrW/2)-(MeasureText("KILL TO LIVE", 64)/2), (scrH/2)-128, 64, RED);
- DrawText("LAUNCH TO START", (scrW/2)-(MeasureText("LAUNCH TO START", 32)/2), (scrH/2)+64, 32, RED);
- }
- if(active_powerups & BOMB && bomb_proj.w == -1)
- DrawCircleSectorLines(flatten(translate(nose, center)), 4.0f, 0, 360, 360, RED);
- if(debug_shotgun)
- enable_shotgun();
- } else if(!(active_powerups & GOD)) {
- DrawText("YOU DIED", (scrW/2)-(MeasureText("YOU DIED", 64)/2), (scrH/2)-64, 64, RED);
- DrawText("FUCK YOU", (scrW/2)-(MeasureText("FUCK YOU", 16)/2), (scrH/2)-8, 16, RED);
- explode_ship();
- SetSoundVolume(sfx_music, .1);
- show_death_stats();
- }
- if(throttle && astr_spawner > 989) {
- spawn_astr();
- }
- update_bullets();
- update_astrs();
- update_explosions();
- if(ship_alive && throttle && shotgun_box.w == 0 && (rand() % 10000) < 8 && !active_powerups & SHOTGUN)
- init_shotgun(); //a little treat
- if(shotgun_box.w == 1)
- draw_shotgun();
- if(shield_pickup.w > 0)
- draw_shield_pickup();
- DrawText("[H]elp", (scrW-MeasureText("[H]elp", 32)-32), scrH-34, 32, WHITE);
- DrawText(TextFormat("%d", score), 4, scrH-34, 32, WHITE);
- if(enable_fps)
- DrawFPS(0, 0);
- EndDrawing();
- if(throttle && !IsSoundPlaying(sfx_music)) {
- PlaySound(sfx_music);
- }
-
- }
- UnloadSound(sfx_shoot);
- UnloadSound(sfx_music);
-
- CloseAudioDevice();
- CloseWindow();
- free(bullets);
- free(asteroids);
- free(dead_ship);
-
- return 0;
-}
-
-//spawn a shield pickup at a dead asteroid
-void init_shield(Vector4* v) {
- shield_pickup.x = v->x;
- shield_pickup.y = v->y;
- shield_pickup.w = 16;
-}
-void draw_shield_pickup() {
- DrawRingLines(flatten(shield_pickup), shield_pickup.w, shield_pickup.w * 1.3, 0, 360, 6, SKYBLUE);
- DrawRingLines(flatten(shield_pickup), shield_pickup.w/3, shield_pickup.w * 0.66, 0, 360, 6, SKYBLUE);
- if(CheckCollisionPointCircle(flatten(center), flatten(shield_pickup), shield_pickup.w)) {
- shield_pickup.w = 0;
- enable_shield();
- }
-}
-
-void enable_shield() {
- memset(&shield_pickup, 0, sizeof(Vector4));
- shield_hp = 9;
- active_powerups |= GOD;
- time(&shield_spawn_time);
-}
-
-void disable_shield() {
- active_powerups ^= GOD;
- shield_hp = 9;
-}
-
-void explode_asteroid(Vector4* astr) {
- for(int i = 0; i < MAX_ASTEROIDS; i++) {
- if(dead_astr[i][0].w == 0) {
- for (int a = 0; a < SHIP_DEBRIS; a++) {
- dead_astr[i][a].x = astr->x;
- dead_astr[i][a].y = astr->y;
- dead_astr[i][a].z = ((360/SHIP_DEBRIS) * a) + (360/(SHIP_DEBRIS*3));
- dead_astr[i][a].w = 1;
- }
- if(shield_pickup.w == 0 && rand() % 30 < 2)
- init_shield(astr);
- break;
- }
- }
-}
-
-void update_explosions() {
- int offscreen_bubbles = 0;
- for(int i = 0; i < MAX_ASTEROIDS; i++) {
- if(dead_astr[i][0].w == 1) {
- for (int a = 0; a < SHIP_DEBRIS; a++) {
- dead_astr[i][a].x += cos(dead_astr[i][a].z * (PI/180)) * 5;
- dead_astr[i][a].y += sin(dead_astr[i][a].z * (PI/180)) * 5;
- DrawCircleLines(dead_astr[i][a].x, dead_astr[i][a].y, 8, RAYWHITE);
- if(!onscreen(flatten(dead_astr[i][a])))
- offscreen_bubbles++;
- if(offscreen_bubbles == SHIP_DEBRIS-1)
- memset(&dead_astr[i], 0, sizeof(Vector4) * SHIP_DEBRIS);
- }
- }
- offscreen_bubbles=0;
- }
-
-}
-
-void init_shotgun() {
- int heading = rand() % 360;
- shotgun_box.z = heading;
- shotgun_box.w = 1;
- shotgun_box.x = (heading > 90 && heading < 270) ? scrW : 0;
- shotgun_box.y = (heading > 180 && heading < 360) ? scrH : 0;
-
- memcpy(s_top_box, master_s_top_box, sizeof(Vector2)*4); memcpy(s_bot_box, master_s_bot_box, sizeof(Vector2)*4);
- for(int i = 0; i < 4; i++) {
- s_top_box[i].x += shotgun_box.x;
- s_top_box[i].y += shotgun_box.y;
- s_bot_box[i].x += shotgun_box.x;
- s_bot_box[i].y += shotgun_box.y;
- }
-}
-
-void update_shotgun() {
- float xd = cos(shotgun_box.z * (PI/180)) *2;
- float yd = sin(shotgun_box.z * (PI/180)) *2;
- shotgun_box.x += xd;
- shotgun_box.y += yd;
-
- for(int i = 0; i < 4; i++) {
- s_top_box[i].x += xd;
- s_top_box[i].y += yd;
- s_bot_box[i].x += xd;
- s_bot_box[i].y += yd;
- }
-
- if(!onscreen(flatten(shotgun_box)))
- shotgun_box.w = 0;
- if(CheckCollisionPointCircle(flatten(center), flatten(shotgun_box), 32)) {
- enable_shotgun();
- shotgun_box.w = 0;
- }
-}
-
-void draw_shotgun() {
- update_shotgun();
- DrawLineStrip(s_top_box, 4, WHITE);
- DrawLineStrip(s_bot_box, 4, WHITE);
- DrawText("S", shotgun_box.x-6, shotgun_box.y-8, 20, GOLD);
-}
-
-void launch_bomb() {
- bomb_proj.x = flatten(translate(nose, center)).x;
- bomb_proj.y = flatten(translate(nose, center)).y;
- bomb_proj.z = nose.z;
- bomb_proj.w = 16;
-}
-
-void update_bomb() {
- if(bomb_proj.z != -1) {
- bomb_proj.x += cos(bomb_proj.z * (PI/180)) *6;
- bomb_proj.y += sin(bomb_proj.z * (PI/180)) *6;
- }
- if(bomb_proj.w < 128) {
- DrawPolyLines(flatten(bomb_proj), 8, bomb_proj.w, whrot, DARKPURPLE);
- DrawPolyLines(flatten(bomb_proj), 8, bomb_proj.w * .8, -whrot, DARKPURPLE);
- DrawPolyLines(flatten(bomb_proj), 8, bomb_proj.w * .5, whrot, DARKPURPLE);
- whrot++;
- } else if (bomb_proj.w >= 128 || (!onscreen(flatten(bomb_proj)) && bomb_proj.w != -1)) {
- active_powerups ^= BOMB;
- memset(&bomb_proj, 0, sizeof(Vector4));
- bomb_proj.w = -1;
- }
- if (!onscreen(flatten(bomb_proj))) {
- bomb_proj.w = -1;
- }
-}
-
-void show_instructions() {
- DrawText("I/UP : START", scrW/4, (scrH/2)-256, 32, RED);
- DrawText("J/LEFT : TURN PORT", scrW/4, (scrH/2)-206, 32, RED);
- DrawText("L/RIGHT : TURN STARBOARD", scrW/4, (scrH/2)-156, 32, RED);
- DrawText("S : SHOOT", scrW/4, (scrH/2)-106, 32, RED);
- DrawText("R : RESPAWN", scrW/4, (scrH/2)-56, 32, RED);
- DrawText("A : WORMHOLE", scrW/4, (scrH/2)-6, 32, RED);
- DrawText("H : UN/PAUSE", scrW/4, (scrH/2)+50, 32, RED);
-
- DrawText("Thanks raysan for Raylib", scrW/4, (scrH)-34, 16, WHITE);
-}
-
-void show_death_stats() {
- DrawText(TextFormat("KILLS : %d", score), scrW/4, (scrH/2)+64, 24, RED);
- DrawText(TextFormat("SHOTGUN KILLS : %d", shotgun_kills), scrW/4, (scrH/2)+96, 24, RED);
- DrawText(TextFormat("WORMHOLE KILLS : %d", bomb_kills), scrW/4, (scrH/2)+128, 24, RED);
- DrawText(TextFormat("DEATHS NOT DIED : %d", deaths_avoided), scrW/4, (scrH/2)+160, 24, RED);
- DrawText(TextFormat("TIME ALIVE : %d SECONDS", time_alive/60), scrW/4, (scrH/2)+ 192, 24, RED);
- DrawText(TextFormat("SUCKS : FUCKED"), scrW/4, (scrH/2)+224, 24, RED);
- DrawText("[R] TO LIVE AND KILL AGAIN", (scrW/2)-MeasureText("[R] TO LIVE AND KILL AGAIN", 32)/2, (scrH/2)+266, 32, RED);
-}
+#include <cstring>\r
+#include <math.h>\r
+#include <unistd.h>\r
+#include "assteroids.h"\r
+#include "powerups.hpp"\r
+#include "vectormath.hpp"\r
+\r
+void show_death_stats();\r
+void show_instructions();\r
+\r
+Vector2 flatten(Vector4 pV){\r
+ Vector2 stan = {pV.x, pV.y};\r
+ return stan;\r
+}\r
+\r
+Vector4 translate(Vector4 v1, Vector4 v2) {\r
+ Vector4 translation = {v1.x+v2.x, v1.y+v2.y, v1.y+v2.y, v1.z+v2.z};\r
+ return translation;\r
+}\r
+\r
+bool onscreen(Vector2 v) {\r
+ // Ensure v is still onscreen\r
+ return CheckCollisionPointRec(v, screenspace);\r
+}\r
+\r
+void init_ship(){\r
+ ship_alive = true;\r
+ throttle = false;\r
+ score = 0;\r
+ nose.z = 270;\r
+ port.z = 55;\r
+ starboard.z = 125;\r
+ active_powerups = 0;\r
+\r
+ nose.x = 0; nose.y = -15;\r
+ port.x = -10; port.y = 15;\r
+ starboard.x = 10; starboard.y = 15;\r
+ center.x = scrW/2; center.y = scrH/2;\r
+ ship_bearing = 0;\r
+\r
+ memset(bullets, 0, sizeof(Vector4) * MAX_BULLETS);\r
+ memset(asteroids, 0, sizeof(Vector4) * MAX_ASTEROIDS);\r
+ memset(dead_ship, 0, sizeof(Vector4) * SHIP_DEBRIS);\r
+ init_shotgun();\r
+ memset(&shotgun_box, 0, sizeof(Vector4));\r
+ memset(dead_astr, 0, sizeof(Vector4) * SHIP_DEBRIS * MAX_ASTEROIDS);\r
+ memset(&shield_pickup, 0, sizeof(Vector4));\r
+ memset(&bomb_proj, 0, sizeof(Vector4));\r
+ bomb_proj.w = -1;\r
+\r
+ bomb_kills = shotgun_kills = deaths_avoided = time_alive = 0;\r
+}\r
+\r
+void die(){\r
+ ship_alive = false;\r
+ disable_shield();\r
+ for(int i = 0; i < SHIP_DEBRIS; i++) {\r
+ if (!onscreen(flatten(dead_ship[i])))\r
+ continue;\r
+ dead_ship[i].x = center.x; dead_ship[i].y = center.y;\r
+ dead_ship[i].z = (360/SHIP_DEBRIS) * (i + 1);\r
+ dead_ship[i].w = 6;\r
+ }\r
+ disable_shotgun();\r
+\r
+}\r
+\r
+void spin_ship(int az_delta){\r
+ nose.z += az_delta; port.z += az_delta; starboard.z += az_delta;\r
+ nose.x = cos(nose.z * (PI/180)) * 15;\r
+ nose.y = sin(nose.z * (PI/180)) * 15;\r
+\r
+ port.x = cos(port.z * (PI/180)) * 15;\r
+ port.y = sin(port.z * (PI/180)) * 15;\r
+\r
+ starboard.x = cos(starboard.z * (PI/180)) * 15;\r
+ starboard.y = sin(starboard.z * (PI/180)) * 15;\r
+\r
+}\r
+\r
+void update_v4(Vector4* origin, Vector4* v_body, int speed){\r
+ Vector2 heading = v2_normal(flatten(*origin));\r
+ v_body->x += heading.x * (speed*throttle);\r
+ v_body->y += heading.y * (speed*throttle);\r
+}\r
+\r
+void shoot(){\r
+ if(time(NULL) <= last_fire)\r
+ return;\r
+ for(int s = 0; s < 1 + (4 * (active_powerups & SHOTGUN)); s++) {\r
+ for(int i = 0; i < MAX_BULLETS; i++){\r
+ // find available bullet\r
+ if(bullets[i].w == 0) {\r
+ bullets[i].x = center.x;\r
+ bullets[i].y = center.y;\r
+ bullets[i].z = nose.z + bullet_offsets[s];\r
+ bullets[i].w = 1;\r
+ PlaySound(sfx_shoot);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if(active_powerups & SHOTGUN)\r
+ shotgun_blasts--;\r
+ if(shotgun_blasts == 0 && active_powerups & SHOTGUN)\r
+ disable_shotgun();\r
+ time(&last_fire);\r
+}\r
+\r
+void update_bullets(){\r
+ Vector4* b;\r
+ for(int i = 0; i < MAX_BULLETS; i++){\r
+ if(!onscreen(flatten(bullets[i])))\r
+ bullets[i].w = 0;\r
+\r
+ if(bullets[i].w == 1) {\r
+ b = &bullets[i];\r
+ b->x += cos(b->z * (PI/180)) * 15;\r
+ b->y += sin(b->z * (PI/180)) * 15;\r
+ DrawCircleV(flatten(bullets[i]), 2, WHITE);\r
+ for(int a = 0; a < MAX_ASTEROIDS; a++) {\r
+ if(CheckCollisionPointCircle(flatten(bullets[i]), flatten(asteroids[a]), asteroids[a].w)) {\r
+ asteroids[a].w = 0;\r
+ bullets[i].w = 0;\r
+ score++;\r
+ explode_asteroid(&asteroids[a]);\r
+ if((score%15 == 0) && score > 0 && bomb_proj.w == -1) {\r
+ active_powerups |= BOMB;\r
+ }\r
+ if(active_powerups & SHOTGUN) {\r
+ shotgun_kills++;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void spawn_astr() {\r
+ int heading = rand() % 360;\r
+ for(int i = 0; i < MAX_ASTEROIDS; i++){\r
+ // find available asteroid\r
+ // no size means you're fuckin dead, gyro\r
+ if(asteroids[i].w == 0) {\r
+ asteroids[i].z = heading;\r
+ asteroids[i].w = rand() % 34 + 30;\r
+ asteroids[i].x = (heading > 90 && heading < 270) ? scrW : 0;\r
+ asteroids[i].y = (heading > 180 && heading < 360) ? scrH : 0;\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+void explode_ship() {\r
+ for (int i = 0; i < SHIP_DEBRIS; i++) {\r
+ DrawCircleLines(dead_ship[i].x, dead_ship[i].y, dead_ship[i].w, RED);\r
+ dead_ship[i].x += cos(dead_ship[i].z * (PI/180)) *3;\r
+ dead_ship[i].y += sin(dead_ship[i].z * (PI/180)) *3;\r
+ }\r
+}\r
+\r
+bool ship_collision(Vector4* body) {\r
+ return (\r
+ CheckCollisionPointCircle(flatten(translate(nose, center)), flatten(*body), body->w * 0.9f) ||\r
+ CheckCollisionPointCircle(flatten(translate(port, center)), flatten(*body), body->w * 0.9f) ||\r
+ CheckCollisionPointCircle(flatten(translate(starboard, center)), flatten(*body), body->w * 0.9f)\r
+ );\r
+\r
+}\r
+\r
+void update_astrs() {\r
+ Vector4* astr;\r
+ for(int i = 0; i < MAX_ASTEROIDS; i++) {\r
+ astr = &asteroids[i];\r
+ if(astr->w != 0) {\r
+ astr->x += cos(astr->z * (PI/180)) *3;\r
+ astr->y += sin(astr->z * (PI/180)) *3;\r
+ DrawPolyLines(flatten(*astr), 7, astr->w, 0, RAYWHITE);\r
+ }\r
+ if(!onscreen(flatten(*astr))) {\r
+ astr->w = 0;\r
+ }\r
+ if(CheckCollisionCircles(flatten(*astr), astr->w, flatten(bomb_proj), bomb_proj.w) && bomb_proj.w >= 16 && astr->w != 0 && ship_alive) {\r
+ astr->w = 0;\r
+ bomb_proj.z = -1; //stop moving the bomb and explode\r
+ bomb_proj.w +=16;\r
+ explode_asteroid(astr);\r
+ bomb_kills++;\r
+ }\r
+\r
+ if(ship_collision(astr) && ship_alive){\r
+ if((active_powerups & GOD) || debug_nodie) {\r
+ deaths_avoided++;\r
+ continue;\r
+ }\r
+ die();\r
+ }\r
+ }\r
+\r
+}\r
+\r
+int main(int argc, char** argv) {\r
+ int opts;\r
+\r
+ while((opts = getopt(argc, argv, "fsgb")) != -1) {\r
+ switch(opts) {\r
+ case 'f':\r
+ printf("turned on fps counter\n");\r
+ enable_fps = true;\r
+ break;\r
+ case 's':\r
+ debug_nodie = true;\r
+ break;\r
+ case 'g':\r
+ debug_shotgun = true;\r
+ break;\r
+ case 'b':\r
+ debug_bomb = true;\r
+ break;\r
+ case '?':\r
+ default:\r
+ break;\r
+ }\r
+\r
+ }\r
+\r
+ InitAudioDevice();\r
+ if(IsAudioDeviceReady()) {\r
+ sfx_shoot = LoadSound(SFX_SHOOT_FILE);\r
+ sfx_music = LoadSound(SFX_BGM_FILE);\r
+ }\r
+ asteroids = (Vector4*)malloc(sizeof(Vector4)*MAX_ASTEROIDS);\r
+ bullets = (Vector4*)malloc(sizeof(Vector4)*MAX_BULLETS);\r
+ dead_ship = (Vector4*)malloc(sizeof(Vector4) * SHIP_DEBRIS);\r
+\r
+ srand(time(NULL));\r
+ InitWindow(scrW, scrH, "Randy's Rowdy Rocket Roundup");\r
+ SetTargetFPS(50);\r
+ init_ship();\r
+ spin_ship(0);\r
+ while(!WindowShouldClose()){\r
+ BeginDrawing();\r
+ ClearBackground(Space);\r
+\r
+ if(IsKeyPressed('H')) {\r
+ paused = !paused;\r
+ }\r
+ if(paused) {\r
+ show_instructions();\r
+ PauseSound(sfx_music);\r
+ EndDrawing();\r
+ continue;\r
+ }\r
+\r
+ if((IsKeyDown('J') || IsKeyDown(KEY_LEFT)) && ship_alive) {\r
+ spin_ship(-6);\r
+ }\r
+ if((IsKeyDown('L') || IsKeyDown(KEY_RIGHT)) && ship_alive) {\r
+ spin_ship(6);\r
+ }\r
+ if((IsKeyPressed('I') || IsKeyPressed(KEY_UP)) && ship_alive) {\r
+ throttle = true;\r
+ SetSoundVolume(sfx_music, 0.5f);\r
+ }\r
+ if(IsKeyPressed('S') && ship_alive) {\r
+ shoot();\r
+ }\r
+ if(IsKeyPressed('R') && !ship_alive) {\r
+ init_ship();\r
+ spin_ship(0);\r
+ StopSound(sfx_music);\r
+ }\r
+ if(IsKeyPressed('A') && ((active_powerups & BOMB) || debug_bomb)) {\r
+ active_powerups ^= BOMB;\r
+ launch_bomb();\r
+ }\r
+\r
+ if(!onscreen(flatten(center)) && ship_alive)\r
+ die();\r
+\r
+ if(ship_alive) {\r
+ time_alive++;\r
+ update_v4(&nose, ¢er, 4);\r
+ DrawTriangleLines(\r
+ flatten(translate(nose, center)),\r
+ flatten(translate(port, center)),\r
+ flatten(translate(starboard, center)),\r
+ RAYWHITE);\r
+ astr_spawner = rand() & 1000 + 1;\r
+ if(active_powerups & GOD) {\r
+ DrawCircleSectorLines(flatten(center), 3*shield_hp, 0, 360, 6, SKYBLUE);\r
+ DrawCircleSectorLines(flatten(center), 2*shield_hp, 0, 360, 6, SKYBLUE);\r
+ if(time(NULL) > shield_spawn_time) {\r
+ time(&shield_spawn_time);\r
+ shield_hp--;\r
+ }\r
+ if(shield_hp <= 0)\r
+ disable_shield();\r
+ }\r
+ if(bomb_proj.w >= 0)\r
+ update_bomb();\r
+ if(!throttle) {\r
+ DrawText("KILL TO LIVE", (scrW/2)-(MeasureText("KILL TO LIVE", 64)/2), (scrH/2)-128, 64, RED);\r
+ DrawText("LAUNCH TO START", (scrW/2)-(MeasureText("LAUNCH TO START", 32)/2), (scrH/2)+64, 32, RED);\r
+ }\r
+ if(active_powerups & BOMB && bomb_proj.w == -1)\r
+ DrawCircleSectorLines(flatten(translate(nose, center)), 4.0f, 0, 360, 360, RED);\r
+ if(debug_shotgun)\r
+ enable_shotgun();\r
+ } else if(!(active_powerups & GOD)) {\r
+ DrawText("YOU DIED", (scrW/2)-(MeasureText("YOU DIED", 64)/2), (scrH/2)-64, 64, RED);\r
+ DrawText("FUCK YOU", (scrW/2)-(MeasureText("FUCK YOU", 16)/2), (scrH/2)-8, 16, RED);\r
+ explode_ship();\r
+ SetSoundVolume(sfx_music, .1);\r
+ show_death_stats();\r
+ }\r
+ if(throttle && astr_spawner > 989) {\r
+ spawn_astr();\r
+ }\r
+ update_bullets();\r
+ update_astrs();\r
+ update_explosions();\r
+ if(ship_alive && throttle && shotgun_box.w == 0 && (rand() % 10000) < 8 && !active_powerups & SHOTGUN)\r
+ init_shotgun(); //a little treat\r
+ if(shotgun_box.w == 1)\r
+ draw_shotgun();\r
+ if(shield_pickup.w > 0)\r
+ draw_shield_pickup();\r
+ DrawText("[H]elp", (scrW-MeasureText("[H]elp", 32)-32), scrH-34, 32, WHITE);\r
+ DrawText(TextFormat("%d", score), 4, scrH-34, 32, WHITE);\r
+ if(enable_fps)\r
+ DrawFPS(0, 0);\r
+ EndDrawing();\r
+ if(throttle && !IsSoundPlaying(sfx_music)) {\r
+ PlaySound(sfx_music);\r
+ }\r
+\r
+ }\r
+ UnloadSound(sfx_shoot);\r
+ UnloadSound(sfx_music);\r
+\r
+ CloseAudioDevice();\r
+ CloseWindow();\r
+ free(bullets);\r
+ free(asteroids);\r
+ free(dead_ship);\r
+\r
+ return 0;\r
+}\r
+\r
+//spawn a shield pickup at a dead asteroid\r
+void init_shield(Vector4* v) {\r
+ shield_pickup.x = v->x;\r
+ shield_pickup.y = v->y;\r
+ shield_pickup.w = 16;\r
+}\r
+void draw_shield_pickup() {\r
+ DrawRingLines(flatten(shield_pickup), shield_pickup.w, shield_pickup.w * 1.3, 0, 360, 6, SKYBLUE);\r
+ DrawRingLines(flatten(shield_pickup), shield_pickup.w/3, shield_pickup.w * 0.66, 0, 360, 6, SKYBLUE);\r
+ if(CheckCollisionPointCircle(flatten(center), flatten(shield_pickup), shield_pickup.w)) {\r
+ shield_pickup.w = 0;\r
+ enable_shield();\r
+ }\r
+}\r
+\r
+void enable_shield() {\r
+ memset(&shield_pickup, 0, sizeof(Vector4));\r
+ shield_hp = 9;\r
+ active_powerups |= GOD;\r
+ time(&shield_spawn_time);\r
+}\r
+\r
+void disable_shield() {\r
+ active_powerups ^= GOD;\r
+ shield_hp = 9;\r
+}\r
+\r
+void explode_asteroid(Vector4* astr) {\r
+ for(int i = 0; i < MAX_ASTEROIDS; i++) {\r
+ if(dead_astr[i][0].w == 0) {\r
+ for (int a = 0; a < SHIP_DEBRIS; a++) {\r
+ dead_astr[i][a].x = astr->x;\r
+ dead_astr[i][a].y = astr->y;\r
+ dead_astr[i][a].z = ((360/SHIP_DEBRIS) * a) + (360/(SHIP_DEBRIS*3));\r
+ dead_astr[i][a].w = 1;\r
+ }\r
+ if(shield_pickup.w == 0 && rand() % 30 < 2)\r
+ init_shield(astr);\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+void update_explosions() {\r
+ int offscreen_bubbles = 0;\r
+ for(int i = 0; i < MAX_ASTEROIDS; i++) {\r
+ if(dead_astr[i][0].w == 1) {\r
+ for (int a = 0; a < SHIP_DEBRIS; a++) {\r
+ dead_astr[i][a].x += cos(dead_astr[i][a].z * (PI/180)) * 5;\r
+ dead_astr[i][a].y += sin(dead_astr[i][a].z * (PI/180)) * 5;\r
+ DrawCircleLines(dead_astr[i][a].x, dead_astr[i][a].y, 8, RAYWHITE);\r
+ if(!onscreen(flatten(dead_astr[i][a])))\r
+ offscreen_bubbles++;\r
+ if(offscreen_bubbles == SHIP_DEBRIS-1)\r
+ memset(&dead_astr[i], 0, sizeof(Vector4) * SHIP_DEBRIS);\r
+ }\r
+ }\r
+ offscreen_bubbles=0;\r
+ }\r
+\r
+}\r
+\r
+void init_shotgun() {\r
+ int heading = rand() % 360;\r
+ shotgun_box.z = heading;\r
+ shotgun_box.w = 1;\r
+ shotgun_box.x = (heading > 90 && heading < 270) ? scrW : 0;\r
+ shotgun_box.y = (heading > 180 && heading < 360) ? scrH : 0;\r
+\r
+ memcpy(s_top_box, master_s_top_box, sizeof(Vector2)*4); memcpy(s_bot_box, master_s_bot_box, sizeof(Vector2)*4);\r
+ for(int i = 0; i < 4; i++) {\r
+ s_top_box[i].x += shotgun_box.x;\r
+ s_top_box[i].y += shotgun_box.y;\r
+ s_bot_box[i].x += shotgun_box.x;\r
+ s_bot_box[i].y += shotgun_box.y;\r
+ }\r
+}\r
+\r
+void update_shotgun() {\r
+ float xd = cos(shotgun_box.z * (PI/180)) *2;\r
+ float yd = sin(shotgun_box.z * (PI/180)) *2;\r
+ shotgun_box.x += xd;\r
+ shotgun_box.y += yd;\r
+\r
+ for(int i = 0; i < 4; i++) {\r
+ s_top_box[i].x += xd;\r
+ s_top_box[i].y += yd;\r
+ s_bot_box[i].x += xd;\r
+ s_bot_box[i].y += yd;\r
+ }\r
+\r
+ if(!onscreen(flatten(shotgun_box)))\r
+ shotgun_box.w = 0;\r
+ if(CheckCollisionPointCircle(flatten(center), flatten(shotgun_box), 32)) {\r
+ enable_shotgun();\r
+ shotgun_box.w = 0;\r
+ }\r
+}\r
+\r
+void draw_shotgun() {\r
+ update_shotgun();\r
+ DrawLineStrip(s_top_box, 4, WHITE);\r
+ DrawLineStrip(s_bot_box, 4, WHITE);\r
+ DrawText("S", shotgun_box.x-6, shotgun_box.y-8, 20, GOLD);\r
+}\r
+\r
+void launch_bomb() {\r
+ bomb_proj.x = flatten(translate(nose, center)).x;\r
+ bomb_proj.y = flatten(translate(nose, center)).y;\r
+ bomb_proj.z = nose.z;\r
+ bomb_proj.w = 16;\r
+}\r
+\r
+void update_bomb() {\r
+ if(bomb_proj.z != -1) {\r
+ bomb_proj.x += cos(bomb_proj.z * (PI/180)) *6;\r
+ bomb_proj.y += sin(bomb_proj.z * (PI/180)) *6;\r
+ }\r
+ if(bomb_proj.w < 128) {\r
+ DrawPolyLines(flatten(bomb_proj), 8, bomb_proj.w, whrot, DARKPURPLE);\r
+ DrawPolyLines(flatten(bomb_proj), 8, bomb_proj.w * .8, -whrot, DARKPURPLE);\r
+ DrawPolyLines(flatten(bomb_proj), 8, bomb_proj.w * .5, whrot, DARKPURPLE);\r
+ whrot++;\r
+ } else if (bomb_proj.w >= 128 || (!onscreen(flatten(bomb_proj)) && bomb_proj.w != -1)) {\r
+ active_powerups ^= BOMB;\r
+ memset(&bomb_proj, 0, sizeof(Vector4));\r
+ bomb_proj.w = -1;\r
+ }\r
+ if (!onscreen(flatten(bomb_proj))) {\r
+ bomb_proj.w = -1;\r
+ }\r
+}\r
+\r
+void show_instructions() {\r
+ DrawText("I/UP : START", scrW/4, (scrH/2)-256, 32, RED);\r
+ DrawText("J/LEFT : TURN PORT", scrW/4, (scrH/2)-206, 32, RED);\r
+ DrawText("L/RIGHT : TURN STARBOARD", scrW/4, (scrH/2)-156, 32, RED);\r
+ DrawText("S : SHOOT", scrW/4, (scrH/2)-106, 32, RED);\r
+ DrawText("R : RESPAWN", scrW/4, (scrH/2)-56, 32, RED);\r
+ DrawText("A : WORMHOLE", scrW/4, (scrH/2)-6, 32, RED);\r
+ DrawText("H : UN/PAUSE", scrW/4, (scrH/2)+50, 32, RED);\r
+\r
+ DrawText("Thanks raysan for Raylib", scrW/4, (scrH)-34, 16, WHITE);\r
+}\r
+\r
+void show_death_stats() {\r
+ DrawText(TextFormat("KILLS : %d", score), scrW/4, (scrH/2)+64, 24, RED);\r
+ DrawText(TextFormat("SHOTGUN KILLS : %d", shotgun_kills), scrW/4, (scrH/2)+96, 24, RED);\r
+ DrawText(TextFormat("WORMHOLE KILLS : %d", bomb_kills), scrW/4, (scrH/2)+128, 24, RED);\r
+ DrawText(TextFormat("DEATHS NOT DIED : %d", deaths_avoided), scrW/4, (scrH/2)+160, 24, RED);\r
+ DrawText(TextFormat("TIME ALIVE : %d SECONDS", time_alive/60), scrW/4, (scrH/2)+ 192, 24, RED);\r
+ DrawText(TextFormat("SUCKS : FUCKED"), scrW/4, (scrH/2)+224, 24, RED);\r
+ DrawText("[R] TO LIVE AND KILL AGAIN", (scrW/2)-MeasureText("[R] TO LIVE AND KILL AGAIN", 32)/2, (scrH/2)+266, 32, RED);\r
+}\r