/* * YAPong.c 0.01 - Yet Another pong clone, made by //YorHel * * Copyright 2006 Y.Heling. * 2006-02-22 * License: MIT */ #include #include #include #include #include #define DI_UP 1 #define DI_DOWN 2 #define DI_RIGHT 3 #define DI_LEFT 4 void movepadel(char, char); void startgame(); void drawpadels(); void updatescore(); void drawframe(); void updatedot(); void movedot(int); int print_help(char *); int winrows, wincols, padsize, padposL, padposR, scoreL, scoreR, dotX, dotY, delay, padstep, dotstep; char direX, direY, started, paused, scored, autosize; WINDOW *win; int main(int argc, char *argv[]) { /* defaults */ autosize = 0; padstep = 1; dotstep = 1; winrows = 25; wincols = 80; padsize = ((winrows-3)/10); delay = 50 * 1000; /* args */ { char *name = *argv++; char *ch; while(ch = *argv++) { if(!strcmp(ch, "-h")) return print_help(name); else if(!strcmp(ch, "-l")) { int level = atoi(*argv++); switch(level) { case 1 : delay = 100*1000; padsize = 6; padstep = 2; dotstep = 1; break; case 2 : delay = 80*1000; padsize = 6; padstep = 2; dotstep = 1; break; case 3 : delay = 65*1000; padsize = 5; padstep = 1; dotstep = 1; break; case 4 : delay = 50*1000; padsize = 3; padstep = 1; dotstep = 1; break; case 5 : delay = 80*1000; padsize = 3; padstep = 1; dotstep = 2; break; default : printf("ERROR: unknown level %d\n", level); return 0; break; } } else if(!strcmp(ch, "-d")) { delay = atoi(*argv++) * 1000; if(delay >= 1000*1000 || delay == 0) { printf("ERROR: delay should be an integer between 0 and 1000\n"); return 1; } } else if(!strcmp(ch, "-p")) { padsize = atoi(*argv++); if(padsize > wincols-3 || padsize == 0) { printf("ERROR: padel size should at least be 1 and should not be too high\n"); return 1; } } else if(!strcmp(ch, "-s")) { if(!strcmp(*argv, "auto")) { autosize = 1; *argv++; } else { wincols = atoi(*argv++); winrows = atoi(*argv++); autosize = 0; if(wincols < 20 || winrows < 5) { printf("ERROR: Window size should at least be 20x5\n"); return 1; } } } else if(!strcmp(ch, "-ps")) { padstep = atoi(*argv++); if(padstep > padsize || padstep <= 0) { printf("ERROR: padstep should at least be 0 and should not be larger than padsize\n"); return 1; } } else if(!strcmp(ch, "-ds")) { dotstep = atoi(*argv++); if(dotstep <= 0) { printf("ERROR: dotstep should be a positive integer\n"); return 1; } } else { printf("ERROR: no such option: %s\n", ch); return print_help(name); } } } /* initialize */ if( (win = initscr()) == NULL) { fprintf(stderr, "ERROR: Can't initialize ncurses\n"); return(1); } cbreak(); /* imidiatly get input chars */ noecho(); /* don't print input chars */ keypad(stdscr, TRUE); /* also get other keys */ curs_set(0); /* hide cursor */ if(autosize) getmaxyx(stdscr, winrows, wincols); /* non-changable stuff */ padposL = padposR = ((winrows/2)-(padsize/2)); scoreL = scoreR = 0; dotX = (wincols/2); dotY = (winrows/2)-1; direX = DI_RIGHT; direY = DI_DOWN; started = paused = 0; mvaddstr(0, 0, "Initializing, please wait..."); refresh(); clear(); /* draw stuff */ drawframe(); drawpadels(); mvaddch(dotY, dotX, '0'); refresh(); /* get keyboard input */ int ch; while(1) { ch = getch(); switch(ch) { case KEY_UP : movepadel('r', 'u'); break; case KEY_DOWN : movepadel('r', 'd'); break; case 'a' : movepadel('l', 'u'); break; case 'z' : movepadel('l', 'd'); break; case ' ' : if(!started) startgame(); else if(scored) { scored = 0; mvaddch(dotY, dotX, ' '); dotX = (wincols/2); dotY = (winrows/2)-1; refresh(); } else if(!paused) paused = 1; else if(paused) paused = 0; break; case 'q' : goto end; break; } } /* cleanup */ end: erase(); mvaddstr(0, 0, "Thank you for playing Yet Another pong game. :)\nPlease visit http://yorhel.nl/ when your bored...\n"); refresh(); delwin(win); endwin(); refresh(); return 0; } void movepadel(char which, char direct) { if(paused || scored || !started) return; int *pos = which == 'r' ? &padposR : &padposL; *pos += direct == 'u' ? -1*padstep : padstep; if(*pos < 2) *pos = 2; if(*pos > winrows-padsize-2) *pos = winrows-padsize-2; drawpadels(); move(wincols-1, 0); refresh(); } void startgame() { struct itimerval t; t.it_interval.tv_sec = t.it_value.tv_sec = 0; t.it_interval.tv_usec = t.it_value.tv_usec = delay; setitimer(ITIMER_REAL, &t, NULL); struct sigaction s; s.sa_handler = movedot; s.sa_flags = 0; sigemptyset(&s.sa_mask); sigaction(SIGALRM, &s, NULL); started = 1; } void drawframe() { mvaddstr(0, 3, "left"); mvaddstr(0, wincols-8, "right"); mvaddstr(0, ((wincols/2)-7), "YAPong by //YorHel"); move(1, 0); hline(ACS_HLINE, wincols); move(winrows-1, 0); hline(ACS_HLINE, wincols); updatescore(); } void updatescore() { char scl[3], scr[3]; sprintf(scl, "%02d", scoreL); sprintf(scr, "%02d", scoreR); mvaddstr(0, 0, scl); mvaddstr(0, wincols-2, scr); } void drawpadels() { int c; for(c=winrows; c--; ) { if(c < 2 || c >= winrows-1) continue; /* left paddel */ if(c >= padposL && c <= padposL+padsize) mvaddch(c, 0, ' ' | A_REVERSE); else mvaddch(c, 0, ' '); /* right paddel */ if(c >= padposR && c <= padposR+padsize) mvaddch(c, wincols-1, ' ' | A_REVERSE); else mvaddch(c, wincols-1, ' '); } } /* called from signal */ void movedot(int signal) { if(signal != SIGALRM || !started || paused || scored) return; mvaddch(dotY, dotX, ' '); dotX += direX == DI_LEFT ? -1*dotstep : dotstep; dotY += direY == DI_UP ? -1*dotstep : dotstep; if(direY == DI_UP && dotY <= 2) { direY = DI_DOWN; dotY = 2; } if(direY == DI_DOWN && dotY >= winrows-2) { direY = DI_UP; dotY = winrows-2; } if(direX == DI_RIGHT && dotX >= wincols-2) { direX = DI_LEFT; dotX = wincols-2; if(dotY < padposR || dotY > padposR + padsize) { scored = 1; scoreL++; direX = DI_LEFT; updatescore(); } } if(direX == DI_LEFT && dotX <= 1) { direX = DI_RIGHT; dotX = 1; if(dotY < padposL || dotY > padposL + padsize) { scored = 1; scoreR++; direX = DI_RIGHT; updatescore(); } } mvaddch(dotY, dotX, '0'); move(wincols-1, 0); refresh(); } int print_help(char *name) { printf("Usage: %s [options]\n\n", name); printf("Options:\n"); printf(" -h This help message.\n"); printf(" -d int Specifies the interval between every move\n"); printf(" of the dot. You can speed up the game by\n"); printf(" setting this to a lower value.\n"); printf(" -p int Specifies the size of each padel in pixels\n"); printf(" -s x y Specifies the size of the window, or set\n"); printf(" to 'auto' to use the size of your current\n"); printf(" terminal. Recommended and default size is\n"); printf(" 80x25.\n"); printf(" -ps int Specifies the amount of pixels the padels\n"); printf(" move each time\n"); printf(" -ds int The amount of pixels the dot moves each\n"); printf(" time, setting this to a larger value\n"); printf(" increases game speed a lot.\n"); printf(" -l level The game-level, higher levels are more\n"); printf(" difficult. See below for more information\n\n"); printf("Levels:\n"); printf(" option equals to\n"); printf(" -l 1 -d 100 -p 6 -ps 2 -ds 1\n"); printf(" -l 2 -d 80 -p 6 -ps 2 -ds 1\n"); printf(" -l 3 -d 65 -p 5 -ps 1 -ds 1\n"); printf(" -l 4 -d 50 -p 3 -ps 1 -ds 1\n"); printf(" -l 5 -d 80 -p 3 -ps 1 -ds 2\n"); printf(" Please note that all the levels are meant for a 80x25\n"); printf(" window size, level 5 might be very easy with a higher\n"); printf(" window size. In that case you should change the\n"); printf(" the options yourself.\n\n"); printf("Ingame keys:\n"); printf(" space Start/pause/resume game\n"); printf(" key_up Move right padel up\n"); printf(" key_down Move right padel down\n"); printf(" a Move left padel up\n"); printf(" z Move left padel down\n"); printf(" q Quit game\n"); return 0; }