char topline[1024];
char *initerror = "";
-struct ship ship = { SHIP, NULL, XSIZE/2, YSIZE/2, SCREENDXMIN, 0.0 };
+struct ship ship = { SHIP, 0, NULL, XSIZE/2, YSIZE/2, SCREENDXMIN, 0.0 };
float screendx = SCREENDXMIN, screendy = 0.0;
-float xscroll, yscroll;
float back_dist;
// all movement is based on t_frame.
if(bdot[i].life<0) { bdot[i].active = 0; continue; }
// move and clip
- bdot[i].x += bdot[i].dx*t_frame - xscroll;
- bdot[i].y += bdot[i].dy*t_frame - yscroll;
+ bdot[i].x += (bdot[i].dx - screendx)*t_frame;
+ bdot[i].y += (bdot[i].dy - screendy)*t_frame;
if(bdot[i].x < 0 || bdot[i].x >= XSIZE || bdot[i].y < 0 || bdot[i].y >= YSIZE) {
bdot[i].active = 0;
continue;
for(i = 0; i<MAXENGINEDOTS; i++) {
if(!edot[i].active) continue;
- edot[i].x += edot[i].dx*t_frame - xscroll;
- edot[i].y += edot[i].dy*t_frame - yscroll;
+ edot[i].x += (edot[i].dx - screendx)*t_frame;
+ edot[i].y += (edot[i].dy - screendy)*t_frame;
edot[i].life -= t_frame*3;
if(edot[i].life < 0
|| edot[i].x<0 || edot[i].x >= XSIZE
}
void
-draw(void) {
+show_lives(void)
+{
int i;
SDL_Rect dest;
+
+ for(i=0; i<ship.lives-1; i++) {
+ dest.x = (i + 1)*(surf_life->w + 10);
+ dest.y = 20;
+ SDL_BlitSurface(surf_life, NULL, surf_screen, &dest);
+ }
+}
+
+void
+draw(void) {
+ SDL_Rect dest;
int x;
char *text;
float fadegame,fadeover;
- // Draw a fully black background
- SDL_FillRect(surf_screen,NULL,0);
-
- // Draw the background dots
- drawdots(surf_screen);
-
- // Draw ship
- if(state == GAMEPLAY) draw_sprite(SPRITE(&ship));
-
+ SDL_FillRect(surf_screen,NULL,0); // black background
+ drawdots(surf_screen); // background dots
+ draw_sprite(SPRITE(&ship));
draw_rocks();
- // Draw the life indicators.
- if(state == GAMEPLAY || state == DEAD_PAUSE || state == GAME_OVER) {
- for(i = 0; i<ship.lives-1; i++) {
- dest.x = (i + 1)*(surf_life->w + 10);
- dest.y = 20;
- SDL_BlitSurface(surf_life, NULL, surf_screen, &dest);
- }
- }
-
- // Draw the score
- snprintscore_line(topline, 50, score);
- SFont_Write(surf_screen, g_font, XSIZE-250, 0, topline);
+ show_lives();
+ show_score();
// If it's game over, show the game over graphic in the dead centre
switch (state) {
ms_frame = SDL_GetTicks() - ms_end;
ms_end += ms_frame;
- if(ms_frame>200 || ms_frame<0) {
- // We won't run at all below 5 frames per second.
- // This also happens if we were paused, grr.
- t_frame = 0;
- ms_frame = 0;
- } else {
- t_frame = opt_gamespeed * ms_frame / 50;
- if(state == GAMEPLAY) score += ms_frame;
- }
+ t_frame = opt_gamespeed * ms_frame / 50;
+ if(state == GAMEPLAY) score += ms_frame;
// Update the surface
SDL_Flip(surf_screen);
}
+static inline void
+kill_ship(Sprite *ship)
+{
+ ship->flags = MOVE|DRAW;
+ SDL_SetAlpha(ship->image, SDL_SRCALPHA, 0);
+ bang = true;
+}
+
void
do_collision(Sprite *a, Sprite *b)
{
- if(a->type == SHIP) {
- a->type = -SHIP; bang = true;
- } else if (b->type == SHIP) {
- b->type = -SHIP; bang = true;
- } else {
- bounce(a, b);
- }
+ if(a->type == SHIP) kill_ship(a);
+ else if (b->type == SHIP) kill_ship(b);
+ else bounce(a, b);
}
-int
+void
+init_score_entry(void)
+{
+ SDL_Event e;
+ state = HIGH_SCORE_ENTRY;
+ state_timeout = 5.0e6;
+ SDL_EnableUNICODE(1);
+ while(SDL_PollEvent(&e))
+ ;
+}
+
+void
gameloop() {
Uint8 *keystate = SDL_GetKeyState(NULL);
float tmp;
for(;;) {
+ SDL_PumpEvents();
+ keystate = SDL_GetKeyState(NULL);
+
if(!paused) {
// Count down the game loop timer, and change state when it gets to zero or less;
if((state_timeout -= t_frame*3) < 0) {
switch(state) {
case DEAD_PAUSE:
- // Create a new ship and start all over again
- ship.sprite_type = SHIP;
+ // 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)) {
- SDL_Event e;
- state = HIGH_SCORE_ENTRY;
- state_timeout = 5.0e6;
- SDL_EnableUNICODE(1);
- while(SDL_PollEvent(&e))
- ;
- } else if(!keystate[SDLK_SPACE]) {
+ if(new_high_score(score)) init_score_entry();
+ else {
state = HIGH_SCORE_DISPLAY;
state_timeout = 400;
}
}
} else {
if(state == DEAD_PAUSE) {
- float blast_radius;
+ float blast_radius, alpha;
if(state_timeout >= DEAD_PAUSE_LENGTH - 20.0) {
blast_radius = BLAST_RADIUS * (DEAD_PAUSE_LENGTH - state_timeout) / 20.0;
blast_rocks(bangx, bangy, blast_radius);
}
if(bangx < 60) bangx = 60;
+
+ alpha = 255.0 * (DEAD_PAUSE_LENGTH - state_timeout) / DEAD_PAUSE_LENGTH;
+ SDL_SetAlpha(ship.image, SDL_SRCALPHA, (uint8_t)alpha);
}
}
screendx += tmp * t_frame/12;
// taper off so we don't hit the barrier abruptly.
// (if we would hit in < 2 seconds, adjust to 2 seconds).
- if(back_dist + (screendx - SCREENDXMIN)*TO_TICKS(2) < 0) {
+ if(back_dist + (screendx - SCREENDXMIN)*TO_TICKS(2) < 0)
screendx = SCREENDXMIN - (back_dist/TO_TICKS(2));
- }
-
back_dist += (screendx - SCREENDXMIN)*t_frame;
if(opt_max_lead >= 0) back_dist = min(back_dist, opt_max_lead);
- xscroll = screendx * t_frame;
- yscroll = screendy * t_frame;
-
// move bang center
- bangx += bangdx*t_frame - xscroll;
- bangy += bangdy*t_frame - yscroll;
+ bangx += (bangdx - screendx)*t_frame;
+ bangy += (bangdy - screendy)*t_frame;
move_sprites();
- // BOUNCE X
- if(ship.x<0 || ship.x>XSIZE-ship.image->w) {
- // BOUNCE from left and right wall
+ // 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)*opt_bounciness;
}
- // BOUNCE Y
- if(ship.y<0 || ship.y>YSIZE-ship.image->h) {
- // BOUNCE from top and bottom wall
+ // 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)*opt_bounciness;
}
play_sound(SOUND_BANG); // Play the explosion sound
bangx = ship.x; bangy = ship.y; bangdx = ship.dx; bangdy = ship.dy;
new_bang_dots(ship.x,ship.y,ship.dx,ship.dy,ship.image);
- ship.dx *= 0.5; ship.dy *= 0.5;
- if(ship.dx < SCREENDXMIN) ship.dx = SCREENDXMIN;
- if(--ship.lives <= 0) {
+
+ if(--ship.lives) {
+ state = DEAD_PAUSE;
+ state_timeout = DEAD_PAUSE_LENGTH;
+ ship.dx = (ship.dx < 0) ? -sqrt(-ship.dx) : sqrt(ship.dx);
+ ship.dy = (ship.dy < 0) ? -sqrt(-ship.dy) : sqrt(ship.dy);
+ if(ship.dx < SCREENDXMIN) ship.dx = SCREENDXMIN;
+ } else {
state = GAME_OVER;
ship.dx = SCREENDXMIN; ship.dy = 0;
state_timeout = 200.0;
fadetimer = 0.0;
faderate = t_frame;
- } else {
- state = DEAD_PAUSE;
- state_timeout = DEAD_PAUSE_LENGTH;
}
}
- SDL_PumpEvents();
- keystate = SDL_GetKeyState(NULL);
-
// new game
- if(keystate[SDLK_SPACE] && (state == HIGH_SCORE_DISPLAY || state == TITLE_PAGE)) {
- reset_sprites();
- reset_rocks();
-
- ship.x = XSIZE/2.2; ship.y = YSIZE/2;
- ship.dx = screendx; ship.dy = screendy;
- ship.lives = 4;
- add_sprite(SPRITE(&ship));
-
- score = 0;
-
- state = GAMEPLAY;
- play_tune(TUNE_GAMEPLAY);
+ if(keystate[SDLK_SPACE]
+ && (state == HIGH_SCORE_DISPLAY
+ || state == TITLE_PAGE
+ || state == GAME_OVER)) {
+ if(state == GAME_OVER && new_high_score(score))
+ init_score_entry();
+ else {
+ reset_sprites();
+ reset_rocks();
+ screendx = SCREENDXMIN; screendy = 0;
+
+ ship.x = XSIZE/2.2; ship.y = YSIZE/2;
+ ship.dx = screendx; ship.dy = screendy;
+ ship.lives = 4;
+ ship.flags = MOVE|DRAW|COLLIDE;
+ SDL_SetAlpha(ship.image, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
+ add_sprite(SPRITE(&ship));
+
+ score = 0;
+
+ state = GAMEPLAY;
+ play_tune(TUNE_GAMEPLAY);
+ }
}
ship.jets = 0;
- } else {
- SDL_PumpEvents();
- keystate = SDL_GetKeyState(NULL);
}
if(state == GAMEPLAY) {
if(!pausedown) {
paused = !paused;
pausedown = 1;
+ if(!paused) ms_end = SDL_GetTicks();
}
} else {
pausedown = 0;
}
- } else if(state == GAME_OVER) {
- if(keystate[SDLK_SPACE]) {
- state_timeout = -1;
- }
}
- if(state != HIGH_SCORE_ENTRY && (keystate[SDLK_q] || keystate[SDLK_ESCAPE])) {
- return 0;
- }
+ if(state != HIGH_SCORE_ENTRY && (keystate[SDLK_q] || keystate[SDLK_ESCAPE]))
+ return;
}
}