123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- #include "definitions.hpp"
- #include "rocket.hpp"
- #include "enemy.hpp"
- #include "player.hpp"
- #include "boss.hpp"
- #include "powerup.hpp"
- #include "functions.hpp"
- #include "wall.hpp"
- #include <mutex>
- #include <thread>
- std::mutex m_player;
- std::mutex m_enemies;
- std::mutex m_bombs;
- std::mutex m_bullets;
- std::mutex m_rockets;
- std::mutex m_pow;
- std::mutex m_boss;
- std::mutex m_walls;
- using std::cout;
- using std::endl;
- using std::min;
- using std::max;
- int ENEMY_NUM=1; // This variable isn't used, but we have to define it since it is decleared in definitions.hpp"
- int main(int argc,char** argv)
- {
- if(argc>1){
- if(strcmp(argv[1],"--uber-debug")!=0 && strcmp(argv[1],"--info")!=0){
- cout<<"Usage: "<<argv[0]<<" [--info]"<<endl;
- return 1;
- }
-
- if(strcmp(argv[1],"--info")==0){
- cout<<endl<<"Curses Invaders 4.4 - Bossrush"<<endl;
- cout<<endl<<"Game developed by Giacomo Parolini (jp) and Enrico Guiraud (blue) in years 2010-2013."<<endl;
- cout<<"Source code is available under request to jp@lcm.mi.infn.it (it's quite ugly, I warn you ;-) )"<<endl;
- cout<<"Report any bug to the same mail address."<<endl<<endl;
- return 1;
- }
- }
- typedef std::list<bullet> b_list;
- typedef std::vector<wall> w_vec;
- typedef std::list<rocket> r_list;
-
- srand(time(NULL));
-
- //OBJECTS INIZIALIZATION
- player player1; //player is automatically created in [C/2][R]
- boss bosses[5]; //vector of bosses
- b_list bullets; //list of player's bullets
- b_list bombs; //list of enemies' bombs
- b_list powerups; //list of powerups
- r_list rockets; //list of rockets
- boss boss1;
- std::list<enemy> enemies;
- int refresh_time=100; //how long the program waits before refreshing the screen
- int chflag=0; //cheat flag: 0=normal, 1=cheats allowed.
- int num=0;
- int commands[CMD_NUM]={'a','d','w','s','p',' ','l','m','q'};
-
- 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
- int level=1; //difficulty level
-
- create_std_bosses();
- std::string bossname1=getenv("HOME");
- bossname1=bossname1+RECORD_DIR+BOSS_FILE1+".dat";
- boss newboss1(1,1,100,9,6,BOSS_FILE1);
- newboss1.loadpicture(bossname1.c_str());
- std::string bossname2=getenv("HOME");
- bossname2=bossname2+RECORD_DIR+BOSS_FILE2+".dat";
- boss newboss2(1,1,200,11,5,BOSS_FILE2);
- newboss2.loadpicture(bossname2.c_str());
- std::string bossname3=getenv("HOME");
- bossname3=bossname3+RECORD_DIR+BOSS_FILE3+".dat";
- boss newboss3(1,1,300,9,6,BOSS_FILE3);
- newboss3.loadpicture(bossname3.c_str());
- std::string bossname4=getenv("HOME");
- bossname4=bossname4+RECORD_DIR+BOSS_FILE4+".dat";
- boss newboss4(1,1,400,11,6,BOSS_FILE4);
- newboss4.loadpicture(bossname4.c_str());
- std::string bossname5=getenv("HOME");
- bossname5=bossname5+RECORD_DIR+BOSS_FILE5+".dat";
- boss newboss5(1,1,500,17,5,BOSS_FILE5);
- newboss5.loadpicture(bossname5.c_str());
-
- bosses[0]=newboss1;
- bosses[1]=newboss2;
- bosses[2]=newboss3;
- bosses[3]=newboss4;
- bosses[4]=newboss5;
- boss1=bosses[0];
- boss1.alive=true;
- player1.weaponclass=1;
-
- //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);
- init_pair(9,COLOR_BLACK,COLOR_GREEN);
-
- 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);
-
- 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);
- level = choose_level_bossrush(commands);
- setup_level_bossrush(level, shootrate, refresh_time);
-
- player1.set_commands(commands);
-
- if(level<3)
- player1.weaponclass=2;
- erase();
-
- if(argc>1)
- if(strcmp(argv[1],"--uber-debug")==0){ player1.weaponclass=5; player1.weaponclassrkt=5; player1.rocketlauncher=true; player1.length=MAX_LENGTH; }
-
- std::thread t_draw(draw,std::ref(player1),std::ref(bullets),std::ref(bombs),std::ref(enemies),std::ref(walls),std::ref(powerups),std::ref(rockets),std::ref(boss1));
-
- /////////ENTERING MAIN LOOP
-
- while(1)
- {
- napms(refresh_time); //ncurses sleep function (ms)
- timeout(0);
- command = getch();
-
- if(command!=ERR) //READING INPUT
- command = tolower(command);
-
- if(command == commands[8]){ //q = exit game
- endwin();
- cout<<lightgreen<<"Game exited correctly."<<none<<endl;
- return 1;
- }
- if(command == commands[4])
- pause_game(chflag); //p = pause game
- if(chflag==1) //cheats
- get_cheat(command,player1,enemies,shootrate);
-
- if(command == commands[0] || command == KEY_LEFT || command == commands[1] || command == KEY_RIGHT || ((command == commands[2]|| command == KEY_UP || command == commands[3] || command == KEY_DOWN) && chflag==1)){ //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==commands[5] || command==commands[6]) { //spacebar = shoot!
- player1.shoot(bullets);
- if(player1.rocketlauncher) player1.shootrkt(rockets);
- }
-
- 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*10.)
- 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(!rockets.empty()) //evaluate new bullets' positions
- for(r_list::iterator it=rockets.begin(); it!=rockets.end(); ++it){
- mvaddch(it->y,it->x,' ');
- it->next_pos();
- }
-
- rockets.unique();
- 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()
- interactions(player1,bullets,bombs,enemies,walls,powerups,rockets,boss1,score);
-
-
- if(boss1.health<=0)
- if(num<4){
- score+=250*level*(num+1);
- for(int i=max(0,boss1.y-1);i<min(R-1,boss1.y+boss1.height+1);i++)
- for(int j=0;j<C;j++)
- mvaddch(i,j,' ');
- num++;
- mvwprintw(BossHP,0,1," ");
- if((double)rand()/RAND_MAX<0.25*num){
- if((double)rand()/RAND_MAX<1./POWERUP_RATIO){
- if((double)rand()/RAND_MAX<1./ROCKET_RATIO){
- powerup newpowerup(boss1.x,boss1.y+1,512);
- powerups.push_back(newpowerup);
- }
- else{
- powerup newpowerup(boss1.x,boss1.y+1,128);
- powerups.push_back(newpowerup);
- }
- }
- else{
- powerup newpowerup(boss1.x,boss1.y+1);
- powerups.push_back(newpowerup);
- }
- }
- if(num==4 && player1.weaponclass<3) player1.weaponclass++;
- boss1=bosses[num];
- boss1.alive=true;
- }
- ///////ENDGAME CHECKS
- if(boss1.health<1 && num==4) //YOU WON!!
- {
- Victory_bossrush(boss1.name,score,level,chflag);
-
- WINDOW *replay;
-
- replay=newwin(3,25,26,20);
- box(replay,ACS_VLINE,ACS_HLINE);
-
- switch(playagain(replay)) // playagain() returns 'y'/'n'/'q'
- {
- case 'y':
- delwin(replay);
- timeout(500);
- score=0;
- erase();
- refresh();
- reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
- resetbosses(bosses,boss1,player1);
- num=0;
- if(level<3)
- player1.weaponclass=2;
- erase();
- refresh();
- continue;
- case 'n':
- delwin(replay);
- timeout(500);
- score=0;
- erase();
- refresh();
- level = choose_level_bossrush(commands);
- setup_level_bossrush(level, shootrate, refresh_time);
- reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
- resetbosses(bosses,boss1,player1);
- num=0;
- if(level<3)
- player1.weaponclass=2;
- erase();
- refresh();
- continue;
- case 'q':
- endwin();
- cout<<lightgreen<<"Game exited correctly."<<none<<endl;
- return 0;
- }
- }
- if(gameover(player1,bombs))
- {
- Defeat(score);
-
- WINDOW* replay;
-
- replay=newwin(3,25,17,20);
- box(replay,ACS_VLINE,ACS_HLINE);
-
- switch(playagain(replay)) // playagain() returns 'y'/'n'/'q'
- {
- case 'y':
- delwin(replay);
- timeout(500);
- score=0;
- erase();
- refresh();
- reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
- resetbosses(bosses,boss1,player1);
- num=0;
- if(level<3)
- player1.weaponclass=2;
- erase();
- refresh();
- continue;
- case 'n':
- delwin(replay);
- timeout(500);
- score=0;
- erase();
- refresh();
- level = choose_level_bossrush(commands);
- setup_level_bossrush(level, shootrate, refresh_time);
- reset(player1, enemies, boss1, bullets, bombs, walls, powerups,rockets, level,chflag); // reset box, player, enemy and deletes all bullets and bombs
- resetbosses(bosses,boss1,player1);
- num=0;
- if(level<3)
- player1.weaponclass=2;
- erase();
- refresh();
- continue;
- case 'q':
- 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 0;
- }
|