Z0OM

Tetris 2021

May 8th, 2021 (edited)
830
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <Windows.h>
  2. #include <thread>
  3. #include <chrono>
  4. #include <math.h>
  5.  
  6. struct Vector{int x, y;};
  7.  
  8. struct Console{
  9.     Vector size;
  10. private:
  11.     char* screen;
  12.     HANDLE hConsole;
  13.     DWORD bytesWritten;
  14.  
  15. public:
  16.     Console(int x, int y);
  17.     ~Console();
  18.     void sleep(int time);
  19.     void clear();
  20.     void draw(int x, int y, char c);
  21.     void draw(int x, int y, const char* str, int size);
  22.     void display();
  23. };
  24. Console console(120, 40);
  25.  
  26. Vector fieldSize{30, 25};
  27. char field[25 * 30];
  28. Vector fieldPos{10,3};
  29.  
  30. std::string shapes[7] =
  31. {
  32.     "..#."
  33.     "..#."
  34.     "..#."
  35.     "..#.",
  36.  
  37.     "...."
  38.     ".##."
  39.     ".##."
  40.     "....",
  41.  
  42.     "...."
  43.     "..#."
  44.     "..#."
  45.     ".##.",
  46.  
  47.     "...."
  48.     ".#.."
  49.     ".#.."
  50.     ".##.",
  51.  
  52.     "...."
  53.     "..##"
  54.     ".##."
  55.     "....",
  56.  
  57.     "...."
  58.     "##.."
  59.     ".##."
  60.     "....",
  61.  
  62.     "...."
  63.     ".#.."
  64.     "###."
  65.     "...."
  66. };
  67. std::string curShape, nextShape;
  68. Vector curPos{fieldSize.x/2 - 2, 1}, nextPos{50, 10};
  69.  
  70. int score = 0;
  71.  
  72. std::string rotate(const std::string& shape);
  73. void drawField();
  74. void drawShape();
  75. bool isShapeColliding();
  76. void updateField();
  77. void resetShape();
  78. void displayScore();
  79. void displayCredits(int x);
  80. char wallCharacter = '\xDB';
  81.  
  82. void start()
  83. {
  84.     console.clear();
  85.     srand(time(NULL));
  86.     nextShape = shapes[rand()%7];
  87.     score = 0;
  88.  
  89.     for(int i = 0; i < fieldSize.x; i++){
  90.         field[(fieldSize.y - 1)*fieldSize.x + i] = '\xDB';
  91.     }
  92.     for(int i = 0; i < fieldSize.y; i++){
  93.         field[i*fieldSize.x] = '\xDB'; field[(i+1)*fieldSize.x - 1] = '\xDB';
  94.     }
  95.     for(int i = 1; i < fieldSize.y - 1; i++)
  96.         for(int j = 1; j < fieldSize.x - 1; j++)
  97.             field[i*fieldSize.x + j] = 0;
  98.  
  99.     resetShape();
  100.     int fallSpeed = 10, moveSpeed = 2, quickFallSpeed = 5;
  101.     int fallCounter = 0, moveCounter = 0, quickFallCounter = 0;
  102.     int level = 1, levelCounter = 0;
  103.     bool isRunning = true;
  104.     while(isRunning){
  105.         console.sleep(50);
  106.  
  107.         if(GetAsyncKeyState(VK_ESCAPE))isRunning = false;
  108.  
  109.         fallCounter++;
  110.         if(fallCounter == fallSpeed){
  111.             fallCounter = 0;
  112.             curPos.y++;
  113.             if(isShapeColliding()){
  114.                 moveCounter = 0;
  115.                 curPos.y--;
  116.                 updateField();
  117.                 resetShape();
  118.                 isRunning = !isShapeColliding();
  119.             }
  120.         }
  121.         moveCounter++;
  122.         if(moveCounter == moveSpeed){
  123.             moveCounter = 0;
  124.             if(GetAsyncKeyState(VK_DOWN)){
  125.                 curPos.y++;
  126.                 if(isShapeColliding())curPos.y--;
  127.             }
  128.             else if(GetAsyncKeyState(VK_LEFT)){
  129.                 curPos.x--;
  130.                 if(isShapeColliding())curPos.x++;
  131.             }
  132.             else if(GetAsyncKeyState(VK_RIGHT)){
  133.                 curPos.x++;
  134.                 if(isShapeColliding())curPos.x--;
  135.             }
  136.             else if(GetAsyncKeyState(VK_SHIFT)){
  137.                 std::string s = rotate(curShape), t = curShape;
  138.                 curShape = s;
  139.                 if(isShapeColliding())curShape = t;
  140.             }
  141.         }
  142.         quickFallCounter++;
  143.         if(quickFallCounter == quickFallSpeed){
  144.             quickFallCounter = 0;
  145.             if(GetAsyncKeyState(VK_SPACE)){
  146.                 while(!isShapeColliding())curPos.y++;
  147.                 curPos.y--;
  148.                 fallCounter = 0;
  149.                 moveCounter = 0;
  150.                 updateField();
  151.                 resetShape();
  152.                 isRunning = !isShapeColliding();
  153.             }
  154.         }
  155.         console.clear();
  156.         displayCredits(80);
  157.         drawShape();
  158.         drawField();
  159.         displayScore();
  160.         console.display();
  161.     }
  162. }
  163.  
  164. int main()
  165. {
  166.     bool isRunning = true;
  167.  
  168.     Vector tet[5] = {{0,0}, {0,-5}, {0,-10}, {0,-15}, {0,-20}};
  169.     int index = 0;
  170.     int counter = 0;
  171.     tet[0].x = rand()%24;
  172.     while(isRunning){
  173.         console.sleep(100);
  174.  
  175.         counter++;
  176.         if(counter == 5){
  177.             counter = 0;
  178.             index++;
  179.             if(index == 5)index = 0;
  180.             tet[index].x = rand()%24;
  181.             tet[index].y = 0;
  182.         }
  183.         console.clear();
  184.  
  185.         for(int i = 0; i < 5; i++){
  186.             if(tet[i].y >=0 )console.draw(tet[i].x, tet[i].y, "TETRIS", 6);
  187.             tet[i].y++;
  188.         }
  189.  
  190.         displayCredits(50);
  191.         if(GetAsyncKeyState(VK_RETURN))isRunning = false;
  192.  
  193.         console.display();
  194.     }
  195.  
  196.     bool gameOver = false;
  197.     if(!isRunning){
  198.         start();
  199.         gameOver = true;
  200.     }
  201.  
  202.     while(gameOver){
  203.         console.sleep(50);
  204.         if(GetAsyncKeyState(VK_ESCAPE))gameOver = false;
  205.         else if(GetAsyncKeyState(VK_RETURN))start();
  206.         console.draw(50, 25, "GAME OVER!", 10);
  207.         console.draw(45, 27, "Press Enter To Restart.", 23);
  208.         displayScore();
  209.         console.display();
  210.     }
  211. }
  212.  
  213. std::string rotate(const std::string& shape)
  214. {
  215.     std::string s = "................";
  216.     for(int i = 0; i < 16; i++){
  217.         int x = i%4;
  218.         int y = i/4;
  219.         s[i] = shape[12 + y - 4*x];
  220.     }
  221.  
  222.     return s;
  223. }
  224.  
  225. void displayCredits(int x)
  226. {
  227.     console.draw(x, 10, "MADE BY : MUKUL SINGH", 21);
  228.     console.draw(x, 11, "May 7/8 2021", 12);
  229.  
  230.     console.draw(x, 13, "In Game Controls :", 18);
  231.     console.draw(x, 14, "Left : LEFT ARROW", 17);
  232.     console.draw(x, 15, "Right : RIGHT ARROW", 19);
  233.     console.draw(x, 16, "Down : DOWN ARROW", 17);
  234.     console.draw(x, 17, "Fall : SPACE", 12);
  235.     console.draw(x, 18, "Rotate : SHIFT", 14);
  236.     console.draw(x, 19, "Exit : ESCAPE", 13);
  237.  
  238. }
  239.  
  240. void resetShape()
  241. {
  242.     curShape = nextShape;
  243.     nextShape = shapes[rand()%7];
  244.     curPos = {fieldSize.x/2 - 2, 1};
  245. }
  246.  
  247. void updateField()
  248. {
  249.      for(int i = 0; i < 16; i++){
  250.         int fi = (curPos.y + i/4) * fieldSize.x + curPos.x + i%4;
  251.         if(curShape[i] == '#')field[fi] = '\xDB';
  252.     }
  253.  
  254.     int score_count = 0;
  255.  
  256.     for(int i = 1; i < fieldSize.y-1; i++){
  257.         bool line = true;
  258.         for(int j = 1; j < fieldSize.x-1 && line; j++){
  259.             line = field[i*fieldSize.x + j] == '\xDB';
  260.         }
  261.         if(line){
  262.             score_count++;
  263.             for(int _i = i; _i > 0; _i--){
  264.                 for(int j = 1; j < fieldSize.x-1; j++){
  265.                     field[_i*fieldSize.x + j] = field[(_i-1)*fieldSize.x + j];
  266.                 }
  267.             }
  268.         }
  269.     }
  270.  
  271.     if(score_count)score += (log2(score_count) + 1) * (500);
  272. }
  273.  
  274. void displayScore()
  275. {
  276.     console.draw(50, 20, "SCORE :", 7);
  277.     std::string str = std::to_string(score);
  278.     console.draw(58, 20, str.c_str(), str.size());
  279. }
  280.  
  281. bool isShapeColliding()
  282. {
  283.     for(int i = 0; i < 16; i++){
  284.         int fi = (curPos.y + i/4) * fieldSize.x + curPos.x + i%4;
  285.         if(curShape[i] == '#' && field[fi] == '\xDB')return true;
  286.     }
  287.     return false;
  288. }
  289.  
  290. void drawShape()
  291. {
  292.     for(int i = 0; i < 16; i++){
  293.         if(curShape[i] == '#')
  294.             console.draw(fieldPos.x + curPos.x + i%4, fieldPos.y + curPos.y + i/4, curShape[i]);
  295.         if(nextShape[i] == '#')
  296.             console.draw(i%4 + nextPos.x,i/4 + nextPos.y, nextShape[i]);
  297.     }
  298.     console.draw(nextPos.x, nextPos.y-1, "NEXT SHAPE :", 12);
  299. }
  300.  
  301. void drawField()
  302. {
  303.     for(int i = 0; i < fieldSize.y * fieldSize.x; i++){
  304.         if(field[i])console.draw(i%fieldSize.x + fieldPos.x, i/fieldSize.x + fieldPos.y, field[i]);
  305.     }
  306. }
  307.  
  308. Console::Console(int x, int y)
  309. {
  310.     size = {x, y};
  311.     screen = new char[size.x * size.y];
  312.     hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
  313.     SetConsoleActiveScreenBuffer(hConsole);
  314.     bytesWritten = 0;
  315. }
  316.  
  317. Console::~Console()
  318. {
  319.     delete screen;
  320. }
  321.  
  322. void Console::sleep(int time)
  323. {
  324.     std::this_thread::sleep_for(std::chrono::milliseconds(time));
  325. }
  326.  
  327. void Console::clear()
  328. {
  329.     for(int i = 0; i < size.x; i++){
  330.         for(int j = 0; j < size.y; j++){
  331.             screen[i*size.y + j] = ' ';
  332.         }
  333.     }
  334. }
  335.  
  336. void Console::draw(int x, int y, char c){
  337.     screen[y*size.x + x] = c;
  338. }
  339.  
  340. void Console::draw(int x, int y, const char* str, int size)
  341. {
  342.     for(int i = 0; i < size; i++){
  343.         console.draw(x + i, y, str[i]);
  344.     }
  345. }
  346.  
  347. void Console::display()
  348. {
  349.     screen[size.x*size.y - 1] = '\0';
  350.     WriteConsoleOutputCharacter(hConsole, screen, size.x * size.y, {0, 0}, &bytesWritten);
  351. }
  352.  
RAW Paste Data