143 lines
5.0 KiB
C++
143 lines
5.0 KiB
C++
#include <iostream>
|
|
|
|
#include <SDL2/SDL_ttf.h>
|
|
|
|
#include <basic_widgets/core/font.hpp>
|
|
|
|
#include "game.hpp"
|
|
#include "game_screen.hpp"
|
|
#include "settings.hpp"
|
|
|
|
using namespace bwidgets;
|
|
using namespace game;
|
|
|
|
auto main() -> int
|
|
{
|
|
const int width = 854;
|
|
const int height = 480;
|
|
|
|
SDL_Init(SDL_INIT_VIDEO);
|
|
SDL_Window* win =
|
|
SDL_CreateWindow("ChainReact", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
|
width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
|
auto* rend = new Renderer(win, -1, SDL_RENDERER_ACCELERATED);
|
|
rend->blend_mode(SDL_BLENDMODE_BLEND);
|
|
|
|
SDL_Rect viewport {0, 0, width, height};
|
|
|
|
TTF_Init();
|
|
|
|
data::Board board(4, 3);
|
|
data::Board transition_board(board);
|
|
|
|
auto* game_screen = new ui::GameScreen();
|
|
game_screen->board.board = &board;
|
|
game_screen->font("Monospace");
|
|
game_screen->renderer(rend);
|
|
game_screen->viewport(viewport);
|
|
|
|
bool quit = false;
|
|
auto player = data::Player::P1;
|
|
auto round = 1;
|
|
game::data::Boards transitions;
|
|
auto transitions_timer = SDL_GetTicks();
|
|
size_t transitions_iterator = 0;
|
|
while (!quit) {
|
|
SDL_Event ev;
|
|
while (SDL_PollEvent(&ev) != 0) {
|
|
switch (ev.type) {
|
|
case SDL_QUIT: {
|
|
quit = true;
|
|
break;
|
|
}
|
|
case SDL_WINDOWEVENT: {
|
|
if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
|
auto s = rend->output_size();
|
|
viewport.w = s.w;
|
|
viewport.h = s.h;
|
|
|
|
game_screen->viewport(viewport);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ev.type == game_screen->board.event_type) {
|
|
switch ((ui::BoardWidget::event_code)ev.user.code) {
|
|
case ui::BoardWidget::event_code::PLAY: {
|
|
auto* const coord = (SDL_Point*)ev.user.data2;
|
|
const auto can_play =
|
|
game_screen->caption_notification.visibility() == 0
|
|
&& (round <= 2
|
|
|| (transitions.empty()
|
|
&& game::logic::winner(board)
|
|
== game::data::Player::NONE));
|
|
if (!can_play) {
|
|
delete coord;
|
|
break;
|
|
}
|
|
|
|
try {
|
|
transitions =
|
|
game::logic::play(board, {coord->x, coord->y}, player);
|
|
game_screen->cur_player = player = player == data::Player::P1
|
|
? data::Player::P2
|
|
: data::Player::P1;
|
|
round++;
|
|
} catch (const game::error::invalid_move&) {
|
|
game_screen->caption_notification.show()->text(
|
|
"Invalid move!");
|
|
}
|
|
delete coord;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (ev.type == game_screen->settings_event()) {
|
|
auto* s = (Settings*)ev.user.data1;
|
|
board = data::Board(s->board_size.w, s->board_size.h);
|
|
game_screen->board.board = &board;
|
|
round = 0;
|
|
delete s;
|
|
}
|
|
|
|
game_screen->handle_event(ev);
|
|
}
|
|
|
|
rend->draw_color({0, 0, 0, SDL_ALPHA_OPAQUE})->clear();
|
|
|
|
if (transitions_iterator < transitions.size()) {
|
|
// NOLINTNEXTLINE(readability-magic-numbers)
|
|
if (auto t = SDL_GetTicks(); t - transitions_timer > 400) {
|
|
game_screen->board.board = &transitions[transitions_iterator];
|
|
transitions_iterator++;
|
|
transitions_timer = t;
|
|
}
|
|
}
|
|
else if (transitions_iterator > 0 && transitions_iterator == transitions.size())
|
|
{
|
|
board = transitions.back();
|
|
game_screen->board.board = &board;
|
|
transitions_iterator = 0;
|
|
transitions.clear();
|
|
if (auto winner = game::logic::winner(board);
|
|
round > 2 && winner != game::data::Player::NONE)
|
|
{
|
|
if (winner == game::data::Player::P1)
|
|
game_screen->caption_notification.show()->text("Player 1 has won!");
|
|
else game_screen->caption_notification.show()->text("Player 2 has won!");
|
|
}
|
|
}
|
|
game_screen->render();
|
|
|
|
rend->present();
|
|
}
|
|
|
|
delete game_screen;
|
|
delete rend;
|
|
TTF_Quit();
|
|
SDL_DestroyWindow(win);
|
|
SDL_Quit();
|
|
return 0;
|
|
}
|