Skip to content

Commit

Permalink
feat(#3): render pieces using FEN notation (#5)
Browse files Browse the repository at this point in the history
Feature: render pieces using `FEN` notation
  • Loading branch information
AlejandroSuero committed Jun 20, 2024
2 parents 97e6823 + 0c420b8 commit a3082dc
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 40 deletions.
12 changes: 9 additions & 3 deletions cmake/compile_commands.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
[
{
"directory": "/Users/aome/dev/c_projects/Chess/cmake/src",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -o CMakeFiles/Chess.dir/Main.cpp.o -c /Users/aome/dev/c_projects/Chess/src/Main.cpp",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -isystem /Library/Frameworks/SDL2_image.framework/Headers -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -F /Library/Frameworks/ -o CMakeFiles/Chess.dir/Main.cpp.o -c /Users/aome/dev/c_projects/Chess/src/Main.cpp",
"file": "/Users/aome/dev/c_projects/Chess/src/Main.cpp",
"output": "src/CMakeFiles/Chess.dir/Main.cpp.o"
},
{
"directory": "/Users/aome/dev/c_projects/Chess/cmake/src",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -o CMakeFiles/Chess.dir/ChessLoop.cpp.o -c /Users/aome/dev/c_projects/Chess/src/ChessLoop.cpp",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -isystem /Library/Frameworks/SDL2_image.framework/Headers -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -F /Library/Frameworks/ -o CMakeFiles/Chess.dir/ChessLoop.cpp.o -c /Users/aome/dev/c_projects/Chess/src/ChessLoop.cpp",
"file": "/Users/aome/dev/c_projects/Chess/src/ChessLoop.cpp",
"output": "src/CMakeFiles/Chess.dir/ChessLoop.cpp.o"
},
{
"directory": "/Users/aome/dev/c_projects/Chess/cmake/src",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -o CMakeFiles/Chess.dir/SDL_Handler.cpp.o -c /Users/aome/dev/c_projects/Chess/src/SDL_Handler.cpp",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -isystem /Library/Frameworks/SDL2_image.framework/Headers -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -F /Library/Frameworks/ -o CMakeFiles/Chess.dir/SDL_Handler.cpp.o -c /Users/aome/dev/c_projects/Chess/src/SDL_Handler.cpp",
"file": "/Users/aome/dev/c_projects/Chess/src/SDL_Handler.cpp",
"output": "src/CMakeFiles/Chess.dir/SDL_Handler.cpp.o"
},
{
"directory": "/Users/aome/dev/c_projects/Chess/cmake/src",
"command": "/usr/bin/g++ -DSOME_DEFINITION -isystem /Library/Frameworks/SDL2.framework/Headers -iframework /Library/Frameworks -isystem /Library/Frameworks/SDL2_image.framework/Headers -Wall -std=c++17 -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk -F /Library/Frameworks/ -o CMakeFiles/Chess.dir/FEN.cpp.o -c /Users/aome/dev/c_projects/Chess/src/FEN.cpp",
"file": "/Users/aome/dev/c_projects/Chess/src/FEN.cpp",
"output": "src/CMakeFiles/Chess.dir/FEN.cpp.o"
}
]
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
set(CHESS_SOURCES
ChessLoop.cpp
SDL_Handler.cpp
FEN.cpp
)

if (WIN32)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/SDL2.dll DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
endif (WIN32)

# add_executable(Chess Main.cpp ${CHESS_SOURCES})
add_executable(${PROJECT_NAME} Main.cpp ${CHESS_SOURCES})

target_link_libraries(${PROJECT_NAME} SDL2::SDL2 SDL2::SDL2main)
target_link_libraries(${PROJECT_NAME} SDL2::SDL2 SDL2::SDL2main SDL2_image::SDL2_image)
1 change: 1 addition & 0 deletions src/ChessLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
void Chess::Run()
{
SDL_Handler handler;
handler.render_background();
while (handler.handling_events)
{
handler.handle_events();
Expand Down
31 changes: 31 additions & 0 deletions src/FEN.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "FEN.h"

std::vector<std::string> FEN::parse(const std::string &fen)
{
std::vector<std::string> pieces;
int pos = 0;
for (int i = 0; i <= fen.size(); i++)
{
if (fen[i] == ' ')
{
pieces.push_back(fen.substr(pos, i - pos));
pos = i + 1;
}
}
pieces.push_back(fen.substr(pos, fen.size() - pos));
return pieces;
}

std::vector<std::string> FEN::get_initial_positions()
{
std::vector<std::string> initial_positions;
std::string initial_position =
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
initial_positions = parse(initial_position);
return initial_positions;
}

std::string FEN::get_positions(const std::vector<std::string> &positions)
{
return positions[0];
}
9 changes: 9 additions & 0 deletions src/FEN.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <string>
#include <vector>

namespace FEN
{
std::vector<std::string> parse(const std::string &fen);
std::vector<std::string> get_initial_positions();
std::string get_positions(const std::vector<std::string> &positions);
};
157 changes: 130 additions & 27 deletions src/SDL_Handler.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "SDL_Handler.h"
#include <iostream>
#include "FEN.h"
#include <SDL2_image/SDL_image.h>
#include <string>
#include <vector>

SDL_Handler::SDL_Handler()
{
Expand All @@ -14,7 +17,9 @@ void SDL_Handler::clean_up()
SDL_DestroyWindow(m_window);
if (m_renderer != nullptr)
SDL_DestroyRenderer(m_renderer);
std::cout << "Bye!" << std::endl;
if (m_texture != nullptr)
SDL_DestroyTexture(m_texture);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Handler cleaned up");
SDL_Quit();
}

Expand All @@ -23,17 +28,34 @@ SDL_Handler::~SDL_Handler() { clean_up(); }
void SDL_Handler::render_background()

{
SDL_RenderClear(m_renderer);
SDL_SetRenderDrawColor(m_renderer, 0, 0xFF, 0, SDL_ALPHA_OPAQUE);
SDL_RenderClear(m_renderer);
render_board();
SDL_RenderPresent(m_renderer);
}

void SDL_Handler::render_texture(SDL_Texture *texture, int t_x, int t_y, int x,
int y)
{
SDL_Rect src;
SDL_Rect dst;
src.x = t_x;
src.y = t_y;
src.w = 333;
src.h = 333;
dst.x = x;
dst.y = y;
dst.w = dst.h = m_CELL_SIZE;
SDL_RenderCopy(m_renderer, texture, &src, &dst);
}

void SDL_Handler::render_board()
{
m_texture = load_texture(PIECES_PATH);
// keep board on screen no matter the window size
int board_width = m_win_width > BOARD_WIDTH ? BOARD_WIDTH : m_win_width;
int board_height = m_win_height > BOARD_HEIGHT ? BOARD_HEIGHT : m_win_height;
int board_width = m_win_width > m_BOARD_SIZE ? m_BOARD_SIZE : m_win_width;
int board_height = m_win_height > m_BOARD_SIZE ? m_BOARD_SIZE : m_win_height;
for (int file = 0; file < 8; file++)
{
for (int rank = 0; rank < 8; rank++)
Expand All @@ -44,26 +66,101 @@ void SDL_Handler::render_board()
else
SDL_SetRenderDrawColor(m_renderer, 89, 44, 42, SDL_ALPHA_OPAQUE);
SDL_Rect rect;
// normalize screen size to 8x8 squares
int square_size = 0;
if (board_width / 8 > board_height / 8)
square_size = board_width / 8;
else
square_size = board_height / 8;

#pragma region draw squares
int offset_x = (m_win_width / 2) - (board_width / 2);
int offset_y = (m_win_height / 2) - (board_height / 2);
rect.x = offset_x + (square_size)*file;
rect.y = offset_y + (square_size)*rank;
rect.w = square_size;
rect.h = square_size;
int x = offset_x + (m_CELL_SIZE)*rank;
int y = offset_y + (m_CELL_SIZE)*file;
rect.x = x;
rect.y = y;
rect.w = rect.h = m_CELL_SIZE;
SDL_RenderFillRect(m_renderer, &rect);
#pragma endregion
#pragma region draw pieces

#pragma endregion
}
}
std::vector<std::string> fen = FEN::get_initial_positions();
std::string initial_fen = FEN::get_positions(fen);
int file = 0;
int rank = 0;
for (char c : initial_fen)
{
if (c == '/')
{
file = 0;
rank++;
}
else
{
if (std::isdigit(c))
file += (c - '0') * m_CELL_SIZE;
else
{
int x = (m_win_width / 2) - (board_width / 2) + file;
int y = m_win_height / 2 - m_BOARD_SIZE / 2 + (m_CELL_SIZE)*rank;
switch (c)
{
case 'r':
render_texture(m_texture, 333 * 4, 333, x, y);
break;
case 'b':
render_texture(m_texture, 333 * 2, 333, x, y);
break;
case 'k':
render_texture(m_texture, 0, 333, x, y);
break;
case 'q':
render_texture(m_texture, 333, 333, x, y);
break;
case 'n':
render_texture(m_texture, 333 * 3, 333, x, y);
break;
case 'p':
render_texture(m_texture, 333 * 5, 333, x, y);
break;
case 'R':
render_texture(m_texture, 333 * 4, 0, x, y);
break;
case 'B':
render_texture(m_texture, 333 * 2, 0, x, y);
break;
case 'N':
render_texture(m_texture, 333 * 3, 0, x, y);
break;
case 'P':
render_texture(m_texture, 333 * 5, 0, x, y);
break;
case 'K':
render_texture(m_texture, 0, 0, x, y);
break;
case 'Q':
render_texture(m_texture, 333, 0, x, y);
break;
default:
break;
}
file += m_CELL_SIZE;
}
}
}
}

SDL_Texture *SDL_Handler::load_texture(const char *path)
{
SDL_Texture *texture = nullptr;
texture = IMG_LoadTexture(m_renderer, path);
if (texture == nullptr)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unable to load image. ERROR: %s", SDL_GetError());
return nullptr;
}
return texture;
}

#if defined(__APPLE__) || defined(__MACH__)
Uint32 SDL_Handler::m_time_left()
{
Expand All @@ -78,7 +175,8 @@ Uint32 SDL_Handler::m_time_left()

void SDL_Handler::handle_events()
{
#if defined(__APPLE__) || defined(__MACH__) // MacOS incompatible with SDL_WaitEvent
#if defined(__APPLE__) || \
defined(__MACH__) // MacOS incompatible with SDL_WaitEvent
m_next_time = SDL_GetTicks() + 60;
while (SDL_PollEvent(&m_event))
#else
Expand All @@ -96,15 +194,16 @@ void SDL_Handler::handle_events()
case SDL_WINDOWEVENT_SIZE_CHANGED:
m_win_width = m_event.window.data1;
m_win_height = m_event.window.data2;
if (m_win_height - BOARD_HEIGHT < 0)
if (m_win_height - m_BOARD_SIZE < 0)
{
m_win_height = BOARD_HEIGHT;
m_win_height = m_BOARD_SIZE;
}
else if (m_win_width - BOARD_WIDTH < 0)
else if (m_win_width - m_BOARD_SIZE < 0)
{
m_win_width = BOARD_WIDTH;
m_win_width = m_BOARD_SIZE;
}
SDL_SetWindowSize(m_window, m_win_width, m_win_height);
render_background();
break;
}
default:
Expand All @@ -114,6 +213,10 @@ void SDL_Handler::handle_events()
if (m_event.key.keysym.sym == SDLK_ESCAPE)
handling_events = false;
break;
case SDL_MOUSEBUTTONDOWN:
if (m_event.button.button == SDL_BUTTON_LEFT)
render_background();
break;
default:
break;
}
Expand All @@ -123,34 +226,34 @@ void SDL_Handler::handle_events()
break;
}
}
render_background();
};

