add sounds, finish main game, add new textures, add tetromino preview, fix some bugs

This commit is contained in:
Rene Kievits
2024-10-15 05:14:41 +02:00
parent 24c8c3fe2c
commit f19f183686
21 changed files with 279 additions and 47 deletions

View File

@@ -1 +1,16 @@
# Tetris written in SDL2 and C++
## TODO
- Game Over screen
- Add Gamemodes
- Gamemode selection screen
- Save score
- Think of a better scoring system
- Save to a file
- Maybe Multiplayer
- Select 1 Player/2 Player in the title
- Peer2Peer or server based?
- Server based could also cloud save the savegame
- Cleanup code/Refractor
- Comment/Document stuff

View File

Before

Width:  |  Height:  |  Size: 236 B

After

Width:  |  Height:  |  Size: 236 B

BIN
assets/scoreboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -11,7 +11,7 @@ bool Game::init(const char* title, int w, int h) {
title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h,
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN
));
if (!window) {
@@ -19,8 +19,6 @@ bool Game::init(const char* title, int w, int h) {
return false;
}
SDL_SetWindowMinimumSize(window.get( ), 800, 650);
renderer = std::shared_ptr<SDL_Renderer>(
SDL_CreateRenderer(window.get( ), -1, SDL_RENDERER_ACCELERATED),
[ ](SDL_Renderer* r) { SDL_DestroyRenderer(r); }
@@ -69,15 +67,24 @@ void Game::run( ) {
gameOver = true;
Mix_PauseMusic( );
Mix_Chunk* rotateSound = Mix_LoadWAV("assets/sound_effects/game_over.wav");
if (rotateSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, rotateSound, 0);
}
while (gameOver) {
if (quit) return;
inputHandler( );
gameRenderer->renderGameOver(gameBoard->getScore( ), gameBoard->getLevel( ));
render( );
gameRenderer->renderGameOver(gameBoard->getScore( ), gameBoard->getLevel( ), gameBoard->getLines( ));
}
}
void Game::inputHandler( ) {
SDL_Event event;
Mix_Chunk* movePieceSound = Mix_LoadWAV("assets/sound_effects/move_piece.wav");
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
SDL_Quit( );
@@ -87,10 +94,20 @@ void Game::inputHandler( ) {
case SDLK_LEFT:
case SDLK_a:
gameBoard->tryMoveCurrentTetromino(-1, 0);
if (movePieceSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, movePieceSound, 0);
}
break;
case SDLK_RIGHT:
case SDLK_d:
gameBoard->tryMoveCurrentTetromino(1, 0);
if (movePieceSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, movePieceSound, 0);
}
break;
case SDLK_DOWN:
case SDLK_s:
@@ -102,8 +119,15 @@ void Game::inputHandler( ) {
case SDLK_ESCAPE:
break;
case SDLK_g:
if (startSequence)
if (startSequence) {
startSequence = false;
Mix_Chunk* menuSound = Mix_LoadWAV("assets/sound_effects/menu.wav");
if (menuSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, menuSound, 0);
}
}
break;
case SDLK_r:
if (isGameOver( ))
@@ -112,10 +136,38 @@ void Game::inputHandler( ) {
case SDLK_q:
SDL_Quit( );
quit = true;
case SDLK_EQUALS:
SDL_Log("Test %d", Mix_GetMusicVolume(bgm.get( )));
Mix_VolumeMusic(Mix_GetMusicVolume(bgm.get( )) + 8);
break;
case SDLK_MINUS:
SDL_Log("Test %d", Mix_GetMusicVolume(bgm.get( )));
Mix_VolumeMusic(Mix_GetMusicVolume(bgm.get( )) - 8);
break;
case SDLK_m:
if (Mix_PausedMusic( ))
Mix_ResumeMusic( );
else
Mix_PauseMusic( );
break;
default:
break;
}
} else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
int TARGET_ASPECT_RATIO = 3 / 4;
int newHeight = event.window.data2, newWidth = event.window.data1;
float newAspectRatio = static_cast<float>(newWidth) / newHeight;
if (newAspectRatio > TARGET_ASPECT_RATIO)
newWidth = static_cast<int>(newHeight * TARGET_ASPECT_RATIO);
else
newHeight = static_cast<int>(newWidth / TARGET_ASPECT_RATIO);
SDL_SetWindowSize(window.get( ), newWidth, newHeight);
handleWindowResize( );
}
}
@@ -150,6 +202,7 @@ void Game::render( ) {
SDL_RenderClear(renderer.get( ));
gameRenderer->renderBoard(*gameBoard);
gameRenderer->renderTetrominoPreview(gameBoard->getNextTetromino( ));
SDL_RenderPresent(renderer.get( ));
}

