JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
stop busy-waiting while paused
[vor.git] / main.c
diff --git a/main.c b/main.c
index 276cf3a..14a486b 100644 (file)
--- a/main.c
+++ b/main.c
@@ -41,6 +41,7 @@
 #include "score.h"
 #include "sprite.h"
 #include "sound.h"
+#include "autopilot.h"
 
 // ************************************* VARS
 // SDL_Surface global variables
@@ -91,7 +92,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;
@@ -165,7 +166,6 @@ new_engine_dots(void) {
                                dx = r * cos(a);
                                dy = r * -sin(a);  // screen y is "backwards".
 
-                               dotptr->active = 1;
                                dotptr->decay = 3;
                                dotptr->heat = 6;
 
@@ -202,8 +202,14 @@ new_engine_dots(void) {
                                dotptr->x += (dotptr->dx - screendx) * time;
                                dotptr->y += (dotptr->dy - screendy) * time;
 
-                               if(dotptr - edot < MAXENGINEDOTS-1) dotptr++;
-                               else dotptr = edot;
+                               if(!fclip(dotptr->x, XSIZE) && !fclip(dotptr->y, YSIZE)) {
+                                       dotptr->active = 1;
+                                       if(dotptr - edot < MAXENGINEDOTS-1) {
+                                               dotptr++;
+                                       } else {
+                                               dotptr = edot;
+                                       }
+                               }
                        }
                }
        }
@@ -511,16 +517,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
@@ -546,6 +555,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;
@@ -587,7 +597,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();
@@ -619,16 +628,25 @@ gameloop() {
        for(;;) {
                ms_frame = SDL_GetTicks() - ms_end;
                ms_end += ms_frame;
-               if(ms_frame > 100) {
-                       ms_frame = 100;
+               if(ms_frame > 50) {
+                       ms_frame = 50;
                }
                t_frame = gamespeed * ms_frame / 50;
                frames++;
 
-               while(SDL_PollEvent(&e)) {
+               if(opt_autopilot) {
+                       autopilot(t_frame);
+               }
+
+               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
@@ -636,40 +654,61 @@ 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:
+                                                               // FIXME make a unique filename like vor-screenshot-<pid>-<count>.bmp
+                                                               SDL_SaveBMP(surf_screen, "snapshot.bmp");
+                                                               break;
+                                                       case SDLK_p:
+                                                       case SDLK_PAUSE:
+                                                               paused = !paused;
+                                                               if(paused) {
+                                                                       pause_tune();
+                                                               } else {
+                                                                       resume_tune();
+                                                                       ms_end = SDL_GetTicks();
+                                                               }
+                                                               break;
+                                                       default:
+                                                               // other keys are handled by checking keystate each frame
+                                                               break;
+                                               }
                                        }
                                        break;
                        }
                }
                keystate = SDL_GetKeyState(NULL);
+               if(opt_autopilot) {
+                       autopilot_fix_keystates(keystate);
+               }
 
                if(state == GAMEPLAY) {
                        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_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();
+                               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);
                                }
-                       } else {
-                               pausedown = 0;
                        }
+
                }
 
                if(!paused) {
@@ -692,22 +731,26 @@ gameloop() {
                        move_dust();
 
                        new_rocks();
-                       new_engine_dots();
-
-                       collisions();
 
                        // BOUNCE off left or right edge of screen
                        if(ship.x < 0 || ship.x+ship.w > XSIZE) {
                                ship.x -= (ship.dx-screendx)*t_frame;
                                ship.dx = screendx - (ship.dx-screendx)*BOUNCINESS;
+                               ship.x = fconstrain(ship.x, XSIZE - ship.w);
                        }
 
                        // BOUNCE off top or bottom of screen
                        if(ship.y < 0 || ship.y+ship.h > YSIZE) {
                                ship.y -= (ship.dy-screendy)*t_frame;
                                ship.dy = screendy - (ship.dy-screendy)*BOUNCINESS;
+                               ship.y = fconstrain(ship.y, YSIZE - ship.h);
                        }
 
+                       new_engine_dots();
+
+                       collisions(); // must happen after ship bouncing because it puts pixels where the ship is (thus the ship must be on the screen)
+
+
                        draw();
 
                        // new game
@@ -770,7 +813,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;
 }