JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
bump version to 0.5.8
[vor.git] / main.c
diff --git a/main.c b/main.c
index 91af524..0af1fdd 100644 (file)
--- a/main.c
+++ b/main.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #include "font.h"
 
 #include "args.h"
 #include "common.h"
-#include "config.h"
+#include <config.h>
+#include "vorconfig.h"
 #include "dust.h"
 #include "file.h"
 #include "float.h"
@@ -59,6 +61,9 @@ SDL_Surface
 
 font *g_font;
 
+#define ENGINEDOT 0
+#define BANGDOT 1
+
 struct dot {
        int active;
        float x, y;
@@ -66,14 +71,18 @@ struct dot {
        float mass;   // in DOT_MASS_UNITs
        float decay;  // rate at which to reduce mass.
        int heat;     // heat multiplier (color).
+       uint8_t type;  // BANGDOT or ENGINEDOT
 };
 
+void draw(void);
+
 struct dot edot[MAXENGINEDOTS], *dotptr = edot;
 struct dot bdot[MAXBANGDOTS];
 
 // Other global variables
 char topline[1024];
 char *initerror = "";
+int screenshot_number = 0;
 
 struct ship ship = { SHIP, 0, NULL, XSIZE/2, YSIZE/2, BARRIER_SPEED, 0.0 };
          
@@ -92,7 +101,7 @@ int score;
 
 float fadetimer = 0;
 
-int pausedown = 0, paused = 0;
+int paused = 0;
 
 // bangdot start (bd1) and end (bd2) position:
 int bd1 = 0, bd2 = 0;
@@ -113,12 +122,12 @@ char *msgs[2][3] = {
        {
                "Press SPACE for normal game",
                "Press '1' for easy game",
-               "http://jasonwoof.org/vor"
+               "https://sametwice.com/vor"
        },
        {
                "Press SPACE for easy game",
                "Press '2' for normal game",
-               "http://jasonwoof.org/vor"
+               "https://sametwice.com/vor"
        }
 };
 
@@ -133,11 +142,28 @@ extern int optind, opterr, optopt;
 
 // ************************************* FUNCS
 
+#ifdef HAVE_NANOSLEEP
 void
-init_engine_dots() {
+tiny_sleep() {
+       struct timespec t;
+       t.tv_sec = 0;
+       t.tv_nsec = 1;
+       nanosleep(&t, 0);
+}
+#else
+#define tiny_sleep()
+#endif
+
+void
+init_dots() {
        int i;
        for(i = 0; i<MAXENGINEDOTS; i++) {
                edot[i].active = 0;
+               edot[i].type = ENGINEDOT;
+       }
+       for(i = 0; i<MAXBANGDOTS; i++) {
+               bdot[i].active = 0;
+               bdot[i].type = BANGDOT;
        }
 }
 
@@ -261,6 +287,10 @@ new_bang_dots(struct sprite *s)
        if(SDL_MUSTLOCK(img)) { SDL_UnlockSurface(img); }
 }
 
+void
+kill_rock(struct rock *r) {
+       r->x = -200;
+}
 
 void
 move_dot(struct dot *d)
@@ -279,6 +309,13 @@ move_dot(struct dot *d)
                        if(hit) if(hit->type != SHIP) {
                                d->active = 0;
                                mass = sprite_mass(hit);
+                               if(d->type == BANGDOT) {
+                                       struct rock *rock = (struct rock*)hit;
+                                       rock->life -= (d->dx - hit->dx) * (d->dx - hit->dx) + (d->dy - hit->dy) * (d->dy - hit->dy);
+                                       if(rock->life < 0) {
+                                               kill_rock(rock);
+                                       }
+                               }
                                hit->dx += DOT_MASS_UNIT * d->mass * (d->dx - hit->dx) / mass;
                                hit->dy += DOT_MASS_UNIT * d->mass * (d->dy - hit->dy) / mass;
                        }
@@ -347,12 +384,31 @@ void font_cleanup() {
        font_free(g_font);
 }
 
+void
+set_video_mode() {
+       Uint32 flag;
+
+       // Attempt to get the required video size
+       flag = SDL_DOUBLEBUF | SDL_HWSURFACE;
+       if(opt_fullscreen) flag |= SDL_FULLSCREEN;
+       surf_screen = SDL_SetVideoMode(XSIZE,YSIZE,16,flag);
+}
+
+void
+toggle_fullscreen() {
+       opt_fullscreen = 1 - opt_fullscreen;
+       set_video_mode();
+       if(paused) {
+               draw();
+       }
+}
+
+
 int
 init(void) {
 
        int i;
        char *s;
-       Uint32 flag;
 
        // Where are our data files?
        if(!find_files()) exit(1);
@@ -377,10 +433,9 @@ init(void) {
 
        play_tune(TUNE_TITLE_PAGE);
 
+
        // Attempt to get the required video size
-       flag = SDL_DOUBLEBUF | SDL_HWSURFACE;
-       if(opt_fullscreen) flag |= SDL_FULLSCREEN;
-       surf_screen = SDL_SetVideoMode(XSIZE,YSIZE,16,flag);
+       set_video_mode();
 
        // Set the title bar text
        SDL_WM_SetCaption("Variations on Rockdodger", "VoR");
@@ -416,7 +471,7 @@ init(void) {
                exit(1);
        }
 
-       init_engine_dots();
+       init_dots();
        init_dust();
 
        init_sprites();
@@ -500,7 +555,7 @@ draw_title_page(void)
        x = (XSIZE-font_width(text))/2 + cos(fadetimer/4.5)*10;
        font_write(x,YSIZE-100 + cos(fadetimer/3)*5,text);
 
-       text = "Version " VERSION;
+       text = "Version " PACKAGE_VERSION;
        x = (XSIZE-font_width(text))/2 + sin(fadetimer/4.5)*10;
        font_write(x,YSIZE-50 + sin(fadetimer/2)*5,text);
 }
@@ -517,16 +572,19 @@ draw(void)
        show_score();
 
        switch (state) {
-               case GAME_OVER: draw_game_over(); break;
+               case GAME_OVER:
+                       draw_game_over();
+                       break;
 
-               case TITLE_PAGE: draw_title_page(); break;
+               case TITLE_PAGE:
+                       draw_title_page();
+                       break;
 
-               case HIGH_SCORE_ENTRY: play_tune(TUNE_HIGH_SCORE_ENTRY);
-                       // and fall through to
+               case HIGH_SCORE_ENTRY:
                case HIGH_SCORE_DISPLAY:
-                       // Display de list o high scores mon.
                        display_scores(150,50);
                        break;
+
                case GAMEPLAY:
                case DEAD_PAUSE:
                        ; // no action necessary
@@ -552,6 +610,7 @@ kill_ship(struct ship *ship)
                if(ship->dx < BARRIER_SPEED) ship->dx = BARRIER_SPEED;
        } else {
                state = GAME_OVER;
+               play_tune(TUNE_TITLE_PAGE);
                state_timeout = 200.0;
                fadetimer = 0.0;
                ship->flags = 0;
@@ -593,7 +652,6 @@ update_state(void)
                        // Restore the ship and continue playing
                        ship.flags = DRAW|MOVE|COLLIDE;
                        state = GAMEPLAY;
-                       play_tune(TUNE_GAMEPLAY);
                        break;
                case GAME_OVER:
                        if(new_high_score(score)) init_score_entry();
@@ -635,10 +693,15 @@ gameloop() {
                        autopilot(t_frame);
                }
 
-               while(SDL_PollEvent(&e)) {
+               while(paused ? SDL_WaitEvent(&e) : SDL_PollEvent(&e)) {
                        switch(e.type) {
                                case SDL_QUIT: return;
                                case SDL_KEYDOWN:
+                                       // even during high-score entry
+                                       if(e.key.keysym.sym == SDLK_ESCAPE) {
+                                               return;
+                                       }
+
                                        if(state == HIGH_SCORE_ENTRY) {
                                                if(!process_score_input(&e.key.keysym)) {
                                                        // Write the high score table to the file
@@ -646,14 +709,53 @@ gameloop() {
                                                        // continue to display the scores briefly
                                                        state = HIGH_SCORE_DISPLAY;
                                                        state_timeout = 200;
-                                                       play_tune(TUNE_TITLE_PAGE);
                                                }
-                                       } else if(e.key.keysym.sym == SDLK_q) {
-                                               return;
-                                       }
-
-                                       if(e.key.keysym.sym == SDLK_ESCAPE) {
-                                               return;
+                                       } else {
+                                               switch(e.key.keysym.sym) {
+                                                       case SDLK_q:
+                                                               return;
+                                                       case SDLK_3:
+                                                       case SDLK_PRINT:
+                                                               {
+                                                                       FILE *screenshot_fp;
+                                                                       char tmp[30];
+                                                                       char *screenshot_filename = &(tmp[0]);
+                                                                       for(;;) {
+                                                                               snprintf(screenshot_filename, 30, "vor-screenshot-%02i.bmp", screenshot_number++);
+                                                                               screenshot_fp = fopen(screenshot_filename, "r");
+                                                                               if(screenshot_fp) {
+                                                                                       fclose(screenshot_fp);
+                                                                               } else {
+                                                                                       break;
+                                                                               }
+                                                                       }
+                                                                       SDL_SaveBMP(surf_screen, screenshot_filename);
+                                                               }
+                                                               break;
+                                                       case SDLK_SPACE:
+                                                               if(state != GAMEPLAY && state != DEAD_PAUSE) {
+                                                                       // don't conflict with space key to start a new game
+                                                                       break;
+                                                               }
+                                                               // else fall through
+                                                       case SDLK_p:
+                                                       case SDLK_PAUSE:
+                                                               paused = !paused;
+                                                               if(paused) {
+                                                                       pause_tune();
+                                                               } else {
+                                                                       resume_tune();
+                                                                       ms_end = SDL_GetTicks();
+                                                               }
+                                                               break;
+                                                       case SDLK_f:
+                                                       case SDLK_F11:
+                                                               toggle_fullscreen();
+                                                               break;
+                                                       default:
+                                                               // other keys are handled by checking keystate each frame
+                                                               break;
+                                               }
                                        }
                                        break;
                        }
@@ -667,26 +769,24 @@ gameloop() {
                        if(!paused) {
                                score += ms_frame;
                                
-                               if(keystate[SDLK_LEFT]  || keystate[SDLK_h]) { ship.dx -= THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<0;}
-                               if(keystate[SDLK_DOWN]  || keystate[SDLK_t]) { ship.dy += THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<1;}
-                               if(keystate[SDLK_RIGHT] || keystate[SDLK_n]) { ship.dx += THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<2;}
-                               if(keystate[SDLK_UP]    || keystate[SDLK_c]) { ship.dy -= THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<3;}
+                               if(keystate[SDLK_LEFT]  || keystate[SDLK_KP4]) {
+                                       ship.dx -= THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<0;
+                               }
+                               if(keystate[SDLK_DOWN]  || keystate[SDLK_KP5] || keystate[SDLK_KP2]) {
+                                       ship.dy += THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<1;
+                               }
+                               if(keystate[SDLK_RIGHT] || keystate[SDLK_KP6]) {
+                                       ship.dx += THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<2;
+                               }
+                               if(keystate[SDLK_UP]    || keystate[SDLK_KP8]) {
+                                       ship.dy -= THRUSTER_STRENGTH*t_frame; ship.jets |= 1<<3;
+                               }
                                if(ship.jets) {
                                        ship.dx = fconstrain2(ship.dx, -50, 50);
                                        ship.dy = fconstrain2(ship.dy, -50, 50);
                                }
-                               if(keystate[SDLK_3])            { SDL_SaveBMP(surf_screen, "snapshot.bmp"); }
                        }
 
-                       if(keystate[SDLK_p] | keystate[SDLK_s]) {
-                               if(!pausedown) {
-                                       paused = !paused;
-                                       pausedown = 1;
-                                       if(!paused) ms_end = SDL_GetTicks();
-                               }
-                       } else {
-                               pausedown = 0;
-                       }
                }
 
                if(!paused) {
@@ -775,6 +875,8 @@ gameloop() {
                        state = HIGH_SCORE_DISPLAY;
                        state_timeout = 400;
                }
+
+               tiny_sleep();
        }
 }
 
@@ -791,7 +893,7 @@ main(int argc, char **argv) {
        frames = 0;
        gameloop();
        end = SDL_GetTicks();
-       printf("%ld frames in %ld ms, %.2f fps.\n", frames, end-start, frames * 1000.0 / (end-start));
+       // printf("%ld frames in %ld ms, %.2f fps.\n", frames, end-start, frames * 1000.0 / (end-start));
 
        return 0;
 }