void SDL_Handler::init()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << "SDL could not initialize! SDL_Error:\n"
<< SDL_GetError() << std::endl;
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL could not initialize! SDL_Error: %s", SDL_GetError());
return;
}

m_window = SDL_CreateWindow(
"Chess Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
m_SCREEN_WIDTH, m_SCREEN_HEIGHT,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (m_window == nullptr)
{
std::cout << "Window could not be created! SDL_Error: " << SDL_GetError()
<< std::endl;
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Window could not be created! SDL_Error: %s", SDL_GetError());
return;
}
m_renderer = SDL_CreateRenderer(
m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (m_renderer == nullptr)
{
std::cout << "Renderer could not be created! SDL_Error: " << SDL_GetError()
<< std::endl;
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Renderer could not be created! SDL_Error: %s",
SDL_GetError());
return;
}
}
24 changes: 16 additions & 8 deletions src/SDL_Handler.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <SDL.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_render.h>
#include <SDL2_image/SDL_image.h>

class SDL_Handler
{
Expand All @@ -12,20 +14,26 @@ class SDL_Handler
void render_background();
void render_board();
void handle_events();
void render_texture(SDL_Texture *texture, int t_x, int t_y, int x, int y);
SDL_Texture *load_texture(const char *path);

public:
bool handling_events = true;
const char *PIECES_PATH = "../resources/Pieces.png";

private:
const int m_SCREEN_WIDTH = 900;
const int m_SCREEN_HEIGHT = 900;
const int m_BOARD_SIZE = 720;
const int m_CELL_SIZE = m_BOARD_SIZE / 8;

private:
SDL_Window *m_window;
SDL_Renderer *m_renderer;
SDL_Event m_event;
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 800;
const int BOARD_WIDTH = 640;
const int BOARD_HEIGHT = 640;
int m_win_width = SCREEN_WIDTH;
int m_win_height = SCREEN_HEIGHT;
SDL_Event m_event{};
SDL_Texture *m_texture{};
int m_win_width = m_SCREEN_WIDTH;
int m_win_height = m_SCREEN_HEIGHT;
#if defined(__APPLE__) || defined(__MACH__)
Uint32 m_time_left();
Uint32 m_next_time = SDL_GetTicks() + 60;
Expand Down

0 comments on commit a3082dc

Please sign in to comment.