X-Git-Url: https://jasonwoof.com/gitweb/?p=vor.git;a=blobdiff_plain;f=main.c;h=78c2ca03e42865ed88460fc4d4f61e086510c2f6;hp=fe58efa5bd1fc77f430c2f31b97c80b5e4ea38a6;hb=0ebbb01f731d0c9bb71140a93cfddd9abde509e5;hpb=0843e88374798bd0fc6a4da2a85b8cc0f3d0f356 diff --git a/main.c b/main.c index fe58efa..78c2ca0 100644 --- a/main.c +++ b/main.c @@ -24,41 +24,23 @@ extern int font_height; void clearBuffer(); -// includes {{{ +#include "config.h" +#include "file.h" +#include "sound.h" + +#include #include #include +#include #include #include #include -#include -#include - -#include -#include #include #include "SFont.h" -// }}} -// constants {{{ -#define XSIZE 640 -#define YSIZE 480 -#define NROCKS 6 // Number of rock image files, not number of rocks visible -#define MAXROCKS 120 // MAX Rocks -#define MAXROCKHEIGHT 100 -#define ROCKRATE 2 -#define MAXBLACKPOINTS 500 -#define MAXENGINEDOTS 5000 -#define MAXBANGDOTS 50000 -#define MAXSPACEDOTS 2000 -#define W 100 -#define M 255 -#define BIG_FONT_FILE "fonts/score.png" -#define STARTSPACE 430 // pixels from the left which will be cleared of rocks when you die -// }}} -// macros {{{ + #define CONDERROR(a) if((a)) {initerror = strdup(SDL_GetError());return 1;} #define NULLERROR(a) CONDERROR((a) == NULL) -// }}} // ************************************* STRUCTS struct rock_struct { @@ -67,9 +49,10 @@ struct rock_struct { // soon as it isn't we BLOW UP float x,y,xvel,yvel; int active; + int dead; // has been blown out of the way + // to make room for a new ship appearing. SDL_Surface *image; int type_number; - float heat; }; struct black_point_struct { int x,y; @@ -98,7 +81,7 @@ struct spacedot { float x,y,dx; Uint16 color; }; -// High score table {{{ +// High score table struct highscore { int score; char *name; @@ -113,10 +96,9 @@ struct highscore { {2000,"Pad",0}, {1500,"Pad",0} }; -// }}} // ************************************* VARS -// SDL_Surface global variables {{{ +// SDL_Surface global variables SDL_Surface *surf_screen, // Screen *surf_b_variations, // "variations" banner @@ -129,15 +111,15 @@ SDL_Surface *surf_rock[NROCKS], // THE ROCKS *surf_deadrock[NROCKS], // THE DEAD ROCKS *surf_font_big; // The big font -// }}} -// Structure global variables {{{ + +// Structure global variables struct enginedots edot[MAXENGINEDOTS], *dotptr = edot; struct rock_struct rock[MAXROCKS], *rockptr = rock; struct black_point_struct black_point[MAXBLACKPOINTS], *blackptr = black_point; struct bangdots bdot[MAXBANGDOTS], *bdotptr = bdot; struct spacedot sdot[MAXSPACEDOTS]; -// }}} -// Other global variables {{{ + +// Other global variables char topline[1024]; char *initerror = ""; char name[1024], debug1[1024]; @@ -146,16 +128,14 @@ float xship,yship = 240.0; // X position, 0..XSIZE float xvel,yvel; // Change in X position per tick. float rockrate,rockspeed; float movementrate; -float shieldlevel, shieldpulse = 0; float yscroll; +float scrollvel; int nships,score,initticks,ticks_since_last, last_ticks; -int initialshield, gameover, fast; +int gameover; int countdown = 0; int maneuver = 0; -int laser = 0; -int shieldsup = 0; -int oss_sound_flag = 0; +int sound_flag = 1, music_flag = 0; int tail_plume = 0; // display big engine at the back? int friction = 0; // should there be friction? int scorerank; @@ -194,61 +174,21 @@ Uint16 heatcolor[W*3]; char *data_dir; extern char *optarg; extern int optind, opterr, optopt; -// }}} -// ************************************* FUNCS -#ifdef DOTCOLLISION -int dotcollision(SDL_Surface *s) { - int i,j,m; - Uint16 *rawpixel, *r; - - /* - * Kill all the dots which collide with other objects. - * This does not work, it's probably in the wrong place or something. - */ - SDL_LockSurface(s); - rawpixel = (Uint16 *) s->pixels; - if(bangdotlife > 0 && bangdotlife<80) { - for(i = 0; i0 && bdot[i].x0 && bdot[i].ypitch/2*(int)(bdot[i].y)) + (int)(bdot[i].x)]; - if(*r != (bdot[i].c ? bdot[i].c : heatcolor[bangdotlife*2])) - bdot[i].active = 0; - } - } - } - SDL_UnlockSurface(s); - - return; +float dist_sq(float x1, float y1, float x2, float y2) +{ + return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1); } -#endif -FILE *hs_fopen(char *mode) { - FILE *f; - mode_t mask; - mask = umask(0111); - if(f = fopen("/usr/share/vor/.highscore",mode)) { - umask(mask); - return f; - } - else { - char s[1024]; - umask(0177); - sprintf(s,"%s/.vor-high",getenv("HOME")); - if(f = fopen(s,mode)) { - umask(mask); - return f; - } - else { - umask(mask); - return 0; - } - } -} -void read_high_score_table() { +// ************************************* FUNCS + +void +read_high_score_table() { FILE *f; int i; - if(f = hs_fopen("r")) { + + f = open_score_file("r"); + if(f) { // If the file exists, read from it for(i = 0; i<8; i++) { char s[1024]; @@ -266,10 +206,14 @@ void read_high_score_table() { fclose(f); } } -void write_high_score_table() { + +void +write_high_score_table() { FILE *f; int i; - if(f = hs_fopen("w")) { + + f = open_score_file("w"); + if(f) { // If the file exists, write to it for(i = 0; i<8; i++) { fprintf (f, "%d %s\n", high[i].score, high[i].name); @@ -277,7 +221,9 @@ void write_high_score_table() { fclose(f); } } -void snprintscore(char *s, size_t n, int score) { + +void +snprintscore(char *s, size_t n, int score) { int min = score/60000; int sec = score/1000%60; int tenths = score%1000/100; @@ -287,16 +233,22 @@ void snprintscore(char *s, size_t n, int score) { snprintf(s, n, " %2d.%d", sec, tenths); } } -float rnd() { + +float +rnd() { return (float)random()/(float)RAND_MAX; } -void init_engine_dots() { + +void +init_engine_dots() { int i; for(i = 0; irock[i].y && yship + 12h && xship + 32w/2) && rock[i].x + (rock[i].image->w/2) < xc) { - xc = rock[i].x + (rock[i].image->w/2); - hitrock = i; - } - } - } - - if(hitrock >= 0) { - rock[hitrock].heat += movementrate*3; - } - - // Plot a number of random dots between xship and XSIZE - SDL_LockSurface(surf_screen); - rawpixel = (Uint16 *) surf_screen->pixels; - c = SDL_MapRGB(surf_ship->format,rnd()*128,128 + rnd()*120,rnd()*128); - - for(i = 0; i<(xc-xship)*5; i += 10) { - int x,y; - x = rnd()*(xc-(xship + 32)) + xship + 32; - y = yship + 12 + (rnd()-0.5)*1.5; - rawpixel[surf_screen->pitch/2*y + x] = c; - } - - SDL_UnlockSurface(surf_screen); -} - - -int makebangdots(int xbang, int ybang, int xvel, int yvel, SDL_Surface *s, int power) { +void +makebangdots(int xbang, int ybang, int xvel, int yvel, SDL_Surface *s, int power) { // TODO - stop generating dots after a certain amount of time has passed, to cope with slower CPUs. // TODO - generate and display dots in a circular buffer - int i,x,y,n,endcount; + int x,y,endcount; Uint16 *rawpixel,c; - double theta,r,dx,dy; + double theta,r; int begin_generate; begin_generate = SDL_GetTicks(); @@ -370,47 +286,45 @@ int makebangdots(int xbang, int ybang, int xvel, int yvel, SDL_Surface *s, int p endcount = 0; while (endcount<3) { + for(x = 0; xw; x++) { + for(y = 0; yh; y++) { + c = rawpixel[s->pitch/2*y + x]; + if(c && c != SDL_MapRGB(s->format,0,255,0)) { - for(x = 0; xw; x++) { - for(y = 0; yh; y++) { - c = rawpixel[s->pitch/2*y + x]; - if(c && c != SDL_MapRGB(s->format,0,255,0)) { - - theta = rnd()*M_PI*2; + theta = rnd()*M_PI*2; - r = 1-(rnd()*rnd()); + r = 1-(rnd()*rnd()); - bdot[bd2].dx = (power/50.0)*45.0*cos(theta)*r + xvel; - bdot[bd2].dy = (power/50.0)*45.0*sin(theta)*r + yvel; - bdot[bd2].x = x + xbang; - bdot[bd2].y = y + ybang; + bdot[bd2].dx = (power/50.0)*45.0*cos(theta)*r + xvel; + bdot[bd2].dy = (power/50.0)*45.0*sin(theta)*r + yvel; + bdot[bd2].x = x + xbang; + bdot[bd2].y = y + ybang; - // Replace the last few bang dots with the pixels from the exploding object - bdot[bd2].c = (endcount>0)?c:0; - bdot[bd2].life = 100; - bdot[bd2].decay = rnd()*3 + 1; - bdot[bd2].active = 1; + // Replace the last few bang dots with the pixels from the exploding object + bdot[bd2].c = (endcount>0)?c:0; + bdot[bd2].life = 100; + bdot[bd2].decay = rnd()*3 + 1; + bdot[bd2].active = 1; - bd2++; - bd2 %= MAXBANGDOTS; + bd2++; + bd2 %= MAXBANGDOTS; - // If the circular buffer is filled, who cares? They've had their chance. - //if(bd2 == bd1-1) goto exitloop; + // If the circular buffer is filled, who cares? They've had their chance. + //if(bd2 == bd1-1) goto exitloop; + } } } - } - - if(SDL_GetTicks() - begin_generate > 7) endcount++; + if(SDL_GetTicks() - begin_generate > 7) endcount++; } -exitloop: SDL_UnlockSurface(s); } -void draw_bang_dots(SDL_Surface *s) { +void +draw_bang_dots(SDL_Surface *s) { int i; int first_i, last_i; Uint16 *rawpixel; @@ -453,7 +367,8 @@ void draw_bang_dots(SDL_Surface *s) { } -void draw_space_dots(SDL_Surface *s) { +void +draw_space_dots(SDL_Surface *s) { int i; Uint16 *rawpixel; rawpixel = (Uint16 *) s->pixels; @@ -476,7 +391,8 @@ void draw_space_dots(SDL_Surface *s) { } } -void draw_engine_dots(SDL_Surface *s) { +void +draw_engine_dots(SDL_Surface *s) { int i; Uint16 *rawpixel; rawpixel = (Uint16 *) s->pixels; @@ -499,7 +415,8 @@ void draw_engine_dots(SDL_Surface *s) { } } -void create_engine_dots(int newdots) { +void +create_engine_dots(int newdots) { int i; double theta,r,dx,dy; @@ -529,7 +446,8 @@ void create_engine_dots(int newdots) { } } -void create_engine_dots2(int newdots, int m) { +void +create_engine_dots2(int newdots, int m) { int i; double theta, theta2, dx, dy, adx, ady; @@ -584,7 +502,8 @@ void create_engine_dots2(int newdots, int m) { } } -int drawdots(SDL_Surface *s) { +void +drawdots(SDL_Surface *s) { int m, scorepos, n; SDL_LockSurface(s); @@ -624,71 +543,35 @@ int drawdots(SDL_Surface *s) { SDL_UnlockSurface(s); } -char * load_file(char *s) { - static char retval[1024]; - snprintf(retval, 1024, "%s/%s", data_dir, s); - return retval; -} - - -int missing(char *dirname) { - struct stat buf; - stat(dirname, &buf); - return (!S_ISDIR(buf.st_mode)); -} - -int init(int fullscreen) { +int +init(int fullscreen) { int i,j; SDL_Surface *temp; Uint16 *raw_pixels; Uint32 flag; + // Where are our data files? + if(!find_files()) exit(1); read_high_score_table(); - // Where are our data files? - // default: ./data - // second alternative: RD_DATADIR - // final alternative: /usr/share/vor - data_dir = strdup("./data"); - if(missing(data_dir)) { - char *env; - env = getenv("RD_DATADIR"); - if(env != NULL) { - data_dir = strdup(env); - if(missing(data_dir)) { - fprintf (stderr,"Cannot find data directory $RD_DATADIR\n"); - exit(-1); - } + if(sound_flag) { + // Initialize SDL with audio and video + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) { + sound_flag = 0; + printf ("Can't open sound, starting without it\n"); + atexit(SDL_Quit); } else { - data_dir = strdup("/usr/share/vor"); - if(missing(data_dir)) { - fprintf (stderr,"Cannot find data in %s\n", data_dir); - exit(-2); - } + atexit(SDL_Quit); + atexit(SDL_CloseAudio); + sound_flag = init_sound(); } - } - - if(oss_sound_flag) { - - // Initialise SDL with audio and video - if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) { - oss_sound_flag = 0; - printf ("Can't open sound, starting without it\n"); - atexit(SDL_Quit); - } else { - atexit(SDL_Quit); - atexit(SDL_CloseAudio); - oss_sound_flag = init_sound(); - } - } else { - // Initialise with video only + // Initialize with video only CONDERROR(SDL_Init(SDL_INIT_VIDEO) != 0); atexit(SDL_Quit); } - if(oss_sound_flag) play_tune(0); // Attempt to get the required video size @@ -697,7 +580,7 @@ int init(int fullscreen) { surf_screen = SDL_SetVideoMode(XSIZE,YSIZE,16,flag); // Set the title bar text - SDL_WM_SetCaption("Rock Dodgers", "rockdodgers"); + SDL_WM_SetCaption("Variations on Rockdodger", "VoR"); NULLERROR(surf_screen); @@ -774,8 +657,10 @@ int init(int fullscreen) { return 0; } -int draw() { - int i,n; + +int +draw() { + int i; SDL_Rect src,dest; struct black_point_struct *p; Uint16 *raw_pixels; @@ -783,8 +668,6 @@ int draw() { char *text; float fadegame,fadeover; - char *statedisplay, buf[1024]; - bang = 0; src.x = 0; @@ -795,46 +678,9 @@ int draw() { // Draw a fully black background SDL_FillRect(surf_screen,NULL,0); - -#ifdef DEBUG - // DEBUG {{{ - // Show the current state - switch (state) { - case TITLE_PAGE: - statedisplay = "title_page"; - break; - case GAMEPLAY: - statedisplay = "gameplay"; - break; - case DEAD_PAUSE: - statedisplay = "dead_pause"; - break; - case GAME_OVER: - statedisplay = "game_over"; - break; - case HIGH_SCORE_ENTRY: - statedisplay = "high_score_entry"; - break; - case HIGH_SCORE_DISPLAY: - statedisplay = "high_score_display"; - break; - case DEMO: - statedisplay = "demo"; - break; - } - snprintf(buf,1024, "mode = %s", statedisplay); - PutString(surf_screen,0,YSIZE-50,buf); - // }}} -#endif - // Draw the background dots drawdots(surf_screen); - // If it's firing, draw the laser - if(laser) { - drawlaser(); - } - // Draw ship if(!gameover && (state == GAMEPLAY || state == DEMO) ) { src.w = surf_ship->w; @@ -860,28 +706,6 @@ int draw() { // Draw the rock SDL_BlitSurface(rock[i].image,&src,surf_screen,&dest); - // Draw the heated part of the rock, in an alpha which reflects the - // amount of heat in the rock. - if(rock[i].heat>0) { - SDL_Surface *deadrock; - deadrock = surf_deadrock[rock[i].type_number]; - SDL_SetAlpha(deadrock,SDL_SRCALPHA,rock[i].heat*255/rock[i].image->h); - dest.x = (int) rock[i].x; // kludge - SDL_BlitSurface(deadrock,&src,surf_screen,&dest); - if(rnd()<0.3) { - rock[i].heat -= movementrate; - } - } - - // If the rock is heated past a certain point, the water content of - // the rock flashes to steam, releasing enough energy to destroy - // the rock in spectacular fashion. - if(rock[i].heat>rock[i].image->h) { - rock[i].active = 0; - play_sound(1 + (int)(rnd()*3)); - makebangdots(rock[i].x,rock[i].y,rock[i].xvel,rock[i].yvel,rock[i].image,10); - } - } } @@ -1011,48 +835,20 @@ int draw() { } if(!gameover && state == GAMEPLAY) { - // Show the freaky shields SDL_LockSurface(surf_screen); raw_pixels = (Uint16 *) surf_screen->pixels; - if(initialshield>0 || shieldsup && shieldlevel>0) { - int x,y,l; - Uint16 c; - - if(initialshield>0) { - initialshield -= movementrate; - c = SDL_MapRGB(surf_screen->format,0,255,255); - } else { - c = heatcolor[(int)shieldlevel]; - shieldlevel -= movementrate; - } - - shieldpulse += 0.2; - for(p = black_point; px + (int)xship + (rnd() + rnd()-1)*sin(shieldpulse)*4 + 1; - y = p->y + (int)yship + (rnd() + rnd()-1)*sin(shieldpulse)*4 + 1; - if(x>0 && y>0 && xpitch/2 * y + x; - raw_pixels[offset] = c; - } - } - } else { - // When the shields are off, check that the black points - // on the ship are still black, and not covered up by rocks - for(p = black_point; ppitch/2 * (p->y + (int)yship) + p->x + (int)xship; - if(raw_pixels[offset]) { - // Set the bang flag - bang = 1; - } + // Check that the black points on the ship are + // still black, and not covered up by rocks. + for(p = black_point; ppitch/2 * (p->y + (int)yship) + p->x + (int)xship; + if(raw_pixels[offset]) { + // Set the bang flag + bang = 1; } } SDL_UnlockSurface(surf_screen); } -#ifdef DOTCOLLISION - dotcollision(surf_screen); // Kill dots that are not on their spots -#endif - // Draw all the little ships if(state == GAMEPLAY || state == DEAD_PAUSE || state == GAME_OVER) for(i = 0; ixvel = -(rockspeed)*(1 + rnd()); rockptr->yvel = rnd()-0.5; rockptr->type_number = random() % NROCKS; - rockptr->heat = 0; rockptr->image = surf_rock[rockptr->type_number];// [random()%NROCKS]; rockptr->active = 1; rockptr->y = rnd()*(YSIZE + rockptr->image->h); @@ -1201,23 +1006,33 @@ int gameloop() { // SCROLLING yscroll = yship - (YSIZE / 2); - yscroll /= -15; + yscroll += yvel * 25; + yscroll /= -25; + yscroll = ((scrollvel * (12 - movementrate)) + (yscroll * movementrate)) / 12; + scrollvel = yscroll; yscroll = yscroll*movementrate; yship += yscroll; // Move all the rocks - for(i = 0; i YSIZE) { - rock[i].y -= YSIZE; - rock[i].y -= rock[i].image->w; - } else if(rock[i].y < -rock[i].image->w) { - rock[i].y += YSIZE; - rock[i].y += rock[i].image->w; - } - if(rock[i].x<-32.0) - rock[i].active = 0; + for(i = 0; i < MAXROCKS; i++) { + if(rock[i].active) { + rock[i].x += rock[i].xvel*movementrate; + rock[i].y += rock[i].yvel*movementrate + yscroll; + if(rock[i].y > YSIZE || rock[i].y < -rock[i].image->h) { + if(rock[i].dead) { + rock[i].dead = 0; + rock[i].active = 0; + } else { + // wrap + rock[i].y = (YSIZE - rock[i].image->h) - rock[i].y; + rock[i].y += (rock[i].yvel*movementrate + yscroll) * 1.01; + } + } + if(rock[i].x < -rock[i].image->w || rock[i].x > XSIZE) { + rock[i].active = 0; + rock[i].dead = 0; + } + } } @@ -1237,10 +1052,8 @@ int gameloop() { if(draw() && state == GAMEPLAY) { - if(oss_sound_flag) { - // Play the explosion sound - play_sound(0); - } + // Play the explosion sound + play_sound(0); makebangdots(xship,yship,xvel,yvel,surf_ship,30); if(--nships <= 0) { gameover = 1; @@ -1251,8 +1064,9 @@ int gameloop() { } else { state = DEAD_PAUSE; - state_timeout = 50.0; - + state_timeout = 20.0; + xvel = 0; + yvel = 0; } } @@ -1267,6 +1081,7 @@ int gameloop() { for(i = 0; i= 0) { + while ((x = getopt(argc,argv,"efhmps")) >= 0) { switch(x) { case 'e': // engine tail_plume = 1; @@ -1358,18 +1172,22 @@ main(int argc, char **argv) { break; case 'h': // help printf("Variations on RockDodger\n" - " -e Big tail [E]ngine\n" + " -e big tail [E]ngine\n" " -f [F]ull screen\n" - " -h This [H]elp message\n" - " -p Stupid original [P]hysics (friction)\n" + " -h this [H]elp message\n" + " -m enable [M]usic\n" + " -p original [P]hysics (friction)\n" " -s [S]ilent (no sound)\n"); exit(0); break; + case 'm': // music + music_flag = 1; case 'p': // physics friction = 1; break; case 's': // silent - oss_sound_flag = 0; + sound_flag = 0; + music_flag = 0; break; } } @@ -1379,19 +1197,14 @@ main(int argc, char **argv) { return 1; } - while(1) { - for(i = 0; i