#include // för Sleep, Beep, etc #include //för cin, cout //#include //för getch #include //för string #include //för vector #include //för filer #include //för finjustering av cout layout: setw(n) #include //for threads using namespace std; #define SCREEN_WIDTH 60 #define SCREEN_HEIGHT 25 #define START_X 10 #define START_Y 23 #define SHIP 30 // This defines ship (pyramid, pointing up): //declare function for drawing playing field: void DrawSpace(CHAR_INFO screenBuffer[], int shipX, int shipY); //declare function for placement/color of cout: void DrawWon(string Str, int X, int Y, WORD color); //declare function for moving mouse: void MouseMove(int x, int y); //declare function for clearing screen: void Eraser(CHAR_INFO screenBuffer[]); bool CheckInput(); //checks user input, if any void HandleGameInput(CHAR_INFO screenBuffer[],COORD &shipPos); //acts on user key presses int DaKeyCode = 0; //holds user key id int bKeyDown = 0; // This tells us if we pressed DOWN a key //Highscores-grejer: vectorvHighscores(25000); //fast vector för highscores vectorvUsers; vectorAllUsersIn; vectoriPointsIn; vectoriPoints; vectorAllUsers; int Placer = 0; int Score = 0; int Empty = 0; string sTest; string sNamn = ""; int Points = 0; int PointsM = 0; //Declare function for highscore list: void fHighscores(void); void play_crash() { PlaySound("mixkit-epic-impact-afar-explosion-2782.wav", NULL, SND_FILENAME|SND_LOOP|SND_ASYNC); } void play_Music() { PlaySound("mixkit-games-music-706_W.wav", NULL, SND_FILENAME| SND_LOOP|SND_ASYNC); } /* void play_alarm() { PlaySound("mixkit-classic-alarm-995.wav", NULL, SND_FILENAME| SND_LOOP|SND_ASYNC); } */ void play_bonus() { PlaySound("mixkit-winning-an-extra-bonus-2060.wav", NULL, SND_FILENAME|SND_LOOP|SND_ASYNC); } /* void play_laser() { PlaySound("mixkit-retro-video-game-bubble-laser-277.wav", NULL,SND_FILENAME|SND_LOOP|SND_ASYNC); } void play_laser2() { PlaySound("mixkit-retro-video-game-bubble-laser-277.wav", NULL, SND_FILENAME); } */ //class definition: class SpaceMon { private: // Private attributes int Armor1 = 2; int Armor2 = 2; int Armor3 = 2; int Armor4 = 2; int Armor5 = 2; int Armor6 = 2; int Armor7 = 2; int Armor8 = 2; int Armor9 = 2; int Armor10 = 2; COORD M1pos = {4,2}; COORD M2pos = {6,2}; COORD M3pos = {8,2}; COORD M4pos = {10,2}; COORD M5pos = {12,2}; COORD M6pos = {14,2}; COORD M7pos = {16,2}; COORD M8pos = {18,2}; COORD M9pos = {20,2}; COORD M10pos = {22,2}; public: // Setters void HitMe(int h) { switch(h) { case 1: Armor1--;break; case 2: Armor2--;break; case 3: Armor3--;break; case 4: Armor4--;break; case 5: Armor5--;break; case 6: Armor6--;break; case 7: Armor7--;break; case 8: Armor8--;break; case 9: Armor9--;break; case 10: Armor10--;break; default: cout << "default hitme" << endl; } } void ResetCoord(int r) { switch(r) { case 1: M1pos = {4,2};break; case 2: M2pos = {6,2};break; case 3: M3pos = {8,2};break; case 4: M4pos = {10,2};break; case 5: M5pos = {12,2};break; case 6: M6pos = {14,2};break; case 7: M7pos = {16,2};break; case 8: M8pos = {18,2};break; case 9: M9pos = {20,2};break; case 10: M10pos = {22,2};break; } } void ResetArmor(int z) { switch(z) { case 1: Armor1 = 2;break; case 2: Armor2 = 2;break; case 3: Armor3 = 2;break; case 4: Armor4 = 2;break; case 5: Armor5 = 2;break; case 6: Armor6 = 2;break; case 7: Armor7 = 2;break; case 8: Armor8 = 2;break; case 9: Armor9 = 2;break; case 10: Armor10 = 2;break; } } void Step(int s) { //each time called: move all coords one step right 3x, then down 1x, then 3x left, etc: switch(s) { case 1:case 2: case 3: case 9: case 10:case 11:case 17:case 18:case 19://walk R case 25: case 26: case 27:case 33:case 34: case 35:case 41: case 42: case 43: { M1pos.X++; M2pos.X++; M3pos.X++; M4pos.X++; M5pos.X ++; M6pos.X++; M7pos.X++; M8pos.X++; M9pos.X++; M10pos.X++; }break; case 4: case 8: case 12: case 16: case 20: case 24: case 28:case 32:case 36://down { M1pos.Y++; M2pos.Y++; M3pos.Y++; M4pos.Y++; M5pos.Y ++; M6pos.Y++; M7pos.Y++; M8pos.Y++; M9pos.Y++; M10pos.Y++; }break; case 48: case 49: case 50:case 51: case 52://down, faster { M1pos.Y++; M2pos.Y++; M3pos.Y++; M4pos.Y++; M5pos.Y ++; M6pos.Y++; M7pos.Y++; M8pos.Y++; M9pos.Y++; M10pos.Y++; M1pos.Y++; M2pos.Y++; M3pos.Y++; M4pos.Y++; M5pos.Y ++; M6pos.Y++; M7pos.Y++; M8pos.Y++; M9pos.Y++; M10pos.Y++; }break; case 5:case 6: case 7: case 13:case 14:case 15: case 21: case 22: case 23: //walk L case 29: case 30: case 31: case 37: case 38: case 39: case 45: case 46:case 47: { M1pos.X--; M2pos.X--; M3pos.X--; M4pos.X--; M5pos.X--; M6pos.X--; M7pos.X--; M8pos.X--; M9pos.X--; M10pos.X--; } break; default:{/*do nothing*/}break; } } // Getters int getArmor(int x) { switch(x) { case 1: return Armor1;break; case 2: return Armor2;break; case 3: return Armor3;break; case 4: return Armor4;break; case 5: return Armor5;break; case 6: return Armor6;break; case 7: return Armor7;break; case 8: return Armor8;break; case 9: return Armor9;break; case 10: return Armor10;break; default: cout << "default getArmor" << endl;break; } //return Armor; } COORD getCoord(int r) { switch(r) { case 1: return M1pos;break; case 2: return M2pos;break; case 3: return M3pos;break; case 4: return M4pos;break; case 5: return M5pos;break; case 6: return M6pos;break; case 7: return M7pos;break; case 8: return M8pos;break; case 9: return M9pos;break; case 10: return M10pos;break; default: cout << "default getCoord" << endl;break; } } }; bool Left; bool Right; bool Shoot; bool M_Shoot; bool Wall; int c = 0; bool Cheat; bool Nuke = false; int main() { CHAR_INFO screenBuffer[SCREEN_WIDTH * SCREEN_HEIGHT] = {0}; COORD bufferSize = {SCREEN_WIDTH , SCREEN_HEIGHT}; COORD shipPos = {START_X, START_Y}; //COORD enemyPos = {2, 2}; //enemy's ship start position COORD oldPosition = shipPos; //declare an object of the class: SpaceMon UpperRow; //int ShotStart = 0; int shotX = 0; int shotY = 23; int oldshotY = 0; //int M_ShotStart = 0; int M_shotX = 0; int M_shotY = 23; int M_oldshotY = 0; //int Time1 = 0; //int Time2 = 0; //int Elapsed = 0; int Shot_Time_1 = 0; int Shot_Time_2 = 0; int ShotElapsed = 0; int M_Shot_Time_1 = 0; int M_Shot_Time_2 = 0; int M_ShotElapsed = 0; int Ship_Time_1 = 0; int Ship_Time_2 = 0; int ShipElapsed = 0; int iStep = 1; int Mon_Time_1 = 0; int Mon_Time_2 = 0; int MonElapsed = 0; int Nuke_Time_1 = 0; int Nuke_Time_2 = 0; int NukeElapsed = 0; //int Mon_that_shoots = 0; COORD Mon_coord; bool Alive; int HitMon = 0; int Level = 1; //ta bort muspilen från spelytan: MouseMove(1, 1); std::thread tM(play_Music); //flashy introskärm: DrawWon("SSSS PPPP EEEE JJJJ SSSS", 10, 4, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("SS S P P E J SS S", 10, 5,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("SS PPPP EEEE J SS ", 10, 6, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon(" SS PP EEEE J J SS", 10, 7, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("S SS PP E J J S SS", 10, 8, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("SSSS PP EEEE JJJJ SSSS", 10, 9, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("********************************", 10, 10, FOREGROUND_RED); DrawWon(" I N V E J D E R S ", 10, 11, FOREGROUND_RED | FOREGROUND_INTENSITY ); //remove cursor: DrawWon(" ", 0, 0, FOREGROUND_RED | FOREGROUND_BLUE ); Sleep(1500); Eraser(screenBuffer); DrawWon("Move ship: left, right arrow keys.", 10, 4, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("Stop ship: down arrow key.", 10, 5, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("Shoot: up arrow key.", 10, 6, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//=white DrawWon("Enter your name: ", 10, 9, FOREGROUND_RED | FOREGROUND_INTENSITY);//=white cin >> sNamn; Eraser(screenBuffer); Sleep(2000); //draw frame: for (int p = 0; p < bufferSize.X; p++) { //rad med punkter längst upp: screenBuffer[p + 1 * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[p + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN; //rad med punkter längst ned: screenBuffer[p + 24 * SCREEN_WIDTH].Char.AsciiChar = '.'; screenBuffer[p + 24 * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN; } //Points sign: screenBuffer[53 + 1 * SCREEN_WIDTH].Char.AsciiChar = 'P'; screenBuffer[53 + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; screenBuffer[54 + 1 * SCREEN_WIDTH].Char.AsciiChar = 'O'; screenBuffer[54 + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; screenBuffer[55 + 1 * SCREEN_WIDTH].Char.AsciiChar = 'I'; screenBuffer[55 + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; screenBuffer[56 + 1 * SCREEN_WIDTH].Char.AsciiChar = 'N'; screenBuffer[56 + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; screenBuffer[57 + 1 * SCREEN_WIDTH].Char.AsciiChar = 'T'; screenBuffer[57 + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; screenBuffer[58 + 1 * SCREEN_WIDTH].Char.AsciiChar ='S'; screenBuffer[58 + 1 * SCREEN_WIDTH].Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; //betongblock: hela: 60 x 25 y //block 1: y 16-22, x 5-10 block 2: y 16-22, x 15-20 block 3: y 16-22, x 25-30 for(int x1 = 5; x1 < 11; x1++ ) { for(int y1 = 18; y1 < 23; y1++) { screenBuffer[x1 + y1 * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[x1 + y1 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;//=white } } for(int x2 = 15; x2 < 21; x2++ ) { for(int y2 = 18; y2 < 23; y2++) { screenBuffer[x2 + y2 * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[x2 + y2 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;//=white } } for(int x3 = 25; x3 < 31; x3++ ) { for(int y3 = 18; y3 < 23; y3++) { screenBuffer[x3 + y3 * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[x3 + y3 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;//=white } } DrawSpace(screenBuffer, shipPos.X, shipPos.Y); //start timers: Shot_Time_1 = GetTickCount(); M_Shot_Time_1 = GetTickCount(); Ship_Time_1 = GetTickCount(); Mon_Time_1 = GetTickCount(); Nuke_Time_1 = GetTickCount(); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); cout << Level; //game loop: while(1) { if(CheckInput()) //if user pressed a key: HandleGameInput(screenBuffer,shipPos); //player moves/shoots, &playerPOS => changes coords also in main //ship movements: //ship movements: //ship movements: Ship_Time_2 = GetTickCount(); ShipElapsed = Ship_Time_2 - Ship_Time_1; if(ShipElapsed > 40)//> 40 msek? { Ship_Time_1 = GetTickCount();//reset ShipElapsed = 0;//reset if((Left) && (shipPos.X > 0)) { oldPosition = shipPos; shipPos.X--; // Erase the old position of ship with a space: screenBuffer[oldPosition.X + oldPosition.Y *SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[oldPosition.X + oldPosition.Y *SCREEN_WIDTH].Attributes = 0; } else if((Right)&& (shipPos.X < SCREEN_WIDTH -1)) { oldPosition = shipPos; shipPos.X++; // Erase the old position of ship with a space: screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Attributes = 0; } }//end if shipelapsed //shots shots shots //shots shots shots //shots shots shots if((Shoot)&&(shotY > 1)) { if(shotY > 22) { shotX = shipPos.X; } //oldshotX = shotX; oldshotY = shotY; Shot_Time_2 = GetTickCount(); ShotElapsed = Shot_Time_2 - Shot_Time_1; if(ShotElapsed > 3)//> 3 msek? { Shot_Time_1 = GetTickCount();//reset ShotElapsed = 0;//reset shotY--; screenBuffer[shotX + shotY * SCREEN_WIDTH].Char.AsciiChar = '*'; screenBuffer[shotX + shotY * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[shotX + oldshotY * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[shotX + oldshotY * SCREEN_WIDTH].Attributes = 0; } }//end if shoot if(shotY == 2)//reset: { screenBuffer[shotX + 2 * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[shotX + 2 * SCREEN_WIDTH].Attributes = 0; Shoot = false; shotY = 23; } // if ship shot hits space monsters: reduce armor, change color, or remove if armor is zero: if( screenBuffer[(shotX) + (shotY - 1) * SCREEN_WIDTH].Char.AsciiChar == '@') { HitMon++; PointsM = PointsM + 20; DrawWon(" ", 59, 1, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << PointsM; for(int blipp = 1; blipp < 11; blipp++) { COORD Eso = UpperRow.getCoord(blipp); if(Eso.X == shotX) { UpperRow.HitMe(blipp);//reduces armor //then check below when draws monsters if zero, red etc } } } //Cheat button (Ctrl) kills all monsters: if(Cheat)//pressed Ctrl { COORD KillThem; //destroy all monsters: for(int ch = 1; ch < 11; ch++) { UpperRow.HitMe(ch); UpperRow.HitMe(ch); //sets armor to zero KillThem = UpperRow.getCoord(ch); //load current coord //erase them from screenbuffer: screenBuffer[KillThem.X + KillThem.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[KillThem.X + KillThem.Y * SCREEN_WIDTH].Attributes = 0; } //reset cheat: Cheat = false; HitMon = 20; //else skips re-load of monsters from top, below! } if(HitMon > 19)//killed all space monsters (2 hits each in 10) { Level++; //level up HitMon = 0; //reset DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); cout << Level; Sleep(250); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << Level; Sleep(250); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); cout << Level; Sleep(250); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_INTENSITY); Sleep(250); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); cout << Level; Sleep(150); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_INTENSITY); Sleep(150); DrawWon("LEVEL ", 65, 1, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); cout << Level; if(Level == 2) { DrawWon("NEW: press space bar to re-build walls.", 15, 2, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); Sleep(2000); } //reset monsters from top: for(int m = 1; m < 11; m++) { UpperRow.ResetCoord(m); } //reset their armor: for(int n = 1; n < 11; n++) { UpperRow.ResetArmor(n); } iStep = 1;//reset }//end if hitmon > 19 //Re-build option, by space bar, old nuke option re-designed: Nuke_Time_2 = GetTickCount(); NukeElapsed = Nuke_Time_2 - Nuke_Time_1; //display nuke re-charge status: if(Level > 1) { if(NukeElapsed < 8000) DrawWon("preparing... ", 65, 4, FOREGROUND_RED); else { DrawWon(" ", 65, 4, FOREGROUND_GREEN | FOREGROUND_INTENSITY);//erase previous DrawWon("Build ready!", 65, 4, FOREGROUND_GREEN | FOREGROUND_INTENSITY); } } if((Nuke)&& (Level > 1) && (NukeElapsed > 8000))//pressed space bar, >= Level 2, time passed { Nuke_Time_1 = GetTickCount();//reset NukeElapsed = 0;//reset Nuke = false; //reset //draw concrete walls again, same color and location: //betongblock: hela: 60 x 25 y //block 1: y 16-22, x 5-10 block 2: y 16-22, x 15-20 block 3: y 16-22, x 25-30 for(int x1 = 5; x1 < 11; x1++ ) { for(int y1 = 18; y1 < 23; y1++) { screenBuffer[x1 + y1 * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[x1 + y1 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;//=white } } for(int x2 = 15; x2 < 21; x2++ ) { for(int y2 = 18; y2 < 23; y2++) { screenBuffer[x2 + y2 * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[x2 + y2 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;//=white } } for(int x3 = 25; x3 < 31; x3++ ) { for(int y3 = 18; y3 < 23; y3++) { screenBuffer[x3 + y3 * SCREEN_WIDTH].Char.AsciiChar = 'X'; screenBuffer[x3 + y3 * SCREEN_WIDTH].Attributes = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;//=white } } DrawSpace(screenBuffer, shipPos.X, shipPos.Y); } //monsters monsters monsters //monsters monsters monsters //monsters monsters monsters Mon_Time_2 = GetTickCount(); MonElapsed = Mon_Time_2 - Mon_Time_1; int walkdelay = 0; switch(Level) //walk faster at higher Level: { case 1: walkdelay = 1000; break; case 2: walkdelay = 700; break; case 3: walkdelay = 500; break; case 4: walkdelay = 300; break; case 5: walkdelay = 100; break; default: walkdelay = 800; break; } if((MonElapsed > walkdelay)&&(iStep < 53)) { iStep++; Mon_Time_1 = GetTickCount();//reset MonElapsed = 0;//reset UpperRow.Step(iStep);//move monsters COORD Esto; for(int i = 1; i < 11; i++)//draw monsters { Esto = UpperRow.getCoord(i); int mhit = UpperRow.getArmor(i); switch(mhit) //BUG: FUNKAR LITE RANDOM, IBLAND HELT BORT, IBLAND OSÅRBAR ETC { //troligen när flyttar suddas gamla, blandas med shot dead case 0: { screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Attributes = 0; }break; case 1: { screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Char.AsciiChar = '@'; screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY; } break; case 2: { screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Char.AsciiChar = '@'; screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY; }break; default: { screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Esto.X + Esto.Y * SCREEN_WIDTH].Attributes = 0; }break; } } //erase previous coord, depending on current direction: if(iStep < 53) { switch(iStep) { case 1:case 2: case 3: case 9: case 10:case 11:case 17:case 18:case 19://walk R case 25: case 26: case 27:case 33:case 34: case 35:case 41: case 42: case 43: { /*M1pos.X++; M2pos.X++; M3pos.X++; M4pos.X++; M5pos.X++; M6pos.X++; M7pos.X++; M8pos.X++; M9pos.X++; M10pos.X++; */ //(just to remind me what the class function looked like here) for(int j = 1; j < 11; j++)//toggle and erase all previous monster-steps: { Esto = UpperRow.getCoord(j); screenBuffer[(Esto.X-1) + Esto.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(Esto.X-1) + Esto.Y * SCREEN_WIDTH].Attributes = 0; } }break; case 4: case 8: case 12: case 16: case 20: case 24: case 28:case 32:case 36://down { /*M1pos.Y++; M2pos.Y++; M3pos.Y++; M4pos.Y++; M5pos.Y++; M6pos.Y++; M7pos.Y++; M8pos.Y++; M9pos.Y++; M10pos.Y++; */ for(int k = 1; k < 11; k++)//toggle and erase all previous monster-steps: { Esto = UpperRow.getCoord(k); screenBuffer[Esto.X + (Esto.Y-1) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Esto.X + (Esto.Y-1) * SCREEN_WIDTH].Attributes = 0; } }break; case 48: case 49: case 50:case 51: case 52://down, faster { /* M1pos.Y++; M2pos.Y++; M3pos.Y++; M4pos.Y++; M5pos.Y++; M6pos.Y++; M7pos.Y++; M8pos.Y++; M9pos.Y++; M10pos.Y++; M1pos.Y++; M2pos.Y++; M3pos.Y++; M4pos.Y++; M5pos.Y ++; M6pos.Y++; M7pos.Y++; M8pos.Y++; M9pos.Y++; M10pos.Y++; */ for(int n = 1; n < 11; n++)//toggle and erase all previous monster-steps: { Esto = UpperRow.getCoord(n); screenBuffer[Esto.X + (Esto.Y-2) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[Esto.X + (Esto.Y-2) * SCREEN_WIDTH].Attributes = 0; } }break; case 5:case 6: case 7: case 13:case 14:case 15: case 21: case 22: case 23: //walk L case 29: case 30: case 31: case 37: case 38: case 39: case 45: case 46:case 47: { /* M1pos.X--; M2pos.X--; M3pos.X--; M4pos.X--; M5pos.X--; M6pos.X--; M7pos.X--; M8pos.X--; M9pos.X--; M10pos.X--; */ for(int m = 1; m < 11; m++)//toggle and erase all previous monster-steps: { Esto = UpperRow.getCoord(m); screenBuffer[(Esto.X+1) + Esto.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[(Esto.X+1) + Esto.Y * SCREEN_WIDTH].Attributes = 0; } } break; default: {/*do nothing */} break; }//ens sw istep }//end if istep < 53 }//end if mon-elapsed > //MONSTER SHOOT, a random monster that was not killed shoots: if(! M_Shoot) //true means shot already in progress { srand(GetTickCount()); //'seeding' the rand function with tick count int Mon_that_shoots = ((rand() % 10) + 1); // 1-10 switch(Mon_that_shoots) { case 1: { if(UpperRow.getArmor(1) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(1); M_shotY = Mon_coord.Y + 1; } }break; case 2: { if(UpperRow.getArmor(2) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(2); M_shotY = Mon_coord.Y + 1; } }break; case 3: { if(UpperRow.getArmor(3) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(3); M_shotY = Mon_coord.Y + 1; } }break; case 4: { if(UpperRow.getArmor(4) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(4); M_shotY = Mon_coord.Y + 1; } }break; case 5: { if(UpperRow.getArmor(5) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(5); M_shotY = Mon_coord.Y + 1; } }break; case 6: { if(UpperRow.getArmor(6) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(6); M_shotY = Mon_coord.Y + 1; } }break; case 7: { if(UpperRow.getArmor(7) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(7); M_shotY = Mon_coord.Y + 1; } }break; case 8: { if(UpperRow.getArmor(8) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(8); M_shotY = Mon_coord.Y + 1; } }break; case 9: { if(UpperRow.getArmor(9) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(9); M_shotY = Mon_coord.Y + 1; } }break; case 10: { if(UpperRow.getArmor(10) > 0) {Alive = true; M_Shoot = true; Mon_coord = UpperRow.getCoord(10); M_shotY = Mon_coord.Y + 1; } }break; default: {cout << "default sw mon shoot" << endl; } break; }//end switch }//end if ! mshoot if(M_shotY < 24) { if(M_shotY < 22) { M_shotX = Mon_coord.X; } M_oldshotY = M_shotY; M_Shot_Time_2 = GetTickCount(); M_ShotElapsed = M_Shot_Time_2 - M_Shot_Time_1; int Mshootdelay = 0; switch(Level) //faster monster shots at higher Levels: { case 1: Mshootdelay = 200; break; case 2: Mshootdelay = 150; break; case 3: Mshootdelay = 100; break; case 4: Mshootdelay = 80; break; case 5: Mshootdelay = 50; break; } if((M_ShotElapsed > Mshootdelay)&&(!Wall))//> 100 msek? and not hit wall { M_Shot_Time_1 = GetTickCount();//reset M_ShotElapsed = 0;//reset M_shotY++; screenBuffer[M_shotX + M_shotY * SCREEN_WIDTH].Char.AsciiChar = 'v'; screenBuffer[M_shotX + M_shotY * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white screenBuffer[M_shotX + M_oldshotY * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[M_shotX + M_oldshotY * SCREEN_WIDTH].Attributes = 0; } }//end if M shoot if((M_shotY == 23)||(Wall))//reset when run all distance or hit wall: { screenBuffer[M_shotX + 23 * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[M_shotX + 23 * SCREEN_WIDTH].Attributes = 0; M_Shoot = false; //reset M_shotY = 1; //reset Wall = false; //reset } //space monster shot hit the walls: if( screenBuffer[(M_shotX) + (M_shotY + 1) * SCREEN_WIDTH].Char.AsciiChar == 'X') { Wall = true; screenBuffer[M_shotX + M_shotY * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[M_shotX + M_shotY * SCREEN_WIDTH].Attributes = 0; screenBuffer[M_shotX + (M_shotY + 1) * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[M_shotX + (M_shotY + 1) * SCREEN_WIDTH].Attributes = 0; } //if enemies crash into ship: if(( screenBuffer[(shipPos.X) + (shipPos.Y - 1) * SCREEN_WIDTH].Char.AsciiChar == '@') ||(screenBuffer[(shipPos.X) + (shipPos.Y - 2) * SCREEN_WIDTH].Char.AsciiChar == '@') ||( screenBuffer[(shipPos.X + 1 ) + (shipPos.Y) * SCREEN_WIDTH].Char.AsciiChar == '@') ||( screenBuffer[(shipPos.X - 1 ) + (shipPos.Y) * SCREEN_WIDTH].Char.AsciiChar == '@') ||( screenBuffer[(shipPos.X + 2 ) + (shipPos.Y) * SCREEN_WIDTH].Char.AsciiChar == '@') ||( screenBuffer[(shipPos.X - 2 ) + (shipPos.Y) * SCREEN_WIDTH].Char.AsciiChar == '@') //or if they shoot the ship: ||( screenBuffer[(shipPos.X) + (shipPos.Y - 1) * SCREEN_WIDTH].Char.AsciiChar == 'v') //of if space monsters hit floor: || (iStep > 51) ) { tM.join(); std::thread tC(play_crash); system("color E2");//ljusgul Sleep(100); system("color 8");//mörkgrå Sleep(100); tC.join(); Sleep(1000); Eraser(screenBuffer); Points = PointsM; //for highscore list //change to bright white: DrawWon(" ", 5, 5, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); fHighscores(); std::thread tBo(play_bonus); Sleep(3000); tBo.join(); return(0); }//end if enemies crash into or shoot ship Sleep(2);//then regulate individual speeds as slower than this, using get tick count DrawSpace(screenBuffer, shipPos.X, shipPos.Y); }//end while 1 return 0; }//end main //////////////////////////////// DRAW SPACE ///////////////////////////////// ///// ///// //////////////////////////////// DRAW SPACE ///////////////////////////////// void DrawSpace(CHAR_INFO screenBuffer[], int shipX, int shipY) { SMALL_RECT drawRect = {0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1}; COORD bufferSize = {SCREEN_WIDTH , SCREEN_HEIGHT}; COORD zeroZero = {0, 0}; HANDLE hOutput; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); // Get an OUTPUT handle to screen (Permission/key to draw). if((shipX == 1)&&(shipY == 55)) { //show nothing!(when crashed) } else //draw ship { screenBuffer[shipX + shipY * SCREEN_WIDTH].Char.AsciiChar = SHIP; screenBuffer[shipX + shipY * SCREEN_WIDTH].Attributes = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;//=white } // draws buffer to screen: WriteConsoleOutput(hOutput, screenBuffer, bufferSize, zeroZero, &drawRect); }//end draw space //////////////////////////////// DRAW Won ///////////////////////////////// //for displaying current points etc //////////////////////////////// DRAW Won ///////////////////////////////// void DrawWon(string Str, int X, int Y, WORD color) { HANDLE OutputH; COORD position = {X, Y}; OutputH = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(OutputH, color); SetConsoleCursorPosition(OutputH, position); cout << Str; //display won or lost }//end draw won //move mouse pointer away from game screen-function: void MouseMove(int x, int y) { double fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN) - 1; double fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN) - 1; double fx = x*(65535.0f / fScreenWidth); double fy = y*(65535.0f / fScreenHeight); INPUT Input = { 0 }; Input.type = INPUT_MOUSE; Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; Input.mi.dx = fx; Input.mi.dy = fy; ::SendInput(1, &Input, sizeof(INPUT)); }//end function move mouse //funktion för highscorelistan: //////////////// FUNCTION HIGHSCORES ///////////////////////////////////////// //////////////////////////////////////////////////////////////////// ////////////// void fHighscores(void) //BUG: when two have same scores, incorrect vector content mismatch when loaded back in! { if (Points < 1) Points = 1; //annars vektorkrash //uppdatera highscorelista från gamla filer, printa sedan ny: //retreive stored names in order: ifstream finStrings("NameScores.txt"); if (!finStrings) { ofstream foutStrings("NameScores.txt"); foutStrings.close(); } while (finStrings >> sTest) AllUsersIn.push_back(sTest);//the list has already been sorted in order, but push_back reverses it!!! Now need to reverse it again: finStrings.close(); //same thing, but for stored scores; int Tempoint = 0; ifstream finInts("IntScores.txt"); if (!finInts) { ofstream foutInts("IntScores.txt"); foutInts.close(); } while (finInts >> Tempoint) iPointsIn.push_back(Tempoint);//already been sorted in order, push_back reverses finInts.close(); int est = 0; // re-assemble the past highscore list: for (int n = 0; n < AllUsersIn.size(); n++)// { //est = 200 - iPointsIn[n]; est = iPointsIn[n]; vHighscores[est] = AllUsersIn[n]; //put name at [points in] position, biggest first }//end for n //Load current name to pre-existing lists: if (Points > 25000) { Points = 25000; }//så inte går över max Points = (25000 - Points); //omdefinierat så hamnar högt upp på listan med hög poäng if (vHighscores[Points].empty())//om ledigt... vHighscores[Points] = sNamn; //sätt namnet där, vid sin poäng! //Tar bort delade platser, blir bugg när laddar in sparade filer igen då; olika vektorstorlakar. //Kompensera med poäng även baserad på steg; mer osannolikt att flera får samma poäng. //else //{//om redan finns nån med samma poäng, sätt på samma plats: //string sDelad = vHighscores[Points] + " OCH " + sNamn;//string = string + string funkar! //vHighscores[Points] = sDelad; //} //store the now udated names and points in files: ofstream foutStoreN("NameScores.txt"); for (int p = 0; p < vHighscores.size(); p++) { // string sOutAll = AllUsers[p]; if (vHighscores[p].empty()) Empty++; //do not print empty positions else { string sOutAll = vHighscores[p]; foutStoreN << sOutAll << endl; } } foutStoreN.close(); ofstream foutStoreI("IntScores.txt"); //for(int q = 0; q < iPoints.size(); q++) for (int q = 0; q < vHighscores.size(); q++) { if (vHighscores[q].empty()) Empty++; //do not print empty positions else { foutStoreI << q << endl; } }//end for q foutStoreI.close(); //output sHighscores vector to Highskor.txt file: ofstream fHigh("Highskor.txt"); //inte ::app, vill ha ny varje gång //use only those positions that are occupied with a name!: //the for loops also serve to reverse the order, printing last first...: fHigh << " HIGHSCORES:" << endl; for (int y = 0; y < vHighscores.size(); y++)// { if (vHighscores[y].empty()) Empty++;//do not print empty positions else { Placer++;//translate to first, second, third etc place! // and translate to a high score for the best: int Score = 25000 - y; // \t är tabulering, sätter ut ett stort mellanrum: if (Placer < 11)//only top 10 on Highscore list { fHigh << Placer << ":" << "\t" << vHighscores[y] << " (" << Score << " poeng)." << endl; } }//end else Placer }// end for y fHigh.close(); Placer = 0; //Visa highscorelista på skärmen också: //But only top 10 on Highscore list!: cout << endl; cout << "*********************************" << endl; cout << " HIGHSCORES:" << endl; for (int z = 0; z < vHighscores.size(); z++)// { if (vHighscores[z].empty()) Empty++;//do not print empty positions else { Placer++;//translate to first, second, third etc place! // and translate to a high score for the best: int screenScore = 25000 - z; if (Placer < 11)//only top 10 on Highscore list { cout << setw(3) << Placer << ":" << "\t" << vHighscores[z] << " (" << screenScore << " poeng)." << endl; } }//end else Placer }// end for z Placer = 0; cout << "*********************************" << endl; Sleep(3000); }//end funktion highscores //////////////////////////////////////////////////////////////////// //////////E R A S E R ///////////////////////////////////////// //////////E R A S E R ///////////////////////////////////////// //////////////////////////////////////////////////////////////////// void Eraser(CHAR_INFO screenBuffer[]) { for(int i = 0; i < SCREEN_WIDTH; i++) { for(int j = 0; j < SCREEN_HEIGHT; j++) { screenBuffer[i + j * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[i + j * SCREEN_WIDTH].Attributes = 0; }//end for j }//end for i DrawSpace(screenBuffer, 1, 1); } //end Eraser //////////////////////// check input //////////////////////////////////////// //////////////////CHECK INPUT////////////////////////////////////////////// bool CheckInput() { DWORD events=0; // input events HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); //handle for checking input INPUT_RECORD InputRecord; GetNumberOfConsoleInputEvents(hInput, &events); if(!events) return false; ReadConsoleInput(hInput, &InputRecord, 1, &events); bKeyDown = InputRecord.Event.KeyEvent.bKeyDown; DaKeyCode = InputRecord.Event.KeyEvent.wVirtualKeyCode; return true; } ////////////////////// Handle Input//////////////////////////////////// //************************************************************************// ////////////////////// Handle Input//////////////////////////////////// void HandleGameInput(CHAR_INFO screenBuffer[],COORD &shipPos) //reference &playerPOS => also changes in main! { COORD oldPosition = shipPos; if((DaKeyCode > 0) && (bKeyDown > 0)) { if(DaKeyCode == VK_UP) { // Shoot Shoot = true; Beep(650,25); PointsM--; //rewards accuracy, and helps generate spread in highscore list DrawWon(" ", 59, 1, FOREGROUND_RED | FOREGROUND_INTENSITY); cout << PointsM; }//end vk up else if(DaKeyCode == VK_DOWN) { // Stop Right = false; Left = false; }//end vk up else if(DaKeyCode == VK_LEFT) { // Fly left: if(shipPos.X > 0) // Check new position doesn't go outside of buffer { Left = true; Right = false; // LEFT } }// end vk left else if(DaKeyCode == VK_RIGHT) { // Fly right if(shipPos.X < (SCREEN_WIDTH - 1) ) { Right = true; Left = false; // RIGHT } }//end vk right else if(DaKeyCode == VK_SPACE) // If space bar is pressed; Nuke { //tests:disabled Nuke = true; } else if(DaKeyCode == VK_CONTROL) //cheat button, kills all, go to next level { Cheat = true; } if(DaKeyCode == VK_RIGHT || DaKeyCode == VK_LEFT || DaKeyCode == VK_UP || DaKeyCode == VK_DOWN ) { // Erase the old position with a space: screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Char.AsciiChar = ' '; screenBuffer[oldPosition.X + oldPosition.Y * SCREEN_WIDTH].Attributes = 0; } } }//end handle input