Untitled
Certainly! I'll help you split the project into separate components for tetromino, game, score, and main. I'll provide header (.h) and implementation (.cpp) files for each component, as well as the main file to handle drawing and game loop. Here's how we can structure the project: 1. Tetromino.h ```cpp #pragma once #include <SFML/Graphics.hpp> struct Point { int x, y; }; class Tetromino { public: Tetromino(); void rotate(); void move(int dx, int dy); void reset(int colorNum); const Point* getPoints() const; int getColor() const; private: Point points[4]; int color; static const int figures[7][4]; }; ``` 2. Tetromino.cpp ```cpp #include "Tetromino.h" #include <cstdlib> const int Tetromino::figures[7][4] = { 1,3,5,7, // I 2,4,5,7, // Z 3,5,4,6, // S 3,5,4,7, // T 2,3,5,7, // L 3,5,7,6, // J 2,3,4,5, // O }; Tetromino::Tetromino() { reset(1); } void Tetromino::rotate() { Point p = points[1]; // center of rotation for (int i = 0; i < 4; i++) { int x = points[i].y - p.y; int y = points[i].x - p.x; points[i].x = p.x - x; points[i].y = p.y + y; } } void Tetromino::move(int dx, int dy) { for (int i = 0; i < 4; i++) { points[i].x += dx; points[i].y += dy; } } void Tetromino::reset(int colorNum) { color = colorNum; int n = rand() % 7; for (int i = 0; i < 4; i++) { points[i].x = figures[n][i] / 2; points[i].y = figures[n][i] % 2; } } const Point* Tetromino::getPoints() const { return points; } int Tetromino::getColor() const { return color; } ``` 3. Game.h ```cpp #pragma once #include "Tetromino.h" #include "Score.h" class Game { public: Game(); void update(float deltaTime); void moveTetrominoLeft(); void moveTetrominoRight(); void rotateTetrominoRight(); void dropTetromino(); bool isGameOver() const; const int* getField() const; const Tetromino& getCurrentTetromino() const; const Tetromino& getNextTetromino() const; Score& getScore(); private: static const int M = 23; static const int N = 10; int field[M][N]; Tetromino currentTetromino; Tetromino nextTetromino; Score score; float timer; float delay; bool gameOver; bool check(); void lockTetromino(); void clearLines(); }; ``` 4. Game.cpp ```cpp #include "Game.h" Game::Game() : timer(0), delay(0.3), gameOver(false) { for (int i = 0; i < M; i++) { for (int j = 0; j < N; j++) { field[i][j] = 0; } } currentTetromino.reset(1 + rand() % 7); nextTetromino.reset(1 + rand() % 7); } void Game::update(float deltaTime) { if (gameOver) return; timer += deltaTime; if (timer > delay) { moveTetrominoDown(); timer = 0; } } void Game::moveTetrominoLeft() { currentTetromino.move(-1, 0); if (!check()) currentTetromino.move(1, 0); } void Game::moveTetrominoRight() { currentTetromino.move(1, 0); if (!check()) currentTetromino.move(-1, 0); } void Game::rotateTetrominoRight() { currentTetromino.rotate(); if (!check()) currentTetromino.rotate(); currentTetromino.rotate(); currentTetromino.rotate(); } void Game::dropTetromino() { while (check()) { currentTetromino.move(0, 1); } currentTetromino.move(0, -1); lockTetromino(); } bool Game::isGameOver() const { return gameOver; } const int* Game::getField() const { return &field[0][0]; } const Tetromino& Game::getCurrentTetromino() const { return currentTetromino; } const Tetromino& Game::getNextTetromino() const { return nextTetromino; } Score& Game::getScore() { return score; } bool Game::check() { const Point* points = currentTetromino.getPoints(); for (int i = 0; i < 4; i++) { if (points[i].x < 0 || points[i].x >= N || points[i].y >= M) return false; if (field[points[i].y][points[i].x]) return false; } return true; } void Game::lockTetromino() { const Point* points = currentTetromino.getPoints(); for (int i = 0; i < 4; i++) { field[points[i].y][points[i].x] = currentTetromino.getColor(); } clearLines(); currentTetromino = nextTetromino; nextTetromino.reset(1 + rand() % 7); if (!check()) gameOver = true; } void Game::clearLines() { int linesCleared = 0; for (int i = M - 1; i >= 0; i--) { bool lineFull = true; for (int j = 0; j < N; j++) { if (field[i][j] == 0) { lineFull = false; break; } } if (lineFull) { linesCleared++; for (int k = i; k > 0; k--) { for (int j = 0; j < N; j++) { field[k][j] = field[k-1][j]; } } for (int j = 0; j < N; j++) { field[0][j] = 0; } i++; } } score.addLines(linesCleared); } ``` 5. Score.h ```cpp #pragma once class Score { public: Score(); void addLines(int lines); int getScore() const; int getHighScore() const; void reset(); private: int currentScore; int highScore; }; ``` 6. Score.cpp ```cpp #include "Score.h" Score::Score() : currentScore(0), highScore(0) {} void Score::addLines(int lines) { switch (lines) { case 1: currentScore += 100; break; case 2: currentScore += 300; break; case 3: currentScore += 500; break; case 4: currentScore += 800; break; } if (currentScore > highScore) { highScore = currentScore; } } int Score::getScore() const { return currentScore; } int Score::getHighScore() const { return highScore; } void Score::reset() { currentScore = 0; } ``` 7. main.cpp ```cpp #include <SFML/Graphics.hpp> #include "Game.h" const int windowWidth = 720; const int windowHeight = 960; const int blockSize = 36; void drawTetromino(sf::RenderWindow& window, const Tetromino& tetromino, sf::Sprite& sprite, int offsetX, int offsetY) { const Point* points = tetromino.getPoints(); for (int i = 0; i < 4; i++) { sprite.setTextureRect(sf::IntRect(tetromino.getColor() * 18, 0, 18, 18)); sprite.setPosition(points[i].x * blockSize + offsetX, points[i].y * blockSize + offsetY); window.draw(sprite); } } int main() { sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "Tetris"); window.setFramerateLimit(60); sf::Texture tileTexture; tileTexture.loadFromFile("images/tiles.png"); sf::Sprite tileSprite(tileTexture); tileSprite.setScale(2, 2); sf::Font font; font.loadFromFile("Roboto-Regular.ttf"); sf::Text scoreText, highScoreText; scoreText.setFont(font); highScoreText.setFont(font); scoreText.setCharacterSize(24); highScoreText.setCharacterSize(24); scoreText.setFillColor(sf::Color::Black); highScoreText.setFillColor(sf::Color::Black); Game game; sf::Clock clock; while (window.isOpen()) { 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) game.moveTetrominoLeft(); if (event.key.code == sf::Keyboard::Right) game.moveTetrominoRight(); if (event.key.code == sf::Keyboard::Up) game.rotateTetrominoRight(); if (event.key.code == sf::Keyboard::Down) game.dropTetromino(); } } float deltaTime = clock.restart().asSeconds(); game.update(deltaTime); window.clear(sf::Color::White); // Draw field const int* field = game.getField(); for (int i = 0; i < 23; i++) { for (int j = 0; j < 10; j++) { if (field[i * 10 + j] == 0) continue; tileSprite.setTextureRect(sf::IntRect(field[i * 10 + j] * 18, 0, 18, 18)); tileSprite.setPosition(j * blockSize + blockSize, i * blockSize + blockSize); window.draw(tileSprite); } } // Draw current tetromino drawTetromino(window, game.getCurrentTetromino(), tileSprite, blockSize, blockSize); // Draw next tetromino drawTetromino(window, game.getNextTetromino(), tileSprite, 12 * blockSize, blockSize); // Draw score scoreText.setString("Score: " + std::to_string(game.getScore().getScore())); scoreText.setPosition(12 * blockSize, 6 * blockSize); window.draw(scoreText); // Draw high score highScoreText.setString("High Score: " + std::to_string(game.getScore().getHighScore())); highScoreText.setPosition(12 * blockSize, 7 * blockSize); window.draw(highScoreText); window.display(); } return 0; } ``` This structure separates the concerns of the game into different components: - Tetromino handles the logic for individual tetromino pieces. - Game manages the game state, including the playing field and game logic. - Score keeps track of the player's score and high score. - The main file handles the game loop, drawing, and input. You'll need to adjust the file paths for textures and fonts to match your project structure. Also, you may need to fine-tune some of the drawing positions and sizes to match your desired layout. Would you like me to explain or elaborate on any part of this code?
Leave a Comment