JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
* main.c: wrapped call to autopilot_fix_keystates.
[vor.git] / main.c
diff --git a/main.c b/main.c
index f69b5dc..91af524 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
@@ -64,6 +65,7 @@ struct dot {
        float dx, dy;
        float mass;   // in DOT_MASS_UNITs
        float decay;  // rate at which to reduce mass.
+       int heat;     // heat multiplier (color).
 };
 
 struct dot edot[MAXENGINEDOTS], *dotptr = edot;
@@ -141,9 +143,9 @@ init_engine_dots() {
 
 
 void
-new_engine_dots(float time_span) {
+new_engine_dots(void) {
        int dir, i;
-       int n = time_span * ENGINE_DOTS_PER_TIC;
+       int n = t_frame * ENGINE_DOTS_PER_TIC;
        float a, r;  // angle, random length
        float dx, dy;
        float hx, hy; // half ship width/height.
@@ -164,11 +166,11 @@ new_engine_dots(float time_span) {
                                dx = r * cos(a);
                                dy = r * -sin(a);  // screen y is "backwards".
 
-                               dotptr->active = 1;
                                dotptr->decay = 3;
+                               dotptr->heat = 6;
 
                                // dot was created at a random time during the time span
-                               time = frnd() * time_span; // this is how long ago
+                               time = frnd() * t_frame; // this is how long ago
 
                                // calculate how fast the ship was going when this engine dot was
                                // created (as if it had a smooth acceleration). This is used in
@@ -183,7 +185,7 @@ new_engine_dots(float time_span) {
 
                                // the starting position (not speed) of the dot is calculated as
                                // though the ship were traveling at a constant speed for this
-                               // time_span.
+                               // t_frame.
                                dotptr->x = (ship.x - (ship.dx - screendx) * time) + s[dir]*hx;
                                dotptr->y = (ship.y - (ship.dy - screendy) * time) + s[(dir+1)&3]*hy;
                                if(dir&1) {
@@ -200,8 +202,14 @@ new_engine_dots(float time_span) {
                                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;
+                                       }
+                               }
                        }
                }
        }
@@ -240,6 +248,7 @@ new_bang_dots(struct sprite *s)
                                        bdot[bd2].y = y + s->y;
                                        bdot[bd2].mass = frnd() * 99;
                                        bdot[bd2].decay = frnd()*1.5 + 0.5;
+                                       bdot[bd2].heat = 3;
                                        bdot[bd2].active = 1;
 
                                        bd2 = (bd2+1) % MAXBANGDOTS;
@@ -254,78 +263,62 @@ new_bang_dots(struct sprite *s)
 
 
 void
-move_dot(struct dot *d, float ticks)
+move_dot(struct dot *d)
 {
        Sprite *hit;
        float mass;
 
        if(d->active) {
-               d->x += (d->dx - screendx) * ticks;
-               d->y += (d->dy - screendy) * ticks;
-               d->mass -= ticks * d->decay;
+               d->x += (d->dx - screendx) * t_frame;
+               d->y += (d->dy - screendy) * t_frame;
+               d->mass -= t_frame * d->decay;
                if(d->mass < 0 || fclip(d->x, XSIZE) || fclip(d->y, YSIZE))
                        d->active = 0; 
                else {
                        hit = pixel_collides(d->x, d->y);
-                       if(hit && hit->type != SHIP) {
+                       if(hit) if(hit->type != SHIP) {
                                d->active = 0;
                                mass = sprite_mass(hit);
-                               hit->dx += DOT_MASS_UNIT * d->mass * d->dx / mass;
-                               hit->dy += DOT_MASS_UNIT * d->mass * d->dy / mass;
+                               hit->dx += DOT_MASS_UNIT * d->mass * (d->dx - hit->dx) / mass;
+                               hit->dy += DOT_MASS_UNIT * d->mass * (d->dy - hit->dy) / mass;
                        }
                }
        }
 }
 
 void
-move_dots(float ticks)
+move_dots(void)
 {
        int i;
 
-       for(i=0; i<MAXBANGDOTS; i++) move_dot(&bdot[i], ticks);
-       for(i=0; i<MAXENGINEDOTS; i++) move_dot(&edot[i], ticks);
+       for(i=0; i<MAXBANGDOTS; i++) move_dot(&bdot[i]);
+       for(i=0; i<MAXENGINEDOTS; i++) move_dot(&edot[i]);
 }
 
 
 void
-draw_bang_dots(SDL_Surface *s)
+draw_dot(struct dot *d)
 {
-       int i;
        uint16_t *pixels, *pixel;
-       int row_inc = s->pitch/sizeof(uint16_t);
-
-       pixels = (uint16_t *) s->pixels;
+       int row_inc;
 
-       for(i=0; i<MAXBANGDOTS; i++) {
-               if(!bdot[i].active) continue;
-               pixel = pixels + row_inc*(int)(bdot[i].y) + (int)(bdot[i].x);
-               *pixel = heatcolor[(int)(bdot[i].mass)*3];
+       if(d->active) {
+               pixels = (uint16_t *) surf_screen->pixels;
+               row_inc = surf_screen->pitch / sizeof(uint16_t);
+               pixel = pixels + (int)d->y * row_inc + (int)d->x;
+               *pixel = heatcolor[min(3*W-1, (int)(d->mass * d->heat))];
        }
 }
 
 void
-draw_engine_dots(SDL_Surface *s)
-{
+draw_dots(void) {
        int i;
-       uint16_t *pixels, *pixel;
-       int row_inc = s->pitch/sizeof(uint16_t);
-
-       pixels = (uint16_t *) s->pixels;
-
-       for(i = 0; i<MAXENGINEDOTS; i++) {
-               if(!edot[i].active) continue;
-               pixel = pixels + row_inc*(int)(edot[i].y) + (int)(edot[i].x);
-               *pixel = heatcolor[min(3*W-1, (int)(edot[i].mass)*6)];
-       }
-}
 
-void
-draw_dots(SDL_Surface *s) {
-       if(SDL_MUSTLOCK(s)) { SDL_LockSurface(s); }
-       draw_dust(s);
-       draw_engine_dots(s);
-       draw_bang_dots(s);
-       if(SDL_MUSTLOCK(s)) { SDL_UnlockSurface(s); }
+       if(SDL_MUSTLOCK(surf_screen)) { SDL_LockSurface(surf_screen); }
+       draw_dust();
+       for(i=0; i<MAXBANGDOTS; i++) draw_dot(&bdot[i]);
+       for(i=0; i<MAXENGINEDOTS; i++) draw_dot(&edot[i]);
+       if(SDL_MUSTLOCK(surf_screen)) { SDL_UnlockSurface(surf_screen); }
 }
 
 SDL_Surface *
@@ -516,7 +509,7 @@ void
 draw(void)
 {
        SDL_FillRect(surf_screen,NULL,0);  // black background
-       draw_dots(surf_screen);            // background dots
+       draw_dots();            // background dots
        draw_sprite(SPRITE(&ship));
        draw_rocks();
 
@@ -532,7 +525,7 @@ draw(void)
                        // and fall through to
                case HIGH_SCORE_DISPLAY:
                        // Display de list o high scores mon.
-                       display_scores(surf_screen, 150,50);
+                       display_scores(150,50);
                        break;
                case GAMEPLAY:
                case DEAD_PAUSE:
@@ -589,9 +582,9 @@ init_score_entry(void)
 
 // Count down the state timer, and change state when it gets to zero or less;
 void
-update_state(float ticks)
+update_state(void)
 {
-       state_timeout -= ticks*3;
+       state_timeout -= t_frame*3;
        if(state_timeout > 0) return;
 
        switch(state) {
@@ -632,12 +625,16 @@ gameloop() {
        for(;;) {
                ms_frame = SDL_GetTicks() - ms_end;
                ms_end += ms_frame;
-               if(ms_frame > 1000) {
-                       ms_frame = 1000;
+               if(ms_frame > 50) {
+                       ms_frame = 50;
                }
                t_frame = gamespeed * ms_frame / 50;
                frames++;
 
+               if(opt_autopilot) {
+                       autopilot(t_frame);
+               }
+
                while(SDL_PollEvent(&e)) {
                        switch(e.type) {
                                case SDL_QUIT: return;
@@ -662,6 +659,9 @@ gameloop() {
                        }
                }
                keystate = SDL_GetKeyState(NULL);
+               if(opt_autopilot) {
+                       autopilot_fix_keystates(keystate);
+               }
 
                if(state == GAMEPLAY) {
                        if(!paused) {
@@ -671,6 +671,10 @@ gameloop() {
                                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(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"); }
                        }
 
@@ -686,7 +690,7 @@ gameloop() {
                }
 
                if(!paused) {
-                       update_state(t_frame);
+                       update_state();
 
                        // SCROLLING
                        tmp = (ship.y+ship.h/2 + ship.dy*t_frame - YSCROLLTO)/25 + (ship.dy-screendy);
@@ -700,27 +704,31 @@ gameloop() {
                        dist_ahead += (screendx - BARRIER_SPEED)*t_frame;
                        if(MAX_DIST_AHEAD >= 0) dist_ahead = min(dist_ahead, MAX_DIST_AHEAD);
 
-                       move_sprites(t_frame);
-                       move_dots(t_frame);
-                       move_dust(t_frame);
-
-                       new_rocks(t_frame);
-                       new_engine_dots(t_frame);
+                       move_sprites();
+                       move_dots();
+                       move_dust();
 
-                       collisions();
+                       new_rocks();
 
                        // 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
@@ -783,7 +791,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;
 }