chainreaction/main.cpp

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;
}