/** * nInvaders - a space invaders clone for ncurses * Copyright (C) 2002-2003 Dettus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * homepage: http://ninvaders.sourceforge.net * mailto: ninvaders-devel@lists.sourceforge.net * */ #include #include #include #include "nInvaders.h" #include "player.h" #include "aliens.h" #include "ufo.h" #include "arduino.h" #include #include #include #include #define FPS 50 int lives; long score; int status; // status handled in timer #define GAME_LOOP 1 #define GAME_NEXTLEVEL 2 #define GAME_PAUSED 3 #define GAME_OVER 4 #define GAME_EXIT 5 #define GAME_HIGHSCORE 6 libusb_device_handle *handle; struct libusb_endpoint_descriptor endpoint_desc_list[ENDPOINTS_NUMBER]; int waitUSB = 0; void sendLives(){ uint8_t toSend = 0x00; if(lives == 5) toSend = 0x1F; else if(lives == 4) toSend = 0x0F; else if(lives == 3) toSend = 0x07; else if(lives == 2) toSend = 0x03; else if(lives == 1) toSend = 0x01; else if(lives == 0) toSend = 0x00; if(handle != NULL && endpoint_desc_list != NULL && waitUSB == 0){ waitUSB = 1; usleep(100000); // wait for endpoints to be free (100 ms) sendData(0, toSend, handle, endpoint_desc_list); waitUSB = 0; } } /** * initialize level: reset attributes of most units */ static void initLevel() { playerReset(); aliensReset(); ufoReset(); bunkersReset(); render(); drawscore(); } /** * evaluate command line parameters */ static void evaluateCommandLine(int argc, char **argv) { // -l : set skill level if (argc == 3 && strcmp(argv[1], "-l") == 0) { if (argv[2][0] >= '0' && argv[2][0] <= '9') { skill_level = argv[2][0] - 48; } else { argc = 2; } } // -gpl : show GNU GPL if (argc == 2 && strcmp(argv[1], "-gpl") == 0) { showGpl(); } // wrong command line: show usage if (argc == 2 || (argc == 3 && strcmp(argv[1], "-l") != 0)) { showVersion(); showUsage(); exit(1); } } static void finish(int sig) { endwin(); showGplShort(); fprintf(stderr,"\n"); fprintf(stderr,"\n"); fprintf(stderr,"=========================================================================\n"); fprintf(stderr,"\n"); fprintf(stderr,"Final score: %7.7ld, Final level: %2.2d\nFinal rating... ",score,level); if (lives>0) fprintf(stderr,"Quitter\n\n"); else if(score<5000) fprintf(stderr,"Alien Fodder\n\n"); else if(score<7500) fprintf(stderr,"Easy Target\n\n"); else if(score<10000) fprintf(stderr,"Barely Mediocre\n\n"); else if(score<12500) fprintf(stderr,"Shows Promise\n\n"); else if(score<15000) fprintf(stderr,"Alien Blaster\n\n"); else if(score<20000) fprintf(stderr,"Earth Defender\n\n"); else if(score>19999) fprintf(stderr,"Supreme Protector\n\n"); showVersion(); exit(0); } void drawscore() { statusDisplay(level, score, lives); } /** * reads input from keyboard and do action */ void readInput() { int ch; static int lastmove; timeout(100); ch = getch(); // get key pressed static uint8_t data = 0; if(ch == -1){ // keyboard first usleep(1000000); // slow down inputs (100 ms) if(handle != NULL && endpoint_desc_list != NULL && waitUSB == 0) receiveData(2, &data, handle, endpoint_desc_list); if(data != 0){ if((data & 0x10) == 0x10) ch = KEY_LEFT; else if((data & 0x04) == 0x04) ch = ' '; else if((data & 0x02) == 0x02) ch = KEY_RIGHT; else return; } else return; } switch (status) { case GAME_PAUSED: if (ch == 'p') { status = GAME_LOOP; } break; case GAME_HIGHSCORE: if (ch == ' ') { titleScreenClear(); level = 0; // reset level score = 0; // reset score lives = 3; // restore lives sendLives(); status = GAME_NEXTLEVEL; } else if (ch == 'q') { // quit game status = GAME_EXIT; } break; case GAME_OVER: break; // don't do anything default: if (ch == 'l' || ch == KEY_RIGHT) { // move player right if (lastmove == 'l') { playerTurboOn(); // enable Turbo } else { playerTurboOff(); // disable Turbo } playerMoveRight(); // move player lastmove = 'l'; // remember last move for turbo mode } else if (ch == 'h' || ch == KEY_LEFT) { // move player left if (lastmove == 'h') { playerTurboOn(); // enable Turbo } else { playerTurboOff(); // disable Turbo } playerMoveLeft(); // move player lastmove = 'h'; // remember last move for turbo mode } else if (ch == 'k' || ch == ' ') { // shoot missile playerLaunchMissile(); } else if (ch == 'p') { // pause game until 'p' pressed again // set status to game paused status = GAME_PAUSED; } else if (ch == 'W') { // cheat: goto next level status = GAME_NEXTLEVEL; } else if (ch == 'L') { // cheat: one more live lives++; sendLives(); drawscore(); } else if (ch == 'q') { // quit game status = GAME_EXIT; } else { // disable turbo mode if key is not kept pressed lastmove = ' '; } } // switch } /** * timer * this method is executed every 1 / FPS seconds */ void handleTimer() { static int aliens_move_counter = 0; static int aliens_shot_counter = 0; static int player_shot_counter = 0; static int ufo_move_counter = 0; static int title_animation_counter = 0; static int game_over_counter = 0; switch (status) { case GAME_NEXTLEVEL: // go to next level level++; // increase level initLevel(); // initialize level aliens_move_counter = 0; aliens_shot_counter = 0; player_shot_counter = 0; ufo_move_counter = 0; weite = (shipnum+(skill_level*10)-(level*5)+5)/10; if (weite < 0) { weite = 0; } // change status and start game! status = GAME_LOOP; case GAME_LOOP: // do game handling // move aliens if (aliens_move_counter == 0 && aliensMove() == 1) { // aliens reached player lives = 0; sendLives(); status = GAME_OVER; } // move player missile if (player_shot_counter == 0 && playerMoveMissile() == 1) { // no aliens left status = GAME_NEXTLEVEL; } // move aliens' missiles if (aliens_shot_counter == 0 && aliensMissileMove() == 1) { // player was hit lives--; // player looses one life sendLives(); drawscore(); // draw score playerExplode(); // display some explosion graphics if (lives == 0) { // if no lives left ... status = GAME_OVER; // ... exit game } } // move ufo if (ufo_move_counter == 0 && ufoShowUfo() == 1) { ufoMoveLeft(); // move it one position to the left } if (aliens_shot_counter++ >= 5) {aliens_shot_counter=0;} // speed of alien shot if (player_shot_counter++ >= 1) {player_shot_counter=0;} // speed of player shot if (aliens_move_counter++ >= weite) {aliens_move_counter=0;} // speed of aliend if (ufo_move_counter++ >= 3) {ufo_move_counter=0;} // speed of ufo refreshScreen(); break; case GAME_PAUSED: // game is paused break; case GAME_OVER: // game over if (game_over_counter == 100) { battleFieldClear(); status = GAME_HIGHSCORE; game_over_counter = 0; } else { gameOverDisplay(); game_over_counter++; } break; case GAME_EXIT: // exit game finish(0); break; case GAME_HIGHSCORE: // display highscore if (title_animation_counter == 0) { titleScreenDisplay(); } if (title_animation_counter++ >= 6) {title_animation_counter = 0;} // speed of animation break; } } /** * set up timer */ void setUpTimer() { struct itimerval myTimer; struct sigaction myAction; myTimer.it_value.tv_sec = 0; myTimer.it_value.tv_usec = 1000000 / FPS; myTimer.it_interval.tv_sec = 0; myTimer.it_interval.tv_usec = 1000000 / FPS; setitimer(ITIMER_REAL, &myTimer, NULL); myAction.sa_handler = &handleTimer; myAction.sa_flags = SA_RESTART; sigaction(SIGALRM, &myAction, NULL); } int go = 1; /*void signalINT(int sig){ if(sig == SIGINT){ go = 0; } }*/ int main(int argc, char **argv) { libusb_context *context; libusb_device **devices; struct libusb_config_descriptor *config_desc; // start start(&context, &devices, &handle, &config_desc, endpoint_desc_list); // singals /*struct sigaction action; action.sa_handler = signalINT; sigaction(SIGINT, &action, NULL);*/ // nInvaders weite = 0; score = 0; lives = 3; sendLives(); level = 0; skill_level = 1; evaluateCommandLine(argc, argv); // evaluate command line parameters graphicEngineInit(); // initialize graphic engine // set up timer/ game handling setUpTimer(); status = GAME_HIGHSCORE; // read keyboard input do { // do movements and key-checking readInput(handle, endpoint_desc_list); } while (go); // stop stop(config_desc, handle, devices, context); return 0; } void doScoring(int alienType) { int points[4] = {500, 200, 150, 100}; // 0: ufo, 1:red, 2:green, 3:blue score += points[alienType]; // every alien type does different scoring points // every 6000 pts player gets a new live if (score % 6000 == 0){ lives++; sendLives(); } drawscore(); // display score }