one should be in the correct folder when initializing the git project...

This commit is contained in:
Rene Kievits
2024-10-14 04:28:43 +02:00
commit 730df043f7
20 changed files with 799 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
build/
.vscode/

38
CMakeLists.txt Normal file
View File

@@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 3.5)
project(SDL_TD VERSION 0.1 LANGUAGES CXX)
find_package(SDL2 QUIET)
set(SDL_INCLUDE_DIRS ${SDL2_INCLUDE_DIRS})
set(SDL_LIBRARIES ${SDL2_LIBRARIES})
find_library(SDL_MIXER_LIBRARY NAMES SDL2_mixer)
find_library(SDL_IMAGE_LIBRARY NAMES SDL2_image)
find_library(SDL_TTF_LIBRARY NAMES SDL2_ttf)
include_directories(${SDL_INCLUDE_DIRS})
file(GLOB_RECURSE PROJECT_SOURCES src/*.cpp)
file(GLOB_RECURSE PROJECT_HEADERS src/*.hpp)
add_executable(SDL_TD
${PROJECT_SOURCES}
${PROJECT_HEADERS}
)
target_link_libraries(SDL_TD
${SDL_LIBRARIES}
${SDL_MIXER_LIBRARY}
${SDL_IMAGE_LIBRARY}
${SDL_TTF_LIBRARY}
fmt
)
file(GLOB ASSETS
"assets/*.png"
)
foreach(ASSET ${ASSETS})
file(COPY ${ASSET} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/assets)
endforeach()

14
README.md Normal file
View File

@@ -0,0 +1,14 @@
# TODO
## Needs
- Input handler
- Collision
- Playing Field
- Scoreboard
## Optional
- Start Page
- Textures
- Audio

BIN
assets/I.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

BIN
assets/J.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/L.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

BIN
assets/O.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

BIN
assets/S.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

BIN
assets/Z.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/bgm.mp3 Normal file

Binary file not shown.

BIN
assets/single.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

142
src/Game.cpp Normal file
View File

@@ -0,0 +1,142 @@
#include "Game.hpp"
Game::Game( ) :
window(nullptr, SDL_DestroyWindow),
gameOver(false),
startSequence(true),
quit(false) { }
bool Game::init(const char* title, int w, int h) {
window.reset(SDL_CreateWindow(
title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
w, h,
SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE
));
if (!window) {
SDL_Log("Failed to create window: %s", SDL_GetError( ));
return false;
}
renderer = std::shared_ptr<SDL_Renderer>(
SDL_CreateRenderer(window.get( ), -1, SDL_RENDERER_ACCELERATED),
[ ](SDL_Renderer* r) { SDL_DestroyRenderer(r); }
);
if (!renderer) {
SDL_Log("Failed to create renderer: %s", SDL_GetError( ));
return false;
}
gameRenderer = make_shared<Renderer>(renderer);
gameBoard = make_shared<GameBoard>( );
bgm = std::shared_ptr<Mix_Music>(Mix_LoadMUS("/home/crylia/Dokumente/git/tetris_sdl/assets/bgm.mp3"), [ ](Mix_Music* m) {
Mix_FreeMusic(m);
});
if (!bgm) {
SDL_Log("Failed to load background music: %s", Mix_GetError( ));
return false;
}
return true;
}
void Game::run( ) {
while (startSequence) {
if (quit) return;
inputHandler( );
gameRenderer->renderStartScreen( );
}
Mix_PlayMusic(bgm.get( ), -1);
lastUpdateTime = SDL_GetTicks( );
while (!gameOver && !gameBoard->isCollision( )) {
if (quit) return;
inputHandler( );
update( );
render( );
}
gameOver = true;
Mix_PauseMusic( );
while (gameOver) {
if (quit) return;
inputHandler( );
gameRenderer->renderGameOver(gameBoard->getScore( ), gameBoard->getLevel( ));
}
}
void Game::inputHandler( ) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) { SDL_Quit( ); } else if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_LEFT:
case SDLK_a:
gameBoard->tryMoveCurrentTetromino(-1, 0);
break;
case SDLK_RIGHT:
case SDLK_d:
gameBoard->tryMoveCurrentTetromino(1, 0);
break;
case SDLK_DOWN:
case SDLK_s:
gameBoard->moveToBottom( );
break;
case SDLK_SPACE:
gameBoard->tryRotateCurrentTetromino( );
break;
case SDLK_ESCAPE:
break;
case SDLK_g:
if (startSequence)
startSequence = false;
break;
case SDLK_r:
if (isGameOver( ))
restart( );
break;
case SDLK_q:
SDL_Quit( );
quit = true;
default:
break;
}
}
}
}
void Game::update( ) {
Uint32 currentTime = SDL_GetTicks( );
Uint32 deltaTime = currentTime - lastUpdateTime;
if (deltaTime >= max(50, 1000 - (gameBoard->getLevel( ) * 100))) {
gameBoard->update( );
lastUpdateTime = currentTime;
}
}
void Game::render( ) {
//Set default color to black
SDL_SetRenderDrawColor(renderer.get( ), 20, 20, 20, 255);
SDL_RenderClear(renderer.get( ));
gameRenderer->renderBoard(*gameBoard);
SDL_RenderPresent(renderer.get( ));
}
bool Game::isGameOver( ) { return gameOver; }
void Game::setGameOver(bool value) { gameOver = value; }
void Game::restart( ) {
gameOver = false;
startSequence = true;
gameBoard = make_shared<GameBoard>( );
}
const bool Game::isGameQuit( )const { return quit; }

46
src/Game.hpp Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include <memory>
extern "C" {
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
}
#include "Renderer.hpp"
#include "GameBoard.hpp"
using namespace std;
class Game {
private:
void update( );
void render( );
void inputHandler( );
unique_ptr<SDL_Window, void(*)(SDL_Window*)> window;
shared_ptr<SDL_Renderer> renderer;
shared_ptr<GameBoard> gameBoard;
shared_ptr<Renderer> gameRenderer;
shared_ptr<Mix_Music> bgm;
Uint32 lastUpdateTime = 0;
int dropInterval = 1000;
bool gameOver;
bool startSequence;
bool quit;
public:
Game( );
bool init(const char* title, int w, int h);
void run( );
void restart( );
bool isGameOver( );
void setGameOver(bool value);
const bool isGameQuit( ) const;
};

120
src/GameBoard.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include "GameBoard.hpp"
#include <iostream>
GameBoard::GameBoard( )
: lockedTetrominos(20, vector<int>(10, 0)), lockedColors(20, std::vector<SDL_Color>(10, { 0, 0, 0, 0 })), score(0), level(1), collision(false) {
spawnNewTetromino( );
}
bool GameBoard::tryMoveCurrentTetromino(int dx, int dy) {
currentTetromino->move(dx, dy);
if (checkCollision(*currentTetromino)) {
currentTetromino->move(-dx, -dy);
return false;
}
return true;
}
void GameBoard::tryRotateCurrentTetromino( ) {
currentTetromino->rotate(*this);
if (checkCollision(*currentTetromino))
for (int i = 0; i < 3; i++)
currentTetromino->rotate(*this);
}
bool GameBoard::checkCollision(const Tetromino& tetromino) const {
const auto& shape = tetromino.getShape( );
int x = tetromino.getX( ), y = tetromino.getY( );
for (int row = 0; row < shape.size( ); ++row)
for (int col = 0; col < shape[row].size( ); ++col)
if (shape[row][col] != 0) {
int newX = x + col;
int newY = y + row;
if (newX < 0 || newX >= width || newY >= height || (newY >= 0 && lockedTetrominos[newY][newX] != 0)) { return true; }
}
return false;
}
void GameBoard::lockTetromino( ) {
const auto& shape = currentTetromino->getShape( );
int x = currentTetromino->getX( ), y = currentTetromino->getY( );
for (int row = 0; row < shape.size( ); ++row)
for (int col = 0; col < shape[row].size( ); ++col)
if (shape[row][col] != 0) {
int lockedTetrominosX = x + col;
int lockedTetrominosY = y + row;
if (lockedTetrominosY >= 0 && lockedTetrominosX < height) {
lockedTetrominos[lockedTetrominosY][lockedTetrominosX] = 1;
lockedColors[lockedTetrominosY][lockedTetrominosX] = currentTetromino->getColor( );
}
}
}
void GameBoard::clearLines( ) {
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);
lockedTetrominos.insert(lockedTetrominos.begin( ), vector<int>(width, 0));
score += 100;
if ((score % 1000) == 0)
level++;
}
}
void GameBoard::spawnNewTetromino( ) {
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);
currentTetromino->setTexture(shape);
currentTetromino->move(width / 2 - 1, 0);
if (checkCollision(*currentTetromino))
collision = true;
}
void GameBoard::update( ) {
if (!tryMoveCurrentTetromino(0, 1)) {
lockTetromino( );
clearLines( );
spawnNewTetromino( );
} else
clearLines( );
}
bool GameBoard::isValidPosition(const vector<vector<int>>& shape, int x, int y) const {
for (int row = 0; row < shape.size( ); ++row)
for (int col = 0; col < shape[row].size( ); ++col)
if (shape[row][col]) {
int newX = x + col;
int newY = y + row;
if (newX < 0 || newX >= width || newY < 0 || newY >= height) return false;
if (lockedTetrominos[newY][newX]) return false;
}
return true;
}
void GameBoard::moveToBottom( ) {
while (isValidPosition(currentTetromino->getShape( ), currentTetromino->getX( ), currentTetromino->getY( ) + 1)) currentTetromino->move(0, 1);
}
const bool GameBoard::isCollision( ) const { return collision; }
const int GameBoard::getScore( ) const { return score; }
const int GameBoard::getLevel( ) const { return level; }
const vector<vector<int>>& GameBoard::getLockedTetrominos( ) const { return lockedTetrominos; }
const vector<vector<SDL_Color>>& GameBoard::getLockedColors( ) const { return lockedColors; }
const Tetromino& GameBoard::getCurrentTetromino( ) const { return *currentTetromino; }
void GameBoard::reset( ) {
lockedTetrominos.clear( );
lockedColors.clear( );
score = 0;
level = 1;
}

40
src/GameBoard.hpp Normal file
View File

@@ -0,0 +1,40 @@
#pragma once
#include <vector>
#include <memory>
#include <algorithm>
#include "Tetromino.hpp"
class GameBoard {
private:
void spawnNewTetromino( );
bool checkCollision(const Tetromino& tetromino) const;
void lockTetromino( );
void clearLines( );
vector<vector<int>> lockedTetrominos;
vector<vector<SDL_Color>> lockedColors;
unique_ptr<Tetromino> currentTetromino;
const int width = 10;
const int height = 20;
bool collision;
int score;
int level;
public:
GameBoard( );
void update( );
bool tryMoveCurrentTetromino(int dx, int dy);
void tryRotateCurrentTetromino( );
bool isValidPosition(const vector<vector<int>>& shape, int x, int y) const;
void moveToBottom( );
void reset( );
const bool isCollision( ) const;
const int getScore( ) const;
const int getLevel( ) const;
const vector<vector<int>>& getLockedTetrominos( ) const;
const vector<vector<SDL_Color>>& getLockedColors( ) const;
const Tetromino& getCurrentTetromino( ) const;
};

151
src/Renderer.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include "Renderer.hpp"
#include <iostream>
Renderer::Renderer(shared_ptr<SDL_Renderer> renderer) : renderer(renderer), blockSize(30) {
setRenderer(renderer);
}
void Renderer::setRenderer(shared_ptr<SDL_Renderer> renderer) {
this->renderer = renderer;
loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::I);
loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::J);
loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::L);
loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::S);
loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::O);
loadTexture("/home/crylia/Dokumente/git/tetris_sdl/assets/single.png", TetrominoShape::Z);
}
void Renderer::renderBoard(const GameBoard& gameBoard) {
drawGrid(gameBoard);
drawLockedBlocks(gameBoard);
drawTetromino(gameBoard.getCurrentTetromino( ));
drawScoreboard(gameBoard.getScore( ), gameBoard.getLevel( ));
}
void Renderer::drawScoreboard(int score, int level) {
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 });
}
void Renderer::drawGrid(const GameBoard& board) {
SDL_SetRenderDrawColor(renderer.get( ), 100, 100, 100, 255);
int w = board.getLockedTetrominos( )[0].size( ), h = board.getLockedTetrominos( ).size( );
for (int x = 0; x <= w; ++x)
SDL_RenderDrawLine(renderer.get( ), x * blockSize, 0, x * blockSize, h * blockSize);
for (int y = 0; y <= h; ++y)
SDL_RenderDrawLine(renderer.get( ), 0, y * blockSize, w * blockSize, y * blockSize);
}
void Renderer::drawLockedBlocks(const GameBoard& gameBoard) {
const auto& lockedTetrominos = gameBoard.getLockedTetrominos( );
const auto& lockedColors = gameBoard.getLockedColors( );
for (int row = 0; row < lockedTetrominos.size( ); ++row) {
for (int col = 0; col < lockedTetrominos[row].size( ); ++col) {
int blockType = lockedTetrominos[row][col];
if (blockType != 0) {
SDL_Rect block = { col * blockSize, row * blockSize, blockSize, blockSize };
SDL_SetTextureBlendMode(textures[TetrominoShape::I], SDL_BLENDMODE_BLEND);
SDL_Color color = lockedColors[row][col];
if (textures[TetrominoShape::I]) {
SDL_SetTextureColorMod(textures[TetrominoShape::I], color.r, color.g, color.b);
renderTexture(TetrominoShape::I, block.x, block.y, block.w, block.h);
} else {
SDL_SetRenderDrawColor(renderer.get( ), color.r, color.g, color.b, 255);
SDL_RenderFillRect(renderer.get( ), &block);
}
}
}
}
}
void Renderer::drawTetromino(const Tetromino& tetromino) {
const auto& shape = tetromino.getShape( );
int x = tetromino.getX( ), y = tetromino.getY( );
auto t = tetromino.getTexture( );
double angle = tetromino.getRotationAngle( );
SDL_SetTextureBlendMode(textures[t], SDL_BLENDMODE_BLEND);
SDL_Color color = tetromino.getColor( );
SDL_SetTextureColorMod(textures[t], color.r, color.g, color.b);
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 = { (x + col) * blockSize, (y + row) * blockSize, blockSize, blockSize };
SDL_Point center = { blockSize / 2, blockSize / 2 };
SDL_RenderCopyEx(renderer.get( ), textures[t], nullptr, &destRect, angle, &center, SDL_FLIP_NONE);
}
}
}
}
bool Renderer::loadTexture(const string& filePath, const TetrominoShape shape) {
SDL_Texture* texture = IMG_LoadTexture(renderer.get( ), filePath.c_str( ));
if (!texture) {
SDL_Log("Failed to load Texture: %s\n%s", filePath, SDL_GetError( ));
return false;
}
textures[shape] = texture;
return true;
}
void Renderer::renderTexture(const TetrominoShape shape, int x, int y, int width, int height) {
SDL_Rect destRect{ x,y,width,height };
SDL_RenderCopy(renderer.get( ), textures[shape], nullptr, &destRect);
}
void Renderer::renderStartScreen( ) {
SDL_SetRenderDrawColor(renderer.get( ), 0, 0, 0, 255);
SDL_RenderClear(renderer.get( ));
renderText("Tetris", 100, 100, 128, SDL_Color{ 200,200,200 });
SDL_RenderPresent(renderer.get( ));
}
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 });
SDL_RenderPresent(renderer.get( ));
}
void Renderer::renderText(string text, int x, int y, int size, SDL_Color color) {
TTF_Font* font = TTF_OpenFont("/usr/share/fonts/TTF/OpenSans-Regular.ttf", size);
SDL_Surface* surface = TTF_RenderText_Solid(font, text.c_str( ), color);
if (!surface) {
SDL_Log("Failed to create surface: %s", TTF_GetError( ));
return;
}
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer.get( ), surface);
if (!texture) {
SDL_Log("Failed to create texture from surface: %s", SDL_GetError( ));
SDL_FreeSurface(surface);
TTF_CloseFont(font);
return;
}
int width = surface->w;
int height = surface->h;
SDL_Rect destRect = { x, y, width, height };
SDL_RenderCopy(renderer.get( ), texture, nullptr, &destRect);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
TTF_CloseFont(font);
}

37
src/Renderer.hpp Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <unordered_map>
#include <string>
#include <fmt/format.h>
extern "C" {
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
}
#include "GameBoard.hpp"
class Renderer {
private:
void drawGrid(const GameBoard& gameBoard);
void drawLockedBlocks(const GameBoard& gameBoard);
void drawTetromino(const Tetromino& tetromino);
void drawScoreboard(int score, int level);
shared_ptr<SDL_Renderer> renderer;
int blockSize;
unordered_map<TetrominoShape, SDL_Texture*> textures;
public:
Renderer(shared_ptr<SDL_Renderer> renderer);
void setRenderer(shared_ptr<SDL_Renderer> renderer);
void renderBoard(const GameBoard& gb);
bool loadTexture(const string& filePath, const TetrominoShape shape);
void renderTexture(const TetrominoShape shape, int x, int y, int width, int height);
void renderStartScreen( );
void renderGameOver(int score, int level);
void renderText(string text, int x, int y, int size, SDL_Color color);
};

112
src/Tetromino.cpp Normal file
View File

@@ -0,0 +1,112 @@
#include "Tetromino.hpp"
#include "GameBoard.hpp"
Tetromino::Tetromino(TetrominoShape shape) : x(0), y(0) {
initializeShape(shape);
currentRotationState = 1;
color.a = 255;
color.r = 0;
color.g = 0;
color.b = 0;
random_device dev;
mt19937 rng(dev( ));
uniform_int_distribution<mt19937::result_type> dist6(0, 5);
switch (dist6(rng)) {
case 0:
color.r = 255;
break;
case 1:
color.g = 255;
break;
case 2:
color.b = 255;
break;
case 3:
color.r = 255;
color.g = 255;
break;
case 4:
color.g = 255;
color.b = 255;
break;
case 5:
color.b = 255;
color.r = 255;
break;
default:
break;
}
}
void Tetromino::initializeShape(TetrominoShape s) {
switch (s) {
case TetrominoShape::I:
shape = { {1, 1, 1, 1} };
break;
case TetrominoShape::O:
shape = { {1, 1}, {1, 1} };
break;
case TetrominoShape::S:
shape = { {0, 1, 1}, {1, 1, 0} };
break;
case TetrominoShape::Z:
shape = { {1, 1, 0}, {0, 1, 1} };
break;
case TetrominoShape::J:
shape = { {1, 0, 0}, {1, 1, 1} };
break;
case TetrominoShape::L:
shape = { {0, 0, 1}, {1, 1, 1} };
break;
default:
shape = { {0} };
break;
}
}
void Tetromino::rotate(GameBoard& gameBoard) {
vector<vector<int>> rotated(shape[0].size( ), vector<int>(shape.size( )));
for (int row = 0; row < shape.size( ); ++row)
for (int col = 0; col < shape[0].size( ); ++col)
rotated[col][shape.size( ) - 1 - row] = shape[row][col];
if (gameBoard.isValidPosition(rotated, x, y)) {
shape = rotated;
currentRotationState = (currentRotationState + 1) % 4;
} else {
int dx = x - 1;
while (!gameBoard.isValidPosition(rotated, dx, y)) {
//If the shape before rotation wont have a valid position then rotation is not possible and we abort
if (!gameBoard.isValidPosition(shape, dx, y)) {
shape = rotated;
return;
}
dx--;
}
x = dx;
shape = rotated;
currentRotationState = (currentRotationState + 1) % 4;
}
}
void Tetromino::move(int dx, int dy) {
x += dx;
y += dy;
}
double Tetromino::getRotationAngle( ) const {
return currentRotationState * 90.0;
}
const vector<vector<int>>& Tetromino::getShape( ) const { return shape; }
int Tetromino::getX( ) const { return x; }
int Tetromino::getY( ) const { return y; }
void Tetromino::setTexture(const TetrominoShape shape) { this->textureShape = shape; }
const TetrominoShape Tetromino::getTexture( ) const { return textureShape; }
SDL_Color Tetromino::getColor( ) const { return color; }

51
src/Tetromino.hpp Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
extern "C" {
#include <SDL2/SDL.h>
}
#include <vector>
#include <string>
#include <random>
using namespace std;
enum class TetrominoShape {
L,
I,
O,
S,
Z,
J,
COUNT //Used to know the ammount of shapes
};
class GameBoard;
class Tetromino {
private:
void initializeShape(TetrominoShape shape);
vector<vector<int>> shape;
int x, y;
int currentRotationState;
TetrominoShape textureShape;
SDL_Color color;
public:
Tetromino(TetrominoShape shape);
void rotate(GameBoard& gameBoard);
void move(int dx, int dy);
double getRotationAngle( ) const;
const vector<vector<int>>& getShape( ) const;
int getX( ) const;
int getY( ) const;
void setTexture(const TetrominoShape textureName);
const TetrominoShape getTexture( ) const;
SDL_Color getColor( ) const;
};

46
src/main.cpp Normal file
View File

@@ -0,0 +1,46 @@
#include <iostream>
extern "C" {
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
}
#include "Game.hpp"
int main( ) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {
SDL_Log("Couldn't init SDL: %s", SDL_GetError( ));
return 1;
}
if (IMG_Init(IMG_INIT_PNG) == 0) {
std::cerr << "Failed to initialize SDL_image: " << IMG_GetError( ) << std::endl;
SDL_Quit( );
return 1;
}
if (TTF_Init( ) == -1) {
std::cerr << "Failed to initialize SDL_ttf: " << TTF_GetError( ) << std::endl;
SDL_Quit( );
return 1;
}
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
SDL_Log("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError( ));
return 1;
}
Game game;
if (!game.init("Tetris", 800, 600)) {
SDL_Log("Failed to init game");
SDL_Quit( );
return 1;
}
while (!game.isGameQuit( ))
game.run( );
SDL_Quit( );
return 0;
}