#include "user_interface_abstraction.h" #include "game_state.h" #include #define MARGIN 300 const char File_Names[12][17] = {"pawn_white.bmp", "pawn_black.bmp", "king_white.bmp", "king_black.bmp", "tower_white.bmp", "tower_black.bmp", "horse_white.bmp", "horse_black.bmp", "bishop_white.bmp", "bishop_black.bmp", "queen_white.bmp", "queen_black.bmp", }; static int Height; static int Width; static SDL_Texture * Board_Texture; static SDL_Rect Rectangle; static int Board_Width; SDL_Surface *bitmapSurface = NULL; SDL_Texture * bitmapTextures[12] = {NULL}; static uint8_t Current_Binary_Board[8] = {0}; /** * @brief Function for setting the lights on the board to the end game state, * clearly indicating which player won. * * @param p_renderer Sdl Renderer * @param game_state->board_pieces board state * @param game_state games state */ static void ui_draw_end_game(SDL_Renderer *p_renderer, Game_State_t * game_state) { SDL_SetRenderTarget(p_renderer, Board_Texture); SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0); SDL_RenderClear(p_renderer); SDL_RenderDrawRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0xFF, 0x00); Rectangle.w = Board_Width; Rectangle.h = Board_Width; Rectangle.x = (Width - Board_Width) / 2; Rectangle.y = (Height - Board_Width) / 2; SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); const int square_size = Board_Width / 8; int starting_x = Rectangle.x; Rectangle.w = square_size; Rectangle.h = square_size; uint8_t white_color[4] = {0xFF, 0xFF, 0x00, 0x00}; uint8_t black_color[4] = {0xFF, 0xFF, 0x00, 0x00}; if (!game_state->error_detected){ if(game_state->player_turn) { white_color[0] = 0x00; white_color[1] = 0xFF; white_color[2] = 0x00; white_color[3] = 0x00; black_color[0] = 0xFF; black_color[1] = 0x00; black_color[2] = 0x00; black_color[3] = 0x00; } else { black_color[0] = 0x00; black_color[1] = 0xFF; black_color[2] = 0x00; black_color[3] = 0x00; white_color[0] = 0xFF; white_color[1] = 0x00; white_color[2] = 0x00; white_color[3] = 0x00; } } for (size_t j = 0; j < 8; j++) { Rectangle.x = starting_x; for (size_t i = 0; i < 8; i++) { if((game_state->board_pieces[j*8+i] & 0x0Fu) != SQUARE_EMPTY) { uint8_t * render_color; if((game_state->board_pieces[j*8+i] % 2u) == 0u ) { render_color = white_color; } else { render_color = black_color; } SDL_SetRenderDrawColor(p_renderer, render_color[0], render_color[1], render_color[2], render_color[3]); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); SDL_RenderCopy(p_renderer, bitmapTextures[(game_state->board_pieces[j*8+i] & 0x0Fu)], NULL, &Rectangle); } else if (((i % 2) + (j % 2)) == 1) { SDL_RenderFillRect(p_renderer, &Rectangle); } else { /* code */ } Rectangle.x += square_size; } Rectangle.y += square_size; } SDL_SetRenderTarget(p_renderer, NULL); SDL_RenderCopy(p_renderer, Board_Texture, NULL, NULL); } /** * @brief Funtion for that will draw the current state of the board including pieces and colors for suggested and possible moves. * @param *p_renderer pointer to the renderer object: * @retval None */ static void ui_draw_board(SDL_Renderer *p_renderer, Game_State_t * game_state) { SDL_SetRenderTarget(p_renderer, Board_Texture); SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0); SDL_RenderClear(p_renderer); SDL_RenderDrawRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0xFF, 0x00); Rectangle.w = Board_Width; Rectangle.h = Board_Width; Rectangle.x = (Width - Board_Width) / 2; Rectangle.y = (Height - Board_Width) / 2; SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); const int square_size = Board_Width / 8; int starting_x = Rectangle.x; Rectangle.w = square_size; Rectangle.h = square_size; for (size_t j = 0; j < 8; j++) { Rectangle.x = starting_x; for (size_t i = 0; i < 8; i++) { if ((game_state->board_state[j*8+i] == POTENTIAL_MOVE) || (game_state->board_state[j*8+i] == POTENTIAL_CASTLE)) { SDL_SetRenderDrawColor(p_renderer, 0x00, 0xFF, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if ((game_state->board_state[j*8+i] == POTENTIAL_TAKE) || (game_state->board_state[j*8+i] == PIECE_NEEDS_TO_BE_HERE) || (game_state->board_state[j*8+i] == PIECE_NEEDS_TO_BE_REMOVED) || (game_state->board_state[j*8+i] == EN_PASSANT_REMOVE) || (game_state->board_state[j*8+i] == EN_PASSANT)) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (game_state->board_state[j*8+i] == PIECE_ORIGIN) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0xFF, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (game_state->board_state[j*8+i] == ERROR_MOVE) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (game_state->board_state[j*8+i] == CONVERTING_PAWN) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x3B, 0x7A, 0x57); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (((i % 2) + (j % 2)) == 1) { SDL_RenderFillRect(p_renderer, &Rectangle); } else { /* code */ } if((game_state->board_pieces[j*8+i] & 0x0Fu) != SQUARE_EMPTY) { SDL_RenderCopy(p_renderer, bitmapTextures[(game_state->board_pieces[j*8+i] & 0x0Fu)], NULL, &Rectangle); } Rectangle.x += square_size; } Rectangle.y += square_size; } Rectangle.x = ((Width - Board_Width) / 2) - (2 * square_size); Rectangle.y = (Height - Board_Width) / 2; int starting_y = Rectangle.y; SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6f, 0x6f, 0x00); /* Now we draw the jail */ for (size_t j = 8; j < 8; j++) { Rectangle.y = starting_y; for (size_t i = 0; i < 8; i++) { if (game_state->board_state[j*8+i] == PIECE_NEEDS_TO_BE_HERE) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6F, 0x6F, 0x00); } else if (game_state->board_state[j*8+i] == ERROR_MOVE) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6F, 0x6F, 0x00); } else { SDL_RenderFillRect(p_renderer, &Rectangle); } if ((game_state->board_pieces[j*8+i] & 0x0Fu) != SQUARE_EMPTY) { SDL_RenderCopy(p_renderer, bitmapTextures[(game_state->board_pieces[j*8+i] & 0x0Fu)], NULL, &Rectangle); } Rectangle.y += square_size; } /*If we are at the end of second jail row, jump to the other side */ if(j == 9) { Rectangle.x += (Board_Width + square_size); } else { Rectangle.x += square_size; } } SDL_SetRenderTarget(p_renderer, NULL); SDL_RenderCopy(p_renderer, Board_Texture, NULL, NULL); } void ui_redraw_board(SDL_Renderer *p_renderer) { Game_State_t * game_state = Board_get_game_state(); if(game_state->game_over) { ui_draw_end_game(p_renderer, game_state); } else { ui_draw_board(p_renderer, game_state); } } /** * @brief Function for resizing the display of the board * @param p_renderer: pointer to the renderer * @param w: width of the new window * @param h: hight of the new window * @retval None */ void ui_resize(SDL_Renderer *p_renderer, int w, int h) { Width = w; Height = h; SDL_DestroyTexture(Board_Texture); Board_Texture = SDL_CreateTexture(p_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h); Board_Width = ((w > h) ? h : w) - MARGIN; // get rid of rounding errors Board_Width -= Board_Width % 8; } /** * @brief Function for registering an incoming click * @param p_renderer: Pointer to the renderer * @param x: x location of the click * @param y: y location of the click * @retval */ void ui_click(SDL_Renderer *p_renderer, int x, int y) { SDL_Point const point = {x, y}; const int square_size = Board_Width / 8; Rectangle.w = Board_Width + (4 * square_size); Rectangle.h = Board_Width; Rectangle.x = ((Width - Board_Width) / 2) - (2 * square_size); Rectangle.y = (Height - Board_Width) / 2; if (SDL_PointInRect(&point, &Rectangle)) { Rectangle.x = (Width - Board_Width) / 2; Rectangle.w = Board_Width; int starting_y = Rectangle.y; const int starting_x = Rectangle.x; Rectangle.w = square_size; Rectangle.h = square_size; for (size_t j = 0; j < 8; j++) { Rectangle.x = starting_x; for (size_t i = 0; i < 8; i++) { if(SDL_PointInRect(&point, &Rectangle)) { Current_Binary_Board[j] ^= (1u << i); Board_Changed(Current_Binary_Board); goto draw_square; } Rectangle.x += square_size; } Rectangle.y += square_size; } Rectangle.x = ((Width - Board_Width) / 2) - (2 * square_size); /* Now we draw the jail */ for (size_t j = 8; j < 12; j++) { Rectangle.y = starting_y; for (size_t i = 0; i < 8; i++) { if (SDL_PointInRect(&point, &Rectangle)) { Current_Binary_Board[j] ^= (1u << i); Board_Changed(Current_Binary_Board); goto draw_square; } Rectangle.y += square_size; } /*If we are at the end of second jail row, jump to the other side */ if (j == 9) { Rectangle.x += (Board_Width + square_size); } else { Rectangle.x += square_size; } } draw_square: SDL_SetRenderTarget(p_renderer, Board_Texture); ui_redraw_board(p_renderer);//, Board_Lights, Board_State); SDL_RenderCopy(p_renderer, Board_Texture, NULL, NULL); SDL_RenderPresent(p_renderer); } } /** * @brief Initialize the ui for the board. Setting all pieces in the correct starting positions * * @param p_renderer pointer to the sdl renderer */ void ui_init(SDL_Renderer *p_renderer) { Current_Binary_Board[0] = 0xFF; Current_Binary_Board[1] = 0xFF; Current_Binary_Board[6] = 0xFF; Current_Binary_Board[7] = 0xFF; for (uint8_t i = 0; i < 12; i++) { //location of all the sprites plus the size of file names char file[25] = "sprites/"; memcpy(&file[8], File_Names[i], 16); bitmapSurface = SDL_LoadBMP(file); bitmapTextures[i] = SDL_CreateTextureFromSurface(p_renderer, bitmapSurface); } SDL_FreeSurface(bitmapSurface); }