#include <stdlib.h>
#include <string.h>
-#include "SFont.h"
+#include "font.h"
#include "args.h"
#include "common.h"
#include "sprite.h"
#include "sound.h"
-#ifdef WIN32
-#define SDL_SetAlpha(surf, flag, alpha)
-#endif
-
// ************************************* VARS
// SDL_Surface global variables
SDL_Surface
*surf_font_big; // The big font
-SFont_Font *g_font;
+font *g_font;
// Structure global variables
struct enginedots edot[MAXENGINEDOTS], *dotptr = edot;
char topline[1024];
char *initerror = "";
-struct ship ship = { SHIP, 0, NULL, XSIZE/2, YSIZE/2, SCREENDXMIN, 0.0 };
+struct ship ship = { SHIP, 0, NULL, XSIZE/2, YSIZE/2, BARRIER_SPEED, 0.0 };
-float screendx = SCREENDXMIN, screendy = 0.0;
-float back_dist;
+float screendx = BARRIER_SPEED, screendy = 0.0;
+float dist_ahead;
// all movement is based on t_frame.
unsigned long frames, start, end;
int ms_frame; // length of this frame (milliseconds)
int ms_end; // end of this frame (milliseconds)
-int bang = false;
-float bangx, bangy, bangdx, bangdy;
+float gamespeed = 1.00;
int score;
-float fadetimer = 0, faderate;
+float fadetimer = 0;
int pausedown = 0, paused = 0;
extern char *optarg;
extern int optind, opterr, optopt;
-#define TO_TICKS(seconds) ((seconds)*20*opt_gamespeed)
+#define TO_TICKS(seconds) ((seconds)*20*gamespeed)
// ************************************* FUNCS
}
void
-new_bang_dots(int xbang, int ybang, int dx, int dy, SDL_Surface *s)
+new_bang_dots(struct sprite *s)
{
int i, n, x, y;
uint16_t *pixel, c;
uint32_t colorkey;
int row_inc;
double theta, r;
+ SDL_Surface *img = s->image;
n = 20;
- pixel = s->pixels;
- row_inc = s->pitch/sizeof(uint16_t) - s->w;
- colorkey = s->format->colorkey;
+ pixel = img->pixels;
+ row_inc = img->pitch/sizeof(uint16_t) - img->w;
+ colorkey = img->format->colorkey;
- if(SDL_MUSTLOCK(s)) { SDL_LockSurface(s); }
+ if(SDL_MUSTLOCK(img)) { SDL_LockSurface(img); }
for(i=0; i<n; i++) {
- pixel = s->pixels;
- for(y=0; y<s->h; y++) {
- for(x = 0; x<s->w; x++) {
+ pixel = img->pixels;
+ for(y=0; y<img->h; y++) {
+ for(x = 0; x<img->w; x++) {
c = *pixel++;
if(c && c != colorkey) {
theta = frnd()*M_PI*2;
r = frnd(); r = 1 - r*r;
- bdot[bd2].dx = 45*r*cos(theta) + dx;
- bdot[bd2].dy = 45*r*sin(theta) + dy;
- bdot[bd2].x = x + xbang;
- bdot[bd2].y = y + ybang;
+ bdot[bd2].dx = 45*r*cos(theta) + s->dx;
+ bdot[bd2].dy = 45*r*sin(theta) + s->dy;
+ bdot[bd2].x = x + s->x;
+ bdot[bd2].y = y + s->y;
//bdot[bd2].c = (i < n-3) ? 0 : c;
bdot[bd2].life = frnd() * 99;
bdot[bd2].decay = frnd()*3 + 1;
}
}
- if(SDL_MUSTLOCK(s)) { SDL_UnlockSurface(s); }
+ if(SDL_MUSTLOCK(img)) { SDL_UnlockSurface(img); }
}
void
// move and clip
bdot[i].x += (bdot[i].dx - screendx)*ticks;
bdot[i].y += (bdot[i].dy - screendy)*ticks;
- if(bdot[i].x < 0 || bdot[i].x >= XSIZE || bdot[i].y < 0 || bdot[i].y >= YSIZE) {
+ if(bdot[i].x < 0 || bdot[i].x >= (XSIZE - 0.000001) || bdot[i].y < 0 || bdot[i].y >= (YSIZE - 0.000001)) {
bdot[i].active = 0;
continue;
}
edot[i].x += (edot[i].dx - screendx)*ticks;
edot[i].y += (edot[i].dy - screendy)*ticks;
edot[i].life -= t_frame*3;
- if(edot[i].life < 0 || edot[i].x<0 || edot[i].x >= XSIZE || edot[i].y < 0 || edot[i].y >= YSIZE) {
+ if(edot[i].life < 0 || edot[i].x<0 || edot[i].x >= (XSIZE - 0.000001) || edot[i].y < 0 || edot[i].y >= (YSIZE - 0.000001)) {
edot[i].active = 0;
continue;
}
load_sprite(SPRITE(&ship), "ship.png");
}
+void font_cleanup() {
+ font_free(g_font);
+}
+
int
init(void) {
// Load the font image
s = add_data_path("font.png");
if(s) {
- NULLERROR(surf_font_big = IMG_Load(s));
- free(s);
- g_font = SFont_InitFont(surf_font_big);
+ g_font = font_load(s);
+ atexit(&font_cleanup);
+ } else {
+ fprintf(stderr, "could create path to font\n");
+ exit(1);
}
init_engine_dots();
int x;
char *text0, *text1;
SDL_Rect dest;
- float a_game = 0, a_over = 0;
-
- // fade in "GAME", then "OVER".
- a_game = min(1.0, faderate*fadetimer/3.0);
- if(a_game == 1.0) a_over = min(1.0, faderate*fadetimer/3.0 - 1);
fadetimer += t_frame;
dest.x = (XSIZE-surf_b_game->w)/2;
dest.y = (YSIZE-surf_b_game->h)/2-40;
- //SDL_SetAlpha(surf_b_game, SDL_SRCALPHA, (int)(a_game*(200 + 55*cos(fadetimer))));
SDL_BlitSurface(surf_b_game,NULL,surf_screen,&dest);
dest.x = (XSIZE-surf_b_over->w)/2;
dest.y = (YSIZE-surf_b_over->h)/2 + 40;
- //SDL_SetAlpha(surf_b_over, SDL_SRCALPHA, (int)(a_over*(200 + 55*sin(fadetimer))));
SDL_BlitSurface(surf_b_over,NULL,surf_screen,&dest);
if(new_high_score(score)) {
text1 = msgs[g_easy][1];
}
- x = (XSIZE-SFont_TextWidth(g_font,text0))/2 + cos(fadetimer/9)*10;
- SFont_Write(surf_screen,g_font,x,YSIZE-100 + cos(fadetimer/6)*5,text0);
+ x = (XSIZE-font_width(text0))/2 + cos(fadetimer/9)*10;
+ font_write(x,YSIZE-100 + cos(fadetimer/6)*5,text0);
- x = (XSIZE-SFont_TextWidth(g_font,text1))/2 + sin(fadetimer/9)*10;
- SFont_Write(surf_screen,g_font,x,YSIZE-50 + sin(fadetimer/4)*5,text1);
+ x = (XSIZE-font_width(text1))/2 + sin(fadetimer/9)*10;
+ font_write(x,YSIZE-50 + sin(fadetimer/4)*5,text1);
}
void
dest.x = (XSIZE-surf_b_variations->w)/2 + cos(fadetimer/6.5)*10;
dest.y = (YSIZE/2-surf_b_variations->h)/2 + sin(fadetimer/5.0)*10;
- //SDL_SetAlpha(surf_b_variations, SDL_SRCALPHA, (int)(200 + 55*sin(fadetimer)));
SDL_BlitSurface(surf_b_variations,NULL,surf_screen,&dest);
dest.x = (XSIZE-surf_b_on->w)/2 + cos((fadetimer + 1.0)/6.5)*10;
dest.y = (YSIZE/2-surf_b_on->h)/2 + surf_b_variations->h + 20 + sin((fadetimer + 1.0)/5.0)*10;
- //SDL_SetAlpha(surf_b_on, SDL_SRCALPHA, (int)(200 + 55*sin(fadetimer-1.0)));
SDL_BlitSurface(surf_b_on,NULL,surf_screen,&dest);
dest.x = (XSIZE-surf_b_rockdodger->w)/2 + cos((fadetimer + 2.0)/6.5)*10;
dest.y = (YSIZE/2-surf_b_rockdodger->h)/2 + surf_b_variations->h + surf_b_on->h + 40 + sin((fadetimer + 2.0)/5)*10;
- //SDL_SetAlpha(surf_b_rockdodger, SDL_SRCALPHA, (int)(200 + 55*sin(fadetimer-2.0)));
SDL_BlitSurface(surf_b_rockdodger,NULL,surf_screen,&dest);
text = msgs[g_easy][(int)(fadetimer/35)%NSEQUENCE];
- x = (XSIZE-SFont_TextWidth(g_font,text))/2 + cos(fadetimer/4.5)*10;
- SFont_Write(surf_screen,g_font,x,YSIZE-100 + cos(fadetimer/3)*5,text);
+ x = (XSIZE-font_width(text))/2 + cos(fadetimer/4.5)*10;
+ font_write(x,YSIZE-100 + cos(fadetimer/3)*5,text);
text = "Version " VERSION;
- x = (XSIZE-SFont_TextWidth(g_font,text))/2 + sin(fadetimer/4.5)*10;
- SFont_Write(surf_screen,g_font,x,YSIZE-50 + sin(fadetimer/2)*5,text);
+ x = (XSIZE-font_width(text))/2 + sin(fadetimer/4.5)*10;
+ font_write(x,YSIZE-50 + sin(fadetimer/2)*5,text);
}
void
-draw(void) {
-
+draw(void)
+{
SDL_FillRect(surf_screen,NULL,0); // black background
- draw_dots(surf_screen); // background dots
+ draw_dots(surf_screen); // background dots
draw_sprite(SPRITE(&ship));
draw_rocks();
show_lives();
show_score();
- // If it's game over, show the game over graphic in the dead centre
switch (state) {
case GAME_OVER: draw_game_over(); break;
case TITLE_PAGE: draw_title_page(); break;
- case HIGH_SCORE_ENTRY:
- play_tune(TUNE_HIGH_SCORE_ENTRY);
- // FALL THROUGH TO
+ case HIGH_SCORE_ENTRY: play_tune(TUNE_HIGH_SCORE_ENTRY);
+ // and fall through to
case HIGH_SCORE_DISPLAY:
// Display de list o high scores mon.
display_scores(surf_screen, 150,50);
; // no action necessary
}
- collisions();
-
// Update the surface
SDL_Flip(surf_screen);
}
static inline void
-kill_ship(Sprite *ship)
+kill_ship(struct ship *ship)
{
- ship->flags = MOVE;
- bang = true;
+ play_sound(SOUND_BANG);
+ new_bang_dots(SPRITE(ship));
+ if(--ship->lives) {
+ state = DEAD_PAUSE;
+ state_timeout = DEAD_PAUSE_LENGTH;
+ // want ship to be invisible, but keep drifting at sqrt(speed)
+ // to leave it in the middle of the space from the explosion.
+ ship->flags = MOVE;
+ 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 < BARRIER_SPEED) ship->dx = BARRIER_SPEED;
+ } else {
+ state = GAME_OVER;
+ state_timeout = 200.0;
+ fadetimer = 0.0;
+ ship->flags = 0;
+ // scrolling is based on the ship speed, so we need to reset it.
+ ship->dx = BARRIER_SPEED; ship->dy = 0;
+ }
}
void
do_collision(Sprite *a, Sprite *b)
{
- if(a->type == SHIP) kill_ship(a);
- else if (b->type == SHIP) kill_ship(b);
+ if(a->type == SHIP) kill_ship((struct ship *)a);
+ else if(b->type == SHIP) kill_ship((struct ship *)b);
else bounce(a, b);
}
if(state_timeout > 0) return;
switch(state) {
+ case GAMEPLAY: break; // no action necessary
case DEAD_PAUSE:
// Restore the ship and continue playing
ship.flags = DRAW|MOVE|COLLIDE;
state = HIGH_SCORE_DISPLAY;
state_timeout = 200.0;
break;
- case GAMEPLAY:
- ; // no action necessary
}
}
for(;;) {
ms_frame = SDL_GetTicks() - ms_end;
ms_end += ms_frame;
- t_frame = opt_gamespeed * ms_frame / 50;
+ if(ms_frame > 1000) {
+ ms_frame = 1000;
+ }
+ t_frame = gamespeed * ms_frame / 50;
frames++;
while(SDL_PollEvent(&e)) {
switch(e.type) {
case SDL_QUIT: return;
- case SDL_KEYUP:
- if(e.key.keysym.sym == SDLK_ESCAPE
- || e.key.keysym.sym == SDLK_q)
- return;
- break;
case SDL_KEYDOWN:
- if(state == HIGH_SCORE_ENTRY)
+ if(state == HIGH_SCORE_ENTRY) {
if(!process_score_input(&e.key.keysym)) {
// Write the high score table to the file
write_high_score_table();
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;
+ }
break;
}
}
if(!paused) {
update_state(t_frame);
- if(state == DEAD_PAUSE && bangx < 60) bangx = 60;
-
// SCROLLING
- tmp = (ship.y+ship.h/2+ship.dy*t_frame-YSCROLLTO)/25 + (ship.dy-screendy);
+ tmp = (ship.y+ship.h/2 + ship.dy*t_frame - YSCROLLTO)/25 + (ship.dy-screendy);
screendy += tmp * t_frame/12;
- tmp = (ship.x+ship.w/2+ship.dx*t_frame-XSCROLLTO)/25 + (ship.dx-screendx);
+ tmp = (ship.x+ship.w/2 + ship.dx*t_frame - XSCROLLTO)/25 + (ship.dx-screendx);
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)
- 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);
-
- // move bang center
- bangx += (bangdx - screendx)*t_frame;
- bangy += (bangdy - screendy)*t_frame;
+ if(dist_ahead + (screendx - BARRIER_SPEED)*TO_TICKS(2) < 0)
+ screendx = BARRIER_SPEED - (dist_ahead/TO_TICKS(2));
+ 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_engine_dots(t_frame);
+ move_sprites(t_frame); new_rocks(t_frame);
+ move_engine_dots(t_frame); new_engine_dots(t_frame);
move_bang_dots(t_frame);
move_dust(t_frame);
+ 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)*opt_bounciness;
+ ship.dx = screendx - (ship.dx-screendx)*BOUNCINESS;
}
// 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;
+ ship.dy = screendy - (ship.dy-screendy)*BOUNCINESS;
}
- new_rocks(t_frame);
- new_engine_dots(t_frame);
-
draw();
- if(state == GAMEPLAY && bang) {
- // Died
- bang = false;
- 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);
-
- 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;
- }
- }
-
// new game
if((keystate[SDLK_SPACE] || keystate[SDLK_1] || keystate[SDLK_2])
&& (state == HIGH_SCORE_DISPLAY
g_easy = 0;
initial_rocks = NORMAL_I_ROCKS;
final_rocks = NORMAL_F_ROCKS;
- if(opt_gamespeed == EASY_GAMESPEED)
- opt_gamespeed = NORMAL_GAMESPEED;
+ if(gamespeed == EASY_GAMESPEED)
+ gamespeed = NORMAL_GAMESPEED;
} else if(keystate[SDLK_1]) {
g_easy = 1;
initial_rocks = EASY_I_ROCKS;
final_rocks = EASY_F_ROCKS;
- opt_gamespeed = EASY_GAMESPEED;
+ gamespeed = EASY_GAMESPEED;
}
reset_sprites();
reset_rocks();
- screendx = SCREENDXMIN; screendy = 0;
+ screendx = BARRIER_SPEED; screendy = 0;
ship.x = XSIZE/2.2; ship.y = YSIZE/2 - ship.w/2;
ship.dx = screendx; ship.dy = screendy;
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;
}