diff --git a/src/Bob.cpp b/src/Bob.cpp index 8003b6e..b576939 100644 --- a/src/Bob.cpp +++ b/src/Bob.cpp @@ -5,6 +5,7 @@ void Game::handle_event(SDL_Event *event) { static SDL_Point window_size; std::string input; + std::ostringstream prompt; switch (event->type) { case (SDL_QUIT): @@ -44,7 +45,11 @@ void Game::handle_event(SDL_Event *event) { this->grid->handle_event(event); this->field_box->handle_event(event); - this->upgrade_box->handle_event(event); + if (this->started) + { + this->upgrade_box->handle_event(event); + + } } break; case SDL_KEYDOWN: @@ -79,13 +84,10 @@ void Game::handle_event(SDL_Event *event) if (this->text_input_box->get_active()) { this->text_input_box->stop(); - this->test_box->set_visible(false); } else { this->text_input_box->start(); - this->test_box->set_visible(true); - } break; case SDLK_RETURN: @@ -133,16 +135,47 @@ void Game::handle_event(SDL_Event *event) { this->text_input_box->handle_event(event); } + break; default: - if (event->type == BOB_MARKERUPDATE - || event->type == BOB_NEXTROUNDEVENT - || event->type == BOB_FIELDUPDATEEVENT - || event->type == BOB_FIELDSELECTEDEVENT + if ((event->type == BOB_MARKERUPDATE || event->type == BOB_FIELDSELECTEDEVENT) + && !this->text_input_box->get_active()) + { + this->grid->handle_event(event); + this->field_box->handle_event(event); + if (this->started) + { + this->upgrade_box->handle_event(event); + } + for (Player *p : this->players) + { + p->handle_event(event); + } + } + if (event->type == BOB_NEXTROUNDEVENT || event->type == BOB_FIELDUPDATEEVENT || event->type == BOB_FIELDUPGRADEVENT) { this->grid->handle_event(event); this->field_box->handle_event(event); this->upgrade_box->handle_event(event); + for (Player *p : this->players) + { + p->handle_event(event); + } + } + else if (event->type == BOB_PLAYERADDED && !this->started) + { + Player *added = (Player *) event->user.data1; + if (event->user.code == 0) + { + this->players.push_back(added); + prompt << "Added Player: " << added->get_name(); + } + else + { + prompt << "Failed to add Player: " << added->get_name(); + delete added; + } + this->text_input_box->prompt(prompt.str()); } break; } @@ -160,51 +193,73 @@ void Game::command(std::string input) { prompt << "This is a test!"; } - else if (input == "next" && this->started) + else if (input == "debug") { - Player *last_player = Player::current_player; - this->turn = this->turn + 1; - if (this->turn == players.size()) + //this->debug->toggle(); + } + else if (input == "next") + { + if (this->started) { - this->turn = 0; - trigger_event(BOB_NEXTROUNDEVENT, 0, (void *) last_player, (void *) Player::current_player); + Player *last_player = Player::current_player; + this->turn = (this->turn + 1) % players.size(); + Player::current_player = players[turn]; + if (this->turn == 0) + { + trigger_event(BOB_NEXTROUNDEVENT, 0, (void *) last_player, (void *) Player::current_player); + } + else + { + trigger_event(BOB_NEXTTURNEVENT, 0, (void *) last_player, (void *) Player::current_player); + } + prompt << "Next player is: " << (Player::current_player)->get_name(); } else { - trigger_event(BOB_NEXTTURNEVENT, 0, (void *) last_player, (void *) Player::current_player); + prompt << "The game was not started yet!"; } - Player::current_player = players[turn]; - prompt << "Next player is: " << (Player::current_player)->get_name(); } else if (input == "surrender") { //Player::current_player->surrender(); } - else if (!this->started && input.substr(0, 10) == "add player") + else if (input.substr(0, 10) == "add player") { - Player *added = new Player(input.substr(11, std::string::npos)); - if (!this->grid->place(added)) + if (!this->started) { - prompt << "Failed to add player:" << added->get_name(); - delete added; + Player *added = new Player(input.substr(11, std::string::npos)); + this->grid->set_selecting(true, added); + prompt << "Select a place, please!"; + this->text_input_box->stop(); } else { - this->players.push_back(added); - prompt << "Added player " << added->get_name(); + prompt << "The game has already been started. No additional player will be accepted for this game. "; } } - else if (input == "start" && !this->started) + else if (input == "start") { - this->start(); - this->started = true; - prompt << "Started the game."; + if (this->players.size() < 2) + { + prompt << "Please add at least one player, before starting the game."; + } + else if (!this->started) + { + this->start(); + this->started = true; + prompt << "Started the game."; + } + else + { + prompt << "The game has already been started!"; + } } this->text_input_box->prompt(prompt.str()); } void Game::start() { + this->players.erase(players.begin()); // remove default player from vector std::random_shuffle(players.begin(), players.end()); this->turn = 0; Player::current_player = players[0]; @@ -222,14 +277,16 @@ int Game::game_loop() { this->move_timer->reset_timer(); SDL_Point move_by = {(this->move[1] - this->move[3]) * 20, (this->move[0] - this->move[2]) * 20}; - this->grid->move(move_by); + if (move[0] || move[1] || move[2] || move[3]) + { + this->grid->move(move_by); + } } if (this->frame_timer->get_timer() > 255) { fps = frame_counter / (this->frame_timer->reset_timer() / 1000.0); - frame_counter = 0; std::cout << fps << std::endl; - this->test_box->load_text(std::to_string(fps)); + frame_counter = 0; } SDL_Event event; while (SDL_PollEvent(&event)) @@ -250,7 +307,6 @@ void Game::render() this->renderer->set_draw_color({0x0, 0x0, 0x0, 0xff}); this->renderer->clear(); this->grid->render(this->renderer); - this->test_box->render(this->renderer); this->field_box->render(this->renderer); this->upgrade_box->render(this->renderer); this->text_input_box->render(this->renderer); diff --git a/src/Bob.hpp b/src/Bob.hpp index 528da88..4171f3e 100644 --- a/src/Bob.hpp +++ b/src/Bob.hpp @@ -44,7 +44,6 @@ public: FieldMeta *center = this->grid->get_field({0, 0, 0}); this->field_box = new FieldBox(this->renderer, {0, 0, 100, 100}, fg, this->font, center); this->upgrade_box = new UpgradeBox(this->renderer, {0, 0, 100, 20}, fg, this->font, center); - this->test_box = new TextBox(this->renderer, {0, 0, 100, 20}, fg, this->font); this->next_turn_button = new NextTurnButtonBox(this->renderer, {window_size.x - 100, window_size.y - 100, 1, 1}, fg, this->font, &(this->players)); @@ -70,7 +69,6 @@ public: } delete text_input_box; delete this->next_turn_button; - delete this->test_box; delete this->upgrade_box; delete this->field_box; delete this->move_timer; @@ -99,7 +97,6 @@ private: NextTurnButtonBox *next_turn_button; UpgradeBox *upgrade_box; FieldBox *field_box; - TextBox *test_box; TTF_Font *font; Window *window; Renderer *renderer; diff --git a/src/Events.cpp b/src/Events.cpp index 90de0c5..b8ba145 100644 --- a/src/Events.cpp +++ b/src/Events.cpp @@ -6,8 +6,8 @@ const Uint32 BOB_FIELDUPDATEEVENT = register_events(1); const Uint32 BOB_FIELDSELECTEDEVENT = register_events(1); const Uint32 BOB_FIELDUPGRADEVENT = register_events(1); const Uint32 BOB_NEXTTURNEVENT = register_events(1); -const Uint32 BOB_ATTACKEVENTS = register_events(1); - +const Uint32 BOB_ATTACKEVENT = register_events(1); +const Uint32 BOB_PLAYERADDED = register_events(1); bool Timer::MOUSE_LOCKED = false; diff --git a/src/Events.hpp b/src/Events.hpp index 340394d..2d68040 100644 --- a/src/Events.hpp +++ b/src/Events.hpp @@ -13,7 +13,8 @@ extern const Uint32 BOB_FIELDUPDATEEVENT; extern const Uint32 BOB_FIELDSELECTEDEVENT; extern const Uint32 BOB_FIELDUPGRADEVENT; extern const Uint32 BOB_NEXTTURNEVENT; -extern const Uint32 BOB_ATTACKEVENTS; +extern const Uint32 BOB_ATTACKEVENT; +extern const Uint32 BOB_PLAYERADDED; #endif Uint32 register_events(Uint32 n); diff --git a/src/Gameplay.cpp b/src/Gameplay.cpp index fcf70e8..6e6e91c 100644 --- a/src/Gameplay.cpp +++ b/src/Gameplay.cpp @@ -160,6 +160,7 @@ void FieldMeta::regenerate_resources() if (this->upgrades[Regeneration_3]) this->resources *= 2; trigger_event(BOB_FIELDUPDATEEVENT, 0, (void *) this, nullptr); + this->changed = true; } Resource HexagonGrid::get_resources_of_cluster(Cluster *cluster) @@ -256,15 +257,10 @@ Resource HexagonGrid::consume_resources_of_cluster(Cluster *cluster, Resource co bool Player::fight(FieldMeta *field) { - if (*this == *(field->get_owner())) // attacked field outside of the map or friendly fire + if (*this == *(field->get_owner())) // friendly fire { return false; } - if (field->get_owner()->get_id().is_nil()) // still to be had - { - field->set_owner(this); - return true; - } // defending player's defense against attacking player's offense int power_level = field->get_defense(); // it's over 9000 @@ -284,8 +280,10 @@ bool Player::fight(FieldMeta *field) if (power_level < 0) // attacking player has won { field->set_owner(this); + this->fought = true; return true; } + this->fought = true; return false; } @@ -294,10 +292,10 @@ void FieldMeta::handle_event(const SDL_Event *event) if (event->type == BOB_NEXTROUNDEVENT) { this->regenerate_resources(); + this->changed = true; } } - void FieldMeta::load(SDL_Renderer *renderer, Layout *layout) { Point precise_location = this->field.field_to_point(layout); @@ -416,7 +414,6 @@ void HexagonGrid::render(Renderer *renderer) this->load(); this->changed = false; } - //this->load(); renderer->copy(this->texture, &(this->layout->box), &(this->layout->box)); } @@ -463,8 +460,8 @@ void HexagonGrid::handle_event(SDL_Event *event) p.x = (int) marker_pos.x; p.y = (int) marker_pos.y; this->move(mouse - p); - this->changed = true; } + this->update_marker(); break; case SDL_MOUSEBUTTONDOWN: switch (event->button.button) @@ -474,25 +471,42 @@ void HexagonGrid::handle_event(SDL_Event *event) break; case SDL_BUTTON_RIGHT: trigger_event(BOB_FIELDSELECTEDEVENT, 0, (void *) this->marker, nullptr); + this->changed = true; break; case SDL_BUTTON_LEFT: - owner = this->marker->get_owner(); - if (*owner == *(Player::current_player)) + if (this->selecting) { - if (this->first_attack != nullptr) + if (this->place(this->selecting_player, this->marker)) { - this->first_attack->set_fighting(false); + trigger_event(BOB_PLAYERADDED, 0, (void *) this->selecting_player, nullptr); } - this->first_attack = this->marker; - this->first_attack->set_fighting(true); + else + { + trigger_event(BOB_PLAYERADDED, 1, (void *) this->selecting_player, nullptr); + } + this->selecting = false; } - else if (this->first_attack != nullptr) + else { - attacking = this->first_attack->get_owner(); - attacking->fight(this->marker); - this->first_attack->set_fighting(false); - this->first_attack = nullptr; + owner = this->marker->get_owner(); + if (*owner == *(Player::current_player)) + { + if (this->first_attack != nullptr) + { + this->first_attack->set_fighting(false); + } + this->first_attack = this->marker; + this->first_attack->set_fighting(true); + } + else if (this->first_attack != nullptr) + { + attacking = this->first_attack->get_owner(); + attacking->fight(this->marker); + this->first_attack->set_fighting(false); + this->first_attack = nullptr; + } } + changed = true; break; default: break; @@ -586,6 +600,7 @@ void HexagonGrid::update_dimensions(SDL_Point dimensions) this->layout->origin = {dimensions.x / 2, dimensions.y / 2}; this->layout->box.w = dimensions.x; this->layout->box.h = dimensions.y; + this->changed = true; } Point HexagonGrid::field_to_point(FieldMeta *field) @@ -599,7 +614,44 @@ bool inside_target(const SDL_Rect *target, const SDL_Point *position) target->y + target->h > position->y; } -bool HexagonGrid::place(Player *player) +bool HexagonGrid::place(Player *player, FieldMeta *center) { - return true; + std::vector selected; + selected.push_back(center); + for (Uint8 i = 0; i < 6; i++) + { + FieldMeta *neighbor = center->get_neighbor(i); + if (neighbor->get_owner()->get_id() == boost::uuids::nil_uuid()) + { + selected.push_back(neighbor); + } + else + { + return false; + } + } + static const Resource lower = {0, 0, 0}; + Resource resources = {0, 0, 0}; + for (auto r : selected) + { + resources += r->get_resources(); + } + if (resources > lower) + { + for (auto i : selected) + { + i->set_owner(player); + i->set_offense(1); + } + return true; + } + return false; +} + +void Player::handle_event(SDL_Event *event) +{ + if (event->type == BOB_NEXTROUNDEVENT) + { + this->fought = false; + } } \ No newline at end of file diff --git a/src/Gameplay.hpp b/src/Gameplay.hpp index bb3ccc4..4d1d4f7 100644 --- a/src/Gameplay.hpp +++ b/src/Gameplay.hpp @@ -511,7 +511,7 @@ public: Player() : name("Default Player"), uuid(boost::uuids::nil_uuid()) { } Player(std::string name_) - : name(name_), uuid(boost::uuids::basic_random_generator()()) + : name(name_), uuid(boost::uuids::basic_random_generator()()), fought(false) { // use the last 24 bits of the tag for the color boost::uuids::uuid id = this->uuid; @@ -543,12 +543,15 @@ public: return !(*this == rhs); } + void handle_event(SDL_Event *event); + static Player *current_player; private: boost::uuids::uuid uuid; SDL_Color color; std::string name; + bool fought; }; class Grid; @@ -559,7 +562,7 @@ class FieldMeta { public: FieldMeta(HexagonGrid *grid_, Field field_, Player *owner_) - : grid(grid_), field(field_), owner(owner_) + : grid(grid_), field(field_), owner(owner_), changed(true) { this->fighting = false; this->upgrades = 0; @@ -569,8 +572,8 @@ public: this->resources_base.circle = distro(rng); this->resources_base.triangle = distro(rng); this->resources_base.square = distro(rng); - this->offense = 1; - this->defense = 1; + this->offense = 0; + this->defense = 0; this->regenerate_resources(); } @@ -580,6 +583,10 @@ public: int get_defense() { return this->defense; } + void set_offense(int off) { this->offense = off; } + + void set_defense(int def) { this->defense = def; } + Field get_field() { return this->field; } Player *get_owner() { return this->owner; } @@ -608,6 +615,7 @@ public: private: bool fighting; + bool changed; const Field field; HexagonGrid *grid; Player *owner; @@ -646,6 +654,7 @@ public: } } this->marker = new FieldMeta(this, new_field, this->default_player); + this->load(); } ~HexagonGrid() @@ -686,10 +695,18 @@ public: void handle_event(SDL_Event *event); - bool place(Player *player); + bool place(Player *player, FieldMeta *center); + + void set_selecting(bool state, Player *player) + { + this->selecting = state; + this->selecting_player = player; + } private: bool changed; + bool selecting; + Player *selecting_player; FieldMeta *first_attack; Renderer *renderer; SDL_Texture *texture; diff --git a/src/Gui.cpp b/src/Gui.cpp index 8ef4fbe..dd8efe1 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -19,18 +19,22 @@ TTF_Font *load_font_from_file(std::string path_to_file, int size) return font; } -bool TextBox::load_text(std::string text) +void TextBox::load() { this->renderer->set_draw_color({0, 0, 0, 0xff}); - const char *displayed_text = text.c_str(); + if (this->text.size() < 1) + { + this->text += " "; + } + const char *displayed_text = this->text.c_str(); SDL_Surface *text_surface = TTF_RenderUTF8_Blended_Wrapped(this->font, displayed_text, this->color, this->dimensions.w); - this->dimensions.h = text_surface->h; if (text_surface == nullptr) { SDL_FreeSurface(text_surface); throw SDL_TTFException(); } + this->dimensions.h = text_surface->h; SDL_Surface *surface = SDL_CreateRGBSurface(0, this->dimensions.w, text_surface->h, 32, rmask, gmask, bmask, amask); if (surface == nullptr || SDL_LockSurface(surface) < 0 || @@ -57,7 +61,6 @@ bool TextBox::load_text(std::string text) throw SDL_TextureException(); } SDL_SetRenderTarget(this->renderer->get_renderer(), nullptr); // reset the render target - return (this->texture != nullptr); } void Container::handle_event(SDL_Event *event) @@ -73,7 +76,7 @@ void FieldBox::handle_event(const SDL_Event *event) FieldMeta *field_update = reinterpret_cast(event->user.data1); if (field_update == this->field) { - this->update(); + changed = true; } } else if (event->type == BOB_MARKERUPDATE) @@ -85,6 +88,7 @@ void FieldBox::handle_event(const SDL_Event *event) SDL_GetMouseState(&mouse.x, &mouse.y); this->update_position(mouse); this->visible = true; + changed = true; } } @@ -100,6 +104,7 @@ void FieldBox::update() << "▲ " << (int) cluster_resources.triangle << " (" << (int) field_resources.triangle << ")" << "\n" << "■ " << (int) cluster_resources.square << " (" << (int) field_resources.square << ")" << "\n"; this->load_text(output.str()); + changed = true; } void UpgradeButtonBox::set_active(bool state) @@ -115,6 +120,7 @@ void UpgradeButtonBox::set_active(bool state) this->color = {0, 0, 0, 0xff}; this->load_text(UPGRADE_NAMES.at(this->upgrade)); } + changed = true; } void UpgradeBox::update_upgrade_boxes() @@ -124,6 +130,7 @@ void UpgradeBox::update_upgrade_boxes() { this->upgrades[i]->set_active(active_upgrades[i]); } + changed = true; } void UpgradeBox::handle_event(const SDL_Event *event) @@ -133,6 +140,7 @@ void UpgradeBox::handle_event(const SDL_Event *event) if (event->type == BOB_FIELDUPDATEEVENT) { this->update_upgrade_boxes(); + changed = true; } else if (event->type == SDL_MOUSEBUTTONDOWN) { @@ -147,6 +155,7 @@ void UpgradeBox::handle_event(const SDL_Event *event) { this->marked_upgrade->handle_event(event); } + changed = true; } else if (event->type == SDL_MOUSEMOTION && this->visible) { @@ -171,6 +180,7 @@ void UpgradeBox::handle_event(const SDL_Event *event) this->upgrade_info->load_text(output.str()); } } + changed = true; } } else // NOT visible @@ -187,6 +197,7 @@ void UpgradeBox::handle_event(const SDL_Event *event) this->field = selected; this->update_upgrade_boxes(); this->set_visible(true); + changed = true; } } } @@ -204,6 +215,7 @@ void UpgradeButtonBox::handle_event(const SDL_Event *event) if (*(Player::current_player) == *(field->get_owner())) { field->upgrade(this->upgrade); + changed = true; } } } @@ -216,9 +228,11 @@ void UpgradeBox::render(Renderer *ext_renderer) { box->render(ext_renderer); } - SDL_Rect dim = this->upgrades[0]->get_dimensions(); + this->changed = false; + /*SDL_Rect dim = this->upgrades[0]->get_dimensions(); this->dimensions.w = dim.w; this->dimensions.h = dim.h * (int) this->upgrades.size(); + */ } void Container::render(Renderer *renderer) @@ -231,10 +245,15 @@ void Container::render(Renderer *renderer) void Box::render(Renderer *ext_renderer) { + if (changed) + { + this->load(); + } if (this->visible && this->texture != nullptr) { ext_renderer->copy(this->texture, nullptr, &(this->dimensions)); } + this->changed = false; } void Container::set_visible(bool visible) @@ -309,6 +328,7 @@ void NextTurnButtonBox::handle_event(const SDL_Event *event) std::ostringstream text; text << "NEXT TURN" << "\n\n" << Player::current_player->get_name(); this->load_text(text.str()); + this->changed = true; } } } @@ -375,6 +395,7 @@ void TextInputBox::handle_event(const SDL_Event *event) if (text.empty()) text += " "; this->load_text(text); + this->changed = true; } } @@ -389,14 +410,21 @@ void TextInputBox::prompt(std::string message) output.str(""); this->prompt(message); } + this->input.str(""); + this->changed = true; } void TextInputBox::render(Renderer *ext_renderer) { + if (this->changed) + { + this->load(); + } if (this->texture != nullptr && this->visible) { ext_renderer->copy(this->texture, nullptr, &(this->dimensions)); } + this->changed = false; } void TextInputBox::update_dimensions(SDL_Rect rect) @@ -404,7 +432,7 @@ void TextInputBox::update_dimensions(SDL_Rect rect) this->dimensions.x = rect.x; this->dimensions.y = rect.y; this->dimensions.w = rect.w; - this->load_text(output.str()); + this->changed = true; } bool TextInputBox::get_active() diff --git a/src/Gui.hpp b/src/Gui.hpp index 6832d68..6a47ed4 100644 --- a/src/Gui.hpp +++ b/src/Gui.hpp @@ -34,6 +34,8 @@ public: virtual void render(Renderer *renderer); + virtual void load() { this->changed = false; } + virtual void set_visible(bool visibility) { this->visible = visibility; } SDL_Rect get_dimensions() { return this->dimensions; } @@ -45,6 +47,7 @@ protected: SDL_Rect dimensions; SDL_Color color; bool visible; + bool changed; }; class TextBox : public Box @@ -53,17 +56,23 @@ public: TextBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font_) : Box(renderer, dimensions, color), font(font_), lines(1) { - this->font_height = TTF_FontHeight(font); + this->load(); } - bool load_text(std::string text); + void load(); + + void load_text(std::string text) + { + this->text = text; + changed = true; + } virtual void handle_event(const SDL_Event *event) { } protected: TTF_Font *font; Uint16 lines; - int font_height; + std::string text; }; class TextInputBox : TextBox @@ -74,6 +83,7 @@ public: { this->visible = false; this->output << Player::current_player->get_name() << "# "; + this->load(); this->load_text(output.str()); }