Тетрис на C++ с библиотекой SFML2

Introduction

Contents
Introduction
Код
Видео

Код

#include <SFML/Graphics.hpp> #include <iostream> #include <time.h> #include <string> const int field_height = 25; // высота игрового поля const int field_width = 15; // ширина игрового поля int field[field_height][field_width] { }; // игровое поле // Массив фигурок-тетрамино int figures[7][4] = { 1,3,5,7, // I 2,4,5,7, // S 3,5,4,6, // Z 3,5,4,7, // T 2,3,5,7, // L 3,5,7,6, // J 2,3,4,5, // O }; int checkLine(int& userPoints) { //----ПРОВЕРКА ЛИНИИ----// int k = field_height - 1; // строка k - самая нижняя for (int i = field_height - 1; i > 0; i--) // i пробегает все строки снизу вверх. // в начале k и i совпадают { int count = 0; for (int j = 0; j < field_width; j++) { if (field[i][j]) { count++; } field[k][j] = field[i][j]; } if (count < field_width) { k--; } else { userPoints += 1; } // k уменьшится только если линия не занята полностью // если линия занята полностью, то следующее i // уже соответствует более высокой строке // а k всё ещё на полной строке // строка k будет перезаписана следующей строкой i } return userPoints; } class Tetramino { public: int color { }; int type { }; int blockPositions[4] { }; struct Coordinates { int x; int y; }; Coordinates coordinates[4]{ }; int figures[7][4] = { 1,3,5,7, // I 2,4,5,7, // S 3,5,4,6, // Z 3,5,4,7, // T 2,3,5,7, // L 3,5,7,6, // J 2,3,4,5, // O }; void create() { std::cout << "new tetramino created" << std::endl; color = 1 + rand() % 7; type = rand() % 7; for (int i = 0; i < 4; i++) { blockPositions[i] = figures[type][i]; } for (int i = 0; i < 4; i++) { coordinates[i].x = blockPositions[i] % 2 + 7; // сдвигаем стартовую позицию ближе к центру с помощью + 7 coordinates[i].y = blockPositions[i] / 2; } }; void draw(sf::RenderWindow& thatWindow, sf::Sprite& thatSprite, int marginLeft, int marginTop) { // Рисуем тетрамино из класса Tetramino for (int i = 0; i < 4; i++) { // Разукрашиваем тетрамино thatSprite.setTextureRect(sf::IntRect(color * 18, 0, 18, 18)); // Устанавливаем позицию каждого кусочка тетрамино thatSprite.setPosition(coordinates[i].x * 18, coordinates[i].y * 18); thatSprite.move(marginLeft, marginTop); // смещение // Отрисовка спрайта thatWindow.draw(thatSprite); } }; bool check() { for (int i = 0; i < 4; i++) { if (coordinates[i].x < 0 || coordinates[i].x >= field_width || coordinates[i].y >= field_height) { std::cout << std::endl << "field X" << coordinates[i].x << "Y " << coordinates[i].y << "is out of board" << std::endl; return false; } else if (field[coordinates[i].y][coordinates[i].x]) { std::cout << std::endl << "field X" << coordinates[i].x << "Y " << coordinates[i].y << "is occupied" << std::endl; return false; } } return true; } void moveDown(sf::RenderWindow& thatWindow) { int x[4]{}; int y[4]{}; for (int i = 0; i < 4; i++) { y[i] = coordinates[i].y; x[i] = coordinates[i].x; } for (int i = 0; i < 4; i++) { coordinates[i].y += 1; } if (check() == false) { std::cout << "stop here" << std::endl; for (int i = 0; i < 4; i++) { coordinates[i].y = y[i]; std::cout << "coloring the field" << std::endl; field[y[i]][x[i]] = color; } create(); if (check() == false) { std::cout << "GAME OVER " << std::endl; thatWindow.close(); } } else { ; } } void moveHoriz(sf::RenderWindow& thatWindow, int direction) { int x[4]{}; int y[4]{}; for (int i = 0; i < 4; i++) { y[i] = coordinates[i].y; x[i] = coordinates[i].x; } for (int i = 0; i < 4; i++) { coordinates[i].x += direction; } if (check() == false) { for (int i = 0; i < 4; i++) { coordinates[i].x = x[i]; } } else { ; } } void rotate() { int x[4]{}; int y[4]{}; for (int i = 0; i < 4; i++) { y[i] = coordinates[i].y; x[i] = coordinates[i].x; } int originX = coordinates[1].x; // указываем X центра вращения int originY = coordinates[1].y; // указываем Y центра вращения for (int i = 0; i < 4; i++) { int dy = coordinates[i].y - originY; // y - y0 int dx = coordinates[i].x - originX; // x - x0 coordinates[i].x = originX - dy; // x_2 = x_0 - dy coordinates[i].y = originY + dx; // y_2 = y_0 + dx } if (check() == false) { for (int i = 0; i < 4; i++) { coordinates[i].x = x[i]; } } else { ; } } }; int main() { srand(time(0)); int window_width{ 640 }; int window_height{ 960 }; int userPoints{ 0 }; Tetramino tetramino; tetramino.create(); sf::RenderWindow window(sf::VideoMode(window_width, window_height), "HH Tetris!"); // Создание и загрузка текстуры sf::Texture texture, texture_background, texture_frame; texture.loadFromFile("C:\Users\andrei\source\repos\tetris\images\corona_tiles.png"); texture_background.loadFromFile("C:\Users\andrei\source\repos\tetris\images\background.png"); texture_frame.loadFromFile("C:\Users\andrei\source\repos\tetris\images\frame.png"); // Создание спрайта sf::Sprite sprite(texture), sprite_background(texture_background), sprite_frame(texture_frame); // Вырезаем из спрайта отдельный квадратик размером 18х18 пикселей sprite.setTextureRect(sf::IntRect(0, 0, 18, 18)); // Переменные для таймера и задержки float timer = 0; float delay = 0.3; // Часы (таймер) sf::Clock clock; // Главный цикл приложения: выполняется, пока открыто окно while (window.isOpen()) { // Получаем время, прошедшее с начала отсчёта, и конвертируем его в секунды float time = clock.getElapsedTime().asSeconds(); clock.restart(); timer += time; // Обрабатываем события в цикле sf::Event event; while (window.pollEvent(event)) { // Пользователь нажал на «крестик» и хочет закрыть окно? if (event.type == sf::Event::Closed) // тогда закрываем его window.close(); // Была ли нажата клавиша на клавиатуре? if (event.type == sf::Event::KeyPressed) { // Эта кнопка – стрелка влево? if (event.key.code == sf::Keyboard::Left) { tetramino.moveHoriz(window, -1); } // Или стрелка вправо? else if (event.key.code == sf::Keyboard::Right) { tetramino.moveHoriz(window, 1); } // Или может стрелка вверх? else if (event.key.code == sf::Keyboard::Up) { tetramino.rotate(); } } // Нажали на кнопку "Вниз" ? Ускоряем падение тетрамино if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) delay = 0.05; } // Движение тетрамино вниз («тик» таймера) if (timer > delay) { tetramino.moveDown(window); timer = 0; } checkLine(userPoints); delay = 0.3; //----ОТРИСОВКА----// // Задаём цвет фона - белый window.clear(sf::Color::White); // Отрисовка фона //window.draw(sprite_background); int tetrisFeildTop{ 150 }; int tetrisFeildLeft{ 185 }; for (int varHeight = 0; varHeight < field_height; varHeight++) { for (int j = 0; j < field_width; j++) { if (field[varHeight][j] == 0) { //std::cout << "empty field" << std::endl; sprite.setTextureRect(sf::IntRect(8 * 18, 0, 18, 18)); sprite.setPosition(tetrisFeildLeft + j * 18, tetrisFeildTop + varHeight * 18); // Отрисовка спрайта window.draw(sprite); } else { sprite.setTextureRect(sf::IntRect(field[varHeight][j] * 18, 0, 18, 18)); // значение каждого поля field[varHeight][j] это цвет, его мы используем //для выбора цветного квадратика из спрайта } sprite.setPosition(tetrisFeildLeft + j * 18, tetrisFeildTop + varHeight * 18); //sprite.move(28, 31); // смещение window.draw(sprite); } } // Рисуем тетрамино с помощью метода draw из класса Tetramino tetramino.draw(window, sprite, tetrisFeildLeft, tetrisFeildTop); // Отрисовка фрейма //window.draw(sprite_frame); sf::Font font; if (!font.loadFromFile("C:\Development\Fonts\Roboto\Roboto-Regular.ttf")) { // error... } sf::Text text; // select the font text.setFont(font); // font is a sf::Font std::string userPointsString = "Score: " + std::to_string(userPoints); // set the string to display text.setString(userPointsString); // set the character size text.setCharacterSize(24); // in pixels, not points! // set the color text.setFillColor(sf::Color::Blue); // set the text style text.setStyle(sf::Text::Bold | sf::Text::Underlined); text.setPosition(190.f, 10.f); window.draw(text); // Отрисовка окна window.display(); } return 0; }

Статьи о C++
Вектор. Часть 0.
Вектор. Часть 1.
Вектор. Часть 2.
Указатели
Классы
SFML
SDL
Массив Структур
Как узнать тип переменной C++
Решение задач на C++
Как создать пустую строку в C++
Errors C++
Share in social media: