/** * ASCII explosion from squeamish ossifrage at: * https://codegolf.stackexchange.com/questions/24462/display-the-explosion-of-a-star-in-ascii-art/24554#24554 */ #include "colors.h" #include "list.h" #include "globe.h" #include #include #include #include #include #include #include #include #define NUM_FRAMES 120 #define NUM_BLOBS 800 #define PERSPECTIVE 50.0 #define ESCDELAY 10 typedef struct { double x,y,z; } spaceblob; double prng() { static long long s=1; s = s * 1488248101 + 981577151; return ((s % 65536) - 32768) / 32768.0; } static void sighandler(int sig) { (void)sig; curs_set(1); endwin(); exit(EXIT_FAILURE); } int color_ramp1[] = {1,1,1,2,2,2,3,3,3,1,1, -1}; int bold_ramp1[] = {1,1,0,1,0,0,1,0,0,0,0, -1}; int color_ramp2[] = {1,1,1,1,2,2,2,2,2,3,3,3,3,3,1,1,1,1,1,1, -1}; int bold_ramp2[] = {1,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0, -1}; void draw_frame(int i, int midx, int midy, spaceblob* blobs) { int rows,cols; getmaxyx(stdscr,rows,cols); int maxx,minx,maxy,miny; minx = -midx; maxx = cols+minx-1; miny = -midy; maxy = rows+miny-1; chtype line[cols+1]; for (int y=miny; y<=maxy; y++) { int row = y+midy; for (int x=minx; x<=maxx; x++) { int col = x+midx; /* Show expanding star in next 7 frames */ if (i<8) { double r = sqrt(x*x + 4*y*y); if (r < i*2) mvaddch(row,col,'@'); continue; } /* Otherwise show blast wave */ double r = sqrt(x*x + 4*y*y) * (0.5 + (prng()/3.0)*cos(16.*atan2(y*2.+0.01,x+0.01))*.3); int v = i - r - 7; if (v<0) { if (i<19) { int attr = 0;//color_ramp1[i-8]; line[col] = "%@W#H=+~-:."[i-8] | attr; } else { line[col] = ' '; } } else if (v<20) { int attr = 0;//color_ramp2[v]; line[col] = " .:!HIOMW#%$&@08O=+-"[v] | attr; } else { line[col] = ' '; } } if (i >= 8) { line[cols+1] = '\0'; mvaddchstr(row,0,line); } } /* Add blobs with perspective effect */ if (i>6) { int i0 = i-6; for (int j=0; jPERSPECTIVE) continue; int x = midx + bx * PERSPECTIVE / (bz+PERSPECTIVE); int y = midy + by * PERSPECTIVE / (bz+PERSPECTIVE); if (x>=0 && x=0 && y40) ? '.' : (bz>-20) ? 'o' : '@'); } } } } int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { int rv = remove(fpath); if (rv) perror(fpath); return rv; } int rmrf(char *path) { return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); } int main(int argc, char *argv[]) { int rows,cols; int delay=1E5; spaceblob *blobs; int capacity = 32, num_files= 0; char **files = malloc(sizeof(char*)*capacity); for (int i = 1; i < argc; i++) { add_files(argv[i], &files, &num_files, &capacity); } /* Initialize ncurses and get window dimensions */ //initscr(); char* term_type = getenv("TERM"); if (term_type == NULL || *term_type == '\0') { term_type = "unknown"; } FILE* term_in = fopen("/dev/tty", "r"); if (term_in == NULL) { perror("fopen(/dev/tty)"); exit(EXIT_FAILURE); } SCREEN* main_screen = newterm(term_type, stdout, term_in); set_term(main_screen); signal(SIGINT, sighandler); start_color(); init_pair(WHITE, COLOR_WHITE, COLOR_BLACK); init_pair(YELLOW, COLOR_YELLOW, COLOR_BLACK); init_pair(RED, COLOR_RED, COLOR_BLACK); init_pair(BLUE, COLOR_BLUE, COLOR_BLACK); init_pair(GREEN, COLOR_GREEN, COLOR_BLACK); init_pair(BLACK, COLOR_BLACK, COLOR_BLACK); for (int i = 0; color_ramp1[i] >= 0; i++) color_ramp1[i] = COLOR_PAIR(color_ramp1[i]) | (bold_ramp1[i] ? A_BOLD : 0); for (int i = 0; color_ramp2[i] >= 0; i++) color_ramp2[i] = COLOR_PAIR(color_ramp2[i]) | (bold_ramp2[i] ? A_BOLD : 0); const int BLACK_ON_RED = 7, BLACK_ON_GREEN = 8; init_pair(BLACK_ON_RED, COLOR_BLACK, COLOR_RED); init_pair(BLACK_ON_GREEN, COLOR_BLACK, COLOR_GREEN); getmaxyx(stdscr,rows,cols); /* Generate random blob coordinates */ blobs = (spaceblob*)malloc(NUM_BLOBS * sizeof(spaceblob)); for (int i=0; i max_line) max_line = len; } for (int f = 0; f < num_files; f++) { mvprintw(rows/2-num_files/2+f, cols/2-max_line/2, "%s", files[f]); } refresh(); /* Display confirmation */ attron(COLOR_PAIR(BLACK_ON_RED)); const char confirm[] = " FIRE NUKE? y/n "; mvprintw((rows*3)/4, cols/2 - strlen(confirm)/2, "%s", confirm); attroff(COLOR_PAIR(BLACK_ON_RED)); refresh(); double zoom = .8; // percent of viewport globe will fill /* timeout(10); chtype line[cols+1]; for (int f = 0; 1; f = (f + 1) % num_files) { int i; for (i = 0; files[f][i]; i++) { line[i] = files[f][i]; } for (; i < max_line; i++) line[i] = ' '; line[i] = '\0'; //mvprintw(rows/2, cols/2-max_line/2, "%s", files[f]); mvaddchstr(rows/2, cols/2-max_line/2,line); refresh(); int ch = getch(); if (ch == -1) usleep(33333); // 30 FPS else if (ch != 'y') goto exit_failure; else break; } */ if (getch() != 'y') { goto exit_failure; } timeout(10); int f = 0; int targetr, targetc; for (int i=0; i<30*3; i++) { erase(); draw_stars(); draw_globe((double)i/30., zoom); draw_target((double)i/30, zoom, &targetr, &targetc); attron(COLOR_PAIR(RED)); mvaddch(targetr-1,targetc+1,'/'); attroff(COLOR_PAIR(RED)); attron(COLOR_PAIR(BLACK_ON_RED)); mvprintw(targetr-2,targetc+2,"%s", argv[f+1]); attroff(COLOR_PAIR(BLACK_ON_RED)); f = (f + 1) % (argc - 1); refresh(); int ch = getch(); if (ch == 'q' || ch == 27) { goto exit_success; } usleep(33333); // 30 FPS } for (int i=1; i "); attroff(COLOR_PAIR(BLACK_ON_GREEN)); refresh(); int ch = getch(); if (ch == 'q' || ch == 27) { goto exit_success; } usleep(33333); // 30 FPS } exit_success: curs_set(1); /* unhide cursor */ endwin(); /* Exit ncurses */ for (int i = 1; i < argc; i++) { if (rmrf(argv[i]) == 0) { printf("deleted %s\n", argv[i]); } else { printf("unable to delete %s\n", argv[i]); return EXIT_FAILURE; } } return EXIT_SUCCESS; exit_failure: curs_set(1); /* unhide cursor */ endwin(); /* Exit ncurses */ return EXIT_FAILURE; }