View File

@@ -2,7 +2,7 @@
#include <iostream>
GameBoard::GameBoard( )
: lockedTetrominos(20, vector<int>(10, 0)), lockedColors(20, std::vector<SDL_Color>(10, { 0, 0, 0, 255 })), score(0), level(1), collision(false) {
: lockedTetrominos(20, vector<int>(10, 0)), lockedColors(20, std::vector<SDL_Color>(10, { 0, 0, 0, 255 })), score(0), level(0), lines(0), collision(false) {
spawnNewTetromino( );
}
@@ -20,6 +20,14 @@ void GameBoard::tryRotateCurrentTetromino( ) {
if (checkCollision(*currentTetromino))
for (int i = 0; i < 3; i++)
currentTetromino->rotate(*this);
else {
Mix_Chunk* rotateSound = Mix_LoadWAV("assets/sound_effects/rotate_piece.wav");
if (rotateSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, rotateSound, 0);
}
}
}
bool GameBoard::checkCollision(const Tetromino& tetromino) const {
@@ -97,9 +105,17 @@ void GameBoard::lockTetromino( ) {
}
}
}
Mix_Chunk* pieceLanded = Mix_LoadWAV("assets/sound_effects/piece_landed.wav");
if (pieceLanded == nullptr)
SDL_Log("Failed to play sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, pieceLanded, 0);
}
}
void GameBoard::clearLines( ) {
int clearedLines = 0;
for (int row = 0; row < height; row++) {
if (all_of(lockedTetrominos[row].begin( ), lockedTetrominos[row].end( ), [ ](int cell) { return cell != 0; })) {
lockedTetrominos.erase(lockedTetrominos.begin( ) + row);
@@ -111,20 +127,61 @@ void GameBoard::clearLines( ) {
score += 100;
if (score % 1000 == 0) {
level++;
Mix_Chunk* levelUpSound = Mix_LoadWAV("assets/sound_effects/level_up.wav");
if (levelUpSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, levelUpSound, 0);
}
}
clearedLines++;
lines++;
}
}
if (clearedLines >= 4) {
Mix_Chunk* clearedLinesSound = Mix_LoadWAV("assets/sound_effects/tetris_line_clear.wav");
if (clearedLinesSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, clearedLinesSound, 0);
}
} else if (clearedLines > 0) {
Mix_Chunk* clearedLinesSound = Mix_LoadWAV("assets/sound_effects/line_clear.wav");
if (clearedLinesSound == nullptr)
SDL_Log("Failed to play rotate sound effect: %s", Mix_GetError( ));
else {
Mix_PlayChannel(-1, clearedLinesSound, 0);
}
}
}
}
void GameBoard::spawnNewTetromino( ) {
//Ensure on startup that we have a tetromino
if (!nextTetromino) {
random_device dev;
mt19937 rng(dev( ));
uniform_int_distribution<mt19937::result_type> dist6(0, static_cast<int>(TetrominoShape::COUNT) - 1);
TetrominoShape shape = static_cast<TetrominoShape>(dist6(rng));
currentTetromino = make_unique<Tetromino>(shape);
nextTetromino = make_shared<Tetromino>(shape);
}
currentTetromino = move(nextTetromino);
currentTetromino->move(width / 2 - 1, 0);
if (checkCollision(*currentTetromino))
// Generate next tetromino
random_device dev;
mt19937 rng(dev( ));
uniform_int_distribution<mt19937::result_type> dist6(0, static_cast<int>(TetrominoShape::COUNT) - 1);
TetrominoShape shape = static_cast<TetrominoShape>(dist6(rng));
nextTetromino = make_shared<Tetromino>(shape);
if (checkCollision(*currentTetromino)) {
collision = true;
lockedTetrominos.clear( );
lockedColors.clear( );
}
}
void GameBoard::update( ) {
@@ -132,8 +189,7 @@ void GameBoard::update( ) {
lockTetromino( );
clearLines( );
spawnNewTetromino( );
} else
clearLines( );
}
}
bool GameBoard::isValidPosition(const vector<vector<int>>& shape, int x, int y) const {
@@ -156,6 +212,9 @@ void GameBoard::moveToBottom( ) {
const bool GameBoard::isCollision( ) const { return collision; }
const int GameBoard::getScore( ) const { return score; }
const int GameBoard::getLevel( ) const { return level; }
const int GameBoard::getLines( ) const { return lines; }
const shared_ptr<Tetromino> GameBoard::getNextTetromino( ) const { return nextTetromino; }
const vector<vector<int>>& GameBoard::getLockedTetrominos( ) const { return lockedTetrominos; }
const vector<vector<SDL_Color>>& GameBoard::getLockedColors( ) const { return lockedColors; }

View File

@@ -1,5 +1,9 @@
#pragma once
extern "C" {
#include <SDL2/SDL_mixer.h>
}
#include <vector>
#include <memory>
#include <algorithm>
@@ -14,12 +18,14 @@ private:
vector<vector<int>> lockedTetrominos;
vector<vector<SDL_Color>> lockedColors;
unique_ptr<Tetromino> currentTetromino;
shared_ptr<Tetromino> currentTetromino;
shared_ptr<Tetromino> nextTetromino;
const int width = 10;
const int height = 20;
bool collision;
int score;
int level;
int lines;
public:
GameBoard( );
@@ -33,6 +39,8 @@ public:
const bool isCollision( ) const;
const int getScore( ) const;
const int getLevel( ) const;
const int getLines( ) const;
const shared_ptr<Tetromino> getNextTetromino( ) const;
const vector<vector<int>>& getLockedTetrominos( ) const;
const vector<vector<SDL_Color>>& getLockedColors( ) const;

View File

@@ -28,13 +28,68 @@ void Renderer::renderBoard(const GameBoard& gameBoard) {
drawGrid(gameBoard);
drawLockedBlocks(gameBoard);
drawTetromino(gameBoard.getCurrentTetromino( ));
drawScoreboard(gameBoard.getScore( ), gameBoard.getLevel( ));
drawScoreboard(gameBoard.getScore( ), gameBoard.getLevel( ), gameBoard.getLines( ));
}
void Renderer::drawScoreboard(int score, int level) {
void Renderer::drawScoreboard(int score, int level, int lines) {
int gapSize = blockSize / 8;
// 6 Because the gameBoard is 10 blocks, half that is 5 + 1 for the wall = 6
int blackAreaWidth = (windowWidth / 2) - (blockSize * 6) - gapSize;
SDL_Rect blackRect = { 0, 0, blackAreaWidth, windowHeight };
SDL_SetRenderDrawColor(renderer.get( ), 0, 0, 0, 255);
renderText(fmt::format("Score: {0}", score), 350, 100, 24, SDL_Color{ 200,128,200 });
renderText(fmt::format("Level: {0}", level), 350, 200, 24, SDL_Color{ 128,200,200 });
SDL_RenderFillRect(renderer.get( ), &blackRect);
SDL_Surface* scoreboardSurface = IMG_Load("assets/scoreboard.png");
if (!scoreboardSurface) {
SDL_Log("Failed to load title surface: %s", SDL_GetError( ));
return;
}
auto scoreboardTexture = SDL_CreateTextureFromSurface(renderer.get( ), scoreboardSurface);
SDL_FreeSurface(scoreboardSurface);
if (!scoreboardTexture) {
SDL_Log("Failed to create title texture: %s", SDL_GetError( ));
return;
}
int width, height;
SDL_QueryTexture(scoreboardTexture, nullptr, nullptr, &width, &height);
int scoreboardWidth = static_cast<int>(width * static_cast<float>(windowHeight) / height);
SDL_Rect scoreboardRect = {
windowWidth - scoreboardWidth,
0,
scoreboardWidth,
windowHeight
};
SDL_RenderCopy(renderer.get( ), scoreboardTexture, nullptr, &scoreboardRect);
SDL_DestroyTexture(scoreboardTexture);
renderRightAlignedText(fmt::format("{0}", score), windowWidth - 30, 97, 32, SDL_Color{ 0,0,0 });
renderText(fmt::format("{0}", level), windowWidth - 92, 230, 32, SDL_Color{ 0,0,0 });
renderText(fmt::format("{0}", lines), windowWidth - 92, 330, 32, SDL_Color{ 0,0,0 });
}
void Renderer::renderRightAlignedText(const std::string& text, int x, int y, int fontSize, const SDL_Color& color) {
TTF_Font* font = TTF_OpenFont("assets/tetris-gb.ttf", fontSize);
if (!font) {
SDL_Log("Failed to open font: %s", TTF_GetError( ));
return;
}
int textWidth;
TTF_SizeText(font, text.c_str( ), &textWidth, nullptr);
int rightAlignedX = x - textWidth;
renderText(text, rightAlignedX, y, fontSize, color);
TTF_CloseFont(font);
}
void Renderer::drawGrid(const GameBoard& board) {
@@ -47,6 +102,9 @@ void Renderer::drawGrid(const GameBoard& board) {
int totalWidth = w * blockSize;
int totalHeight = h * blockSize;
SDL_SetTextureBlendMode(textures[TetrisAssets::BORDER], SDL_BLENDMODE_BLEND);
SDL_SetTextureColorMod(textures[TetrisAssets::BORDER], 165, 42, 42);
for (int y = 0; y < (h + (innerBorderThickness * h)); ++y) {
SDL_Rect leftBlock = { offsetX - blockSize, offsetY + y * blockSize, blockSize, blockSize };
renderTexture(TetrisAssets::BORDER, leftBlock.x, leftBlock.y - (innerBorderThickness * y + 1), leftBlock.w, leftBlock.h);
@@ -130,33 +188,25 @@ void Renderer::drawTetromino(const Tetromino& tetromino) {
SDL_SetTextureColorMod(textures[shapeToAsset(tetrominoShape)], color.r, color.g, color.b);
if (tetrominoShape == TetrominoShape::I) {
if (angle == 90 || angle == 270) {
SDL_SetTextureColorMod(textures[TetrisAssets::I_STARTR], color.r, color.g, color.b);
SDL_SetTextureColorMod(textures[TetrisAssets::I_MIDR], color.r, color.g, color.b);
SDL_SetTextureColorMod(textures[TetrisAssets::I_ENDR], color.r, color.g, color.b);
for (int i = 0; i < 4; ++i) {
SDL_Rect destRect = { offsetX + (x + i) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopy(renderer.get( ), textures[TetrisAssets::I_MIDR], nullptr, &destRect);
}
SDL_Rect startRect = { offsetX + (x + 0) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopy(renderer.get( ), textures[TetrisAssets::I_ENDR], nullptr, &startRect);
SDL_Rect endRect = { offsetX + (x + 3) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopy(renderer.get( ), textures[TetrisAssets::I_STARTR], nullptr, &endRect);
} else {
SDL_SetTextureColorMod(textures[TetrisAssets::I_START], color.r, color.g, color.b);
SDL_SetTextureColorMod(textures[TetrisAssets::I_MID], color.r, color.g, color.b);
SDL_SetTextureColorMod(textures[TetrisAssets::I_END], color.r, color.g, color.b);
if (angle == 90) {
for (int i = 0; i < 4; ++i) {
SDL_Rect destRect = { offsetX + (x + i) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_MID], nullptr, &destRect, angle, nullptr, SDL_FLIP_NONE);
}
SDL_Rect startRect = { offsetX + (x + 0) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_START], nullptr, &startRect, angle, nullptr, SDL_FLIP_NONE);
SDL_Rect endRect = { offsetX + (x + 3) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_END], nullptr, &endRect, angle, nullptr, SDL_FLIP_NONE);
} else if (angle == 270) {
for (int i = 0; i < 4; ++i) {
SDL_Rect destRect = { offsetX + (x + i) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_MID], nullptr, &destRect, angle, nullptr, SDL_FLIP_NONE);
}
SDL_Rect startRect = { offsetX + (x + 0) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_END], nullptr, &startRect, angle, nullptr, SDL_FLIP_NONE);
SDL_Rect endRect = { offsetX + (x + 3) * blockSize, offsetY + y * blockSize, blockSize, blockSize };
SDL_RenderCopyEx(renderer.get( ), textures[TetrisAssets::I_START], nullptr, &endRect, angle, nullptr, SDL_FLIP_NONE);
} else {
SDL_Rect destRect1 = { offsetX + (x + 0) * blockSize, offsetY + (y + 0) * blockSize, blockSize, blockSize };
SDL_Rect destRect2 = { offsetX + (x + 0) * blockSize, offsetY + (y + 1) * blockSize, blockSize, blockSize };
SDL_Rect destRect3 = { offsetX + (x + 0) * blockSize, offsetY + (y + 2) * blockSize, blockSize, blockSize };
@@ -274,25 +324,70 @@ void Renderer::renderStartScreen( ) {
TTF_SizeText(font, "PRESS START", &w, &h);
TTF_CloseFont(font);
renderText("press G to start", (windowWidth / 2) - (w / 2), windowHeight - 100, 16, SDL_Color{ 0, 0, 0 });
renderText("press G to start", (windowWidth / 2) - (w / 2), windowHeight - 70, 16, SDL_Color{ 0, 0, 0 });
SDL_RenderPresent(renderer.get( ));
}
void Renderer::renderGameOver(int score, int level, int lines) {
int fontSize = 24;
int lineSpacing = fontSize + 10;
int totalHeight = 5 * lineSpacing;
void Renderer::renderGameOver(int score, int level) {
SDL_SetRenderDrawColor(renderer.get( ), 0, 0, 0, 128);
SDL_RenderClear(renderer.get( ));
renderText("Game Over", 100, 100, 128, SDL_Color{ 200, 200, 200 });
renderText(fmt::format("Score: {0}", score), 100, 250, 64, SDL_Color{ 200, 128, 200 });
renderText(fmt::format("Level: {0}", level), 100, 350, 64, SDL_Color{ 128, 200, 200 });
int centerX = (windowWidth / 2);
int centerY = (windowHeight / 2) - (totalHeight / 2);
renderText("game", centerX, centerY, fontSize, SDL_Color{ 0, 0, 0 });
renderText("over", centerX, centerY + lineSpacing, fontSize, SDL_Color{ 0, 0, 0 });
renderText("please", centerX, centerY + 2 * lineSpacing, fontSize, SDL_Color{ 0, 0, 0 });
renderText("try", centerX, centerY + 3 * lineSpacing, fontSize, SDL_Color{ 0, 0, 0 });
renderText("again @", centerX, centerY + 4 * lineSpacing, fontSize, SDL_Color{ 0, 0, 0 });
SDL_RenderPresent(renderer.get( ));
}
void Renderer::renderTetrominoPreview(const shared_ptr<Tetromino> nextTetromino) {
const auto& shape = nextTetromino->getShape( );
int x = nextTetromino->getX( ), y = nextTetromino->getY( );
double angle = nextTetromino->getRotationAngle( );
TetrominoShape tetrominoShape = nextTetromino->getShapeEnumn( );
SDL_SetTextureBlendMode(textures[shapeToAsset(tetrominoShape)], SDL_BLENDMODE_BLEND);
SDL_Color color = nextTetromino->getColor( );
SDL_SetTextureColorMod(textures[shapeToAsset(tetrominoShape)], color.r, color.g, color.b);
if (tetrominoShape == TetrominoShape::I) {
SDL_SetTextureColorMod(textures[TetrisAssets::I_STARTR], color.r, color.g, color.b);
SDL_SetTextureColorMod(textures[TetrisAssets::I_MIDR], color.r, color.g, color.b);
SDL_SetTextureColorMod(textures[TetrisAssets::I_ENDR], color.r, color.g, color.b);
for (int i = 0; i < 4; ++i) {
SDL_Rect destRect = { (windowWidth - 155) + (x + i) * blockSize, (windowHeight - 120) + y * blockSize, blockSize, blockSize };
SDL_RenderCopy(renderer.get( ), textures[TetrisAssets::I_MIDR], nullptr, &destRect);
}
SDL_Rect startRect = { (windowWidth - 155) + (x + 0) * blockSize, (windowHeight - 120) + y * blockSize, blockSize, blockSize };
SDL_RenderCopy(renderer.get( ), textures[TetrisAssets::I_ENDR], nullptr, &startRect);
SDL_Rect endRect = { (windowWidth - 155) + (x + 3) * blockSize, (windowHeight - 120) + y * blockSize, blockSize, blockSize };
SDL_RenderCopy(renderer.get( ), textures[TetrisAssets::I_STARTR], nullptr, &endRect);
} else {
for (int row = 0; row < shape.size( ); ++row) {
for (int col = 0; col < shape[row].size( ); ++col) {
if (shape[row][col] != 0) {
SDL_Rect destRect = { (windowWidth - 140) + col * blockSize, (windowHeight - 130) + row * blockSize, blockSize, blockSize };
SDL_Point center = { blockSize / 2, blockSize / 2 };
SDL_RenderCopy(renderer.get( ), textures[shapeToAsset(tetrominoShape)], nullptr, &destRect);
}
}
}
}
}
void Renderer::renderText(string text, int x, int y, int size, SDL_Color color) {
TTF_Font* font = TTF_OpenFont("assets/tetris-gb.ttf", size);
SDL_Surface* surface = TTF_RenderText_Solid(font, text.c_str( ), color);

View File

@@ -35,7 +35,7 @@ private:
void drawGrid(const GameBoard& gameBoard);
void drawLockedBlocks(const GameBoard& gameBoard);
void drawTetromino(const Tetromino& tetromino);
void drawScoreboard(int score, int level);
void drawScoreboard(int score, int level, int lines);
TetrisAssets shapeToAsset(const TetrominoShape shape);
@@ -58,8 +58,10 @@ public:
bool loadTexture(const string& filePath, const TetrisAssets shape);
void renderTexture(const TetrisAssets shape, int x, int y, int width, int height);
void renderStartScreen( );
void renderGameOver(int score, int level);
void renderGameOver(int score, int level, int lines);
void renderText(string text, int x, int y, int size, SDL_Color color);
void renderRightAlignedText(const std::string& text, int x, int y, int fontSize, const SDL_Color& color);
void renderTetrominoPreview(const shared_ptr<Tetromino> nextTetromino);
const int getBlockSize( ) const;
void setBlockSize(int newBlockSize);

View File

@@ -1,6 +1,6 @@
#include "Tetromino.hpp"
#include "GameBoard.hpp"
#include <iostream>
Tetromino::Tetromino(TetrominoShape shape) : x(0), y(0), textureShape(shape) {
initializeShape(shape);
currentRotationState = 1;

View File

@@ -31,7 +31,7 @@ int main( ) {
}
Game game;
if (!game.init("Tetris", 800, 600)) {
if (!game.init("Tetris", 810, 600)) {
SDL_Log("Failed to init game");
SDL_Quit( );
return 1;