|
@@ -1,324 +0,0 @@
|
|
|
-#include "bullet.hpp"
|
|
|
-#include "enemy.hpp"
|
|
|
-#include "player.hpp"
|
|
|
-#include "box.hpp"
|
|
|
-#include "boss.hpp"
|
|
|
-#include "powerup.hpp"
|
|
|
-#include "definitions.hpp"
|
|
|
-#include "functions.hpp"
|
|
|
-#include "wall.hpp"
|
|
|
-
|
|
|
-using std::cout;
|
|
|
-using std::endl;
|
|
|
-using std::min;
|
|
|
-
|
|
|
-int main()
|
|
|
-{
|
|
|
-
|
|
|
- typedef std::list<bullet> b_list;
|
|
|
- typedef std::list<enemy> e_list;
|
|
|
- typedef std::vector<wall> w_vec;
|
|
|
- srand(time(NULL));
|
|
|
-
|
|
|
- //OBJECTS INIZIALIZATION
|
|
|
- Box box1;
|
|
|
- player player1; //player is automatically created in [C/2][R]
|
|
|
- e_list enemies; //vector of enemies
|
|
|
- b_list bullets; //list of player's bullets
|
|
|
- b_list bombs; //list of enemies' bombs
|
|
|
- b_list powerups; //list of powerups
|
|
|
- int refresh_time; //how long the program waits before refreshing the screen
|
|
|
- int chflag=0; //cheat flag: 0=normal, 1=cheats allowed, 2=special mode activated, 3=both special mode and cheats.
|
|
|
- boss boss1;
|
|
|
- WINDOW *Score,*BossHP;
|
|
|
-
|
|
|
- //PARAMETERS/UTILITIES
|
|
|
- double shootrate; //probability of an enemy shooting a bomb
|
|
|
- int command; //keyboard input
|
|
|
- int score=0; //score: gain +100 when an enemy is destroyed and +50 when a bomb is destroyed
|
|
|
- char level='1';
|
|
|
- bool sound=true; //difficulty level
|
|
|
-
|
|
|
-
|
|
|
- //NCURSES STUFF
|
|
|
- initscr();
|
|
|
- curs_set(0);
|
|
|
- noecho();
|
|
|
- cbreak();
|
|
|
- keypad(stdscr,TRUE);
|
|
|
- start_color();
|
|
|
- init_pair(0,COLOR_WHITE,COLOR_BLACK);
|
|
|
- init_pair(1,COLOR_GREEN,COLOR_BLACK); //PLAYER
|
|
|
- init_pair(2,COLOR_RED,COLOR_BLACK); //ENEMY
|
|
|
- init_pair(3,COLOR_YELLOW,COLOR_BLACK); //BULLETS-POWERUPS
|
|
|
- init_pair(4,COLOR_MAGENTA,COLOR_BLACK); //WALLS
|
|
|
- init_pair(5,COLOR_CYAN,COLOR_BLACK); //BOSS
|
|
|
- init_pair(6,COLOR_BLUE,COLOR_BLACK); //BOMBS
|
|
|
- init_pair(7,COLOR_RED,COLOR_RED);
|
|
|
- init_pair(8,COLOR_GREEN,COLOR_GREEN);
|
|
|
-
|
|
|
- //////////PROGRAM START: creation of game objects and set of parameters
|
|
|
-
|
|
|
- WALLS_NUM=2;
|
|
|
-
|
|
|
- ENEMY_NUM=choose_level(shootrate, refresh_time, boss1, level); //choose difficulty level and set game parameters and boss
|
|
|
-
|
|
|
- erase();
|
|
|
-
|
|
|
- if(atoi(&level)==1) WALLS_NUM=3;
|
|
|
-
|
|
|
- w_vec walls(WALLS_NUM);
|
|
|
-
|
|
|
- Score=newwin(3,10,R/3,C+3);
|
|
|
- BossHP=newwin(3,15,R/3-3,C+3);
|
|
|
- load_enemies(enemies,ENEMY_NUM);
|
|
|
-
|
|
|
- int i=0;
|
|
|
- for(w_vec::iterator it=walls.begin(); it!=walls.end(); ++it, ++i) //creating walls (in a quite symmetric pattern)
|
|
|
- it->create((i+1)*(C/(3*WALLS_NUM+1))+i*(2*C/(3*WALLS_NUM+1)),2*R/3,(int)min(6,2*C/(3*WALLS_NUM+1)),2,3);
|
|
|
-
|
|
|
- box1.refresh(bullets, bombs, enemies, player1, score, boss1, walls, powerups); //matrix is loaded for the first time
|
|
|
-
|
|
|
-
|
|
|
- /////////ENTERING MAIN LOOP
|
|
|
-
|
|
|
- int childPID0=fork();
|
|
|
- if(childPID0==0 && sound){
|
|
|
- music();
|
|
|
- return 0;
|
|
|
- }
|
|
|
- while(1)
|
|
|
- {
|
|
|
- napms(refresh_time); //ncurses sleep function (ms)
|
|
|
- timeout(0);
|
|
|
- command = getch();
|
|
|
-
|
|
|
- if(command!=ERR) //READING INPUT
|
|
|
- command = tolower(command);
|
|
|
-
|
|
|
- if(command == 'q'){ //q = exit game
|
|
|
- endwin();
|
|
|
- kill_music(childPID0);
|
|
|
- cout<<lightgreen<<"Game exited correctly."<<none<<endl;
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- if(command == 'p')
|
|
|
- pause_game(chflag); //p = pause game
|
|
|
-
|
|
|
- if(chflag==1 || chflag==3){ //cheats
|
|
|
- if(command == '+' && player1.weaponclass<5) player1.weaponclass++; //increase weaponclass
|
|
|
- if(command == '\\' && player1.weaponclass>1) player1.weaponclass--; //decrease weaponclass
|
|
|
- if(command == '-' && player1.length>2){ //decrease size
|
|
|
- mvaddch(player1.y,player1.x+player1.length-1,' ');
|
|
|
- player1.length--;
|
|
|
- }
|
|
|
- if(command == '\'' && player1.length<20) player1.length++; //increase size
|
|
|
- if(command == 'n') //nuke enemies
|
|
|
- for(e_list::iterator it=enemies.begin();it!=enemies.end();it++){
|
|
|
- it->alive=false;
|
|
|
- mvaddch(it->y,it->x,' ');
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(chflag!=2 && chflag!=3)
|
|
|
- get_KonamiCode(command,chflag,boss1,enemies,bullets,bombs,powerups,box1);
|
|
|
-
|
|
|
- if(command == 'a' || command == KEY_LEFT || command == 'd' || command == KEY_RIGHT ||
|
|
|
- ((command == 'w'|| command == KEY_UP || command == 's' || command == KEY_DOWN) &&
|
|
|
- (chflag==1 || chflag==3))){ //a or d = move player (if cheats are triggered, also w and s)
|
|
|
- for(int i=player1.x;i<player1.x+player1.length;i++) mvaddch(player1.y,i,' ');
|
|
|
- player1.next_pos(command);
|
|
|
- }
|
|
|
-
|
|
|
- if(command==' '){ //spacebar = shoot!
|
|
|
- if(sound){
|
|
|
- int childPID=fork();
|
|
|
- if(childPID==0){
|
|
|
- system("beep -f 1000 -l 30 -n -f 850 -l 30");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- player1.shoot(bullets);
|
|
|
- }
|
|
|
-
|
|
|
- if(command=='m'){ //mute/unmute
|
|
|
- if(sound) kill_music(childPID0);
|
|
|
- else{
|
|
|
- childPID0=fork();
|
|
|
- if(childPID0==0){
|
|
|
- music();
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- sound=!sound;
|
|
|
- }
|
|
|
-
|
|
|
- if(enemyalive(enemies)) //if there's at least one enemy alive:
|
|
|
- {
|
|
|
- int n_enemies=0;
|
|
|
- e_list::const_iterator e_end = enemies.end();
|
|
|
-
|
|
|
- for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)
|
|
|
- if(it->alive) n_enemies++; //counts alive enemies
|
|
|
-
|
|
|
- for(e_list::iterator it=enemies.begin(); it!=e_end; ++it)
|
|
|
- {
|
|
|
- mvaddch(it->y,it->x,' ');
|
|
|
- it->next_pos(); //evaluate new positions
|
|
|
- if(it->alive && (double)rand()/RAND_MAX<(shootrate*ENEMY_NUM/n_enemies)){ //try a bomb-dropping
|
|
|
- if(sound){
|
|
|
- int childPID=fork();
|
|
|
- if(childPID==0){
|
|
|
- system("beep -f 1500 -l 30 -n -f 1000 -l 30");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- it->shoot(bombs);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else boss1.alive = true; //if no enemy is alive, boss spawns
|
|
|
-
|
|
|
- if(boss1.alive) //if boss is alive, moves and shoots
|
|
|
- {
|
|
|
- for(int i=0;i<boss1.width;i++) mvaddch(boss1.y,boss1.x+i,' ');
|
|
|
- for(int j=0;j<boss1.height;j++){
|
|
|
- mvaddch(boss1.y+j,boss1.x,' ');
|
|
|
- mvaddch(boss1.y+j,boss1.x+boss1.width-1,' ');
|
|
|
- }
|
|
|
- boss1.next_pos();
|
|
|
- if((double)rand()/RAND_MAX<shootrate*25.){ //boss's shootrate is 25 times the one of normal enemies
|
|
|
- if(sound){
|
|
|
- int childPID=fork();
|
|
|
- if(childPID==0){
|
|
|
- system("beep -f 1500 -l 30 -n -f 1000 -l 30");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
- boss1.shoot(bombs);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(!bullets.empty()) //evaluate new bullets' positions
|
|
|
- for(b_list::iterator it=bullets.begin(); it!=bullets.end(); ++it){
|
|
|
- mvaddch(it->y,it->x,' ');
|
|
|
- it->next_pos();
|
|
|
- }
|
|
|
-
|
|
|
- bullets.unique(); //remove duplicates of bullets (i.e. player can't shoot enemies)
|
|
|
-
|
|
|
- if(!bombs.empty()) //evaluate new bombs' positions
|
|
|
- for(b_list::iterator it=bombs.begin(); it!=bombs.end(); ++it){
|
|
|
- mvaddch(it->y,it->x,' ');
|
|
|
- it->next_pos();
|
|
|
- }
|
|
|
-
|
|
|
- bombs.unique(); //remove duplicates of bombs
|
|
|
-
|
|
|
- if(!powerups.empty()) //new powerups' positions
|
|
|
- for(b_list::iterator it=powerups.begin(); it!=powerups.end(); ++it){
|
|
|
- mvaddch(it->y,it->x,' ');
|
|
|
- it->next_pos();
|
|
|
- }
|
|
|
-
|
|
|
- powerups.unique(); //FIXME: THIS ONLY WORKS ON CONSECUTIVE ELEMENTS OF THE LIST!! we should at least sort powerups before calling unique()
|
|
|
-
|
|
|
- box1.refresh(bullets, bombs, enemies, player1, score, boss1, walls, powerups);
|
|
|
-
|
|
|
- ///////ENDGAME CHECKS
|
|
|
- if(boss1.health<1) //YOU WON!!
|
|
|
- {
|
|
|
- if(sound){
|
|
|
- kill_music(childPID0);
|
|
|
- int childPID=fork();
|
|
|
- if(childPID==0){
|
|
|
- system("beep -f 1000 -l 150 -n -f 800 -l 150 -n -f 1000 -l 150 -n -f 1500 -l 600");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Victory(boss1.name,score,level,chflag);
|
|
|
-
|
|
|
- WINDOW *replay;
|
|
|
-
|
|
|
- replay=newwin(3,25,26,20);
|
|
|
- box(replay,ACS_VLINE,ACS_HLINE);
|
|
|
-
|
|
|
- if(playagain(replay)) //playagain() returns true if player wants to play again, false otherwise
|
|
|
- {
|
|
|
- delwin(replay);
|
|
|
- timeout(500);
|
|
|
- score=0;
|
|
|
- erase();
|
|
|
- refresh();
|
|
|
- choose_level(shootrate, refresh_time, boss1, level);
|
|
|
- reset(box1, player1, enemies, boss1, bullets, bombs, walls, powerups, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
|
|
|
- erase();
|
|
|
- refresh();
|
|
|
- continue;
|
|
|
- }
|
|
|
- else {
|
|
|
- endwin();
|
|
|
- cout<<lightgreen<<"Game exited correctly."<<none<<endl;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if(gameover(box1,player1))
|
|
|
- {
|
|
|
- if(sound){
|
|
|
- kill_music(childPID0);
|
|
|
- int childPID=fork();
|
|
|
- if(childPID==0){
|
|
|
- system("beep -f 700 -l 150 -n -f 585 -l 150 -n -f 550 -l 150 -n -f 520 -l 600");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Defeat(score);
|
|
|
-
|
|
|
- WINDOW* replay;
|
|
|
-
|
|
|
- replay=newwin(3,25,17,20);
|
|
|
- box(replay,ACS_VLINE,ACS_HLINE);
|
|
|
-
|
|
|
- if(playagain(replay)) //playagain() returns true if player wants to play again, false otherwise
|
|
|
- {
|
|
|
- delwin(replay);
|
|
|
- timeout(500);
|
|
|
- score=0;
|
|
|
- erase();
|
|
|
- refresh();
|
|
|
- choose_level(shootrate, refresh_time, boss1, level);
|
|
|
- reset(box1, player1, enemies, boss1, bullets, bombs, walls, powerups, level,chflag); // reset box, player, enemy and delete all bullets and bombs
|
|
|
- erase();
|
|
|
- refresh();
|
|
|
- continue;
|
|
|
- }
|
|
|
- else {
|
|
|
- endwin();
|
|
|
- cout<<lightgreen<<"Game exited correctly."<<none<<endl;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- write_score(Score,score);
|
|
|
-
|
|
|
- if(boss1.alive){
|
|
|
- write_bosshp(BossHP,boss1.health,boss1.healthmax,boss1.name);
|
|
|
- wrefresh(BossHP);
|
|
|
- }
|
|
|
-
|
|
|
- wrefresh(Score);
|
|
|
- refresh();
|
|
|
- }
|
|
|
-////////END OF MAIN LOOP
|
|
|
-
|
|
|
- endwin();
|
|
|
-
|
|
|
- return -1; //program never really reaches here, but compiler is happy
|
|
|
-}
|
|
|
-
|
|
|
-
|