diff --git a/src/Bob.cpp b/src/Bob.cpp index 0da5bb4..942fcd7 100644 --- a/src/Bob.cpp +++ b/src/Bob.cpp @@ -2,6 +2,7 @@ void Game::handle_event(SDL_Event *event) { + static SDL_Point window_size; switch (event->type) { case (SDL_QUIT): @@ -13,7 +14,7 @@ void Game::handle_event(SDL_Event *event) switch (event->window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: - this->grid->update_box({event->window.data1, event->window.data2}); + this->grid->update_dimensions({event->window.data1, event->window.data2}); break; default: break; @@ -21,13 +22,13 @@ void Game::handle_event(SDL_Event *event) } break; case SDL_MOUSEMOTION: - grid->handle_event(event, this->event_context); + grid->handle_event(event); break; case SDL_MOUSEWHEEL: - grid->handle_event(event, this->event_context); + grid->handle_event(event); break; case SDL_MOUSEBUTTONDOWN: - grid->handle_event(event, this->event_context); + grid->handle_event(event); break; case SDL_KEYDOWN: switch (event->key.keysym.sym) @@ -45,7 +46,9 @@ void Game::handle_event(SDL_Event *event) this->move[3] = true; break; case SDLK_f: - this->grid->update_box(this->window->toggle_fullscreen()); + window_size = this->window->toggle_fullscreen(); + this->grid->update_dimensions(window_size); + this->side_bar->update_dimensions(window_size); break; case SDLK_ESCAPE: this->quit = true; @@ -73,15 +76,13 @@ void Game::handle_event(SDL_Event *event) break; } break; - case SDL_USEREVENT: - switch (event->type - this->event_context->base_event) - { - case BOB_NEXTTURNEVENT: - this->grid->handle_event(event, this->event_context); - default: - break; - } default: + if (event->type == BOB_MARKERUPDATE || event->type == BOB_NEXTTURNEVENT || + event->type == BOB_FIELDUPDATEEVENT) + { + this->grid->handle_event(event); + this->side_bar->handle_event(event); + } break; } } @@ -94,7 +95,7 @@ int Game::game_loop() Uint32 frame_counter = 0; while (!this->quit) { - if (this->move_timer->get_timer() > 16) + if (this->move_timer->get_timer() > 1) { this->move_timer->reset_timer(); SDL_Point move_by = {(this->move[1] - this->move[3]) * 20, (this->move[0] - this->move[2]) * 20}; @@ -163,7 +164,7 @@ int main(int, char **) SDL_Quit(); } SDL_Rect window_dimensions = {SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGTH}; - Game *game = new Game(&window_dimensions, 6); + Game *game = new Game(&window_dimensions, 2); int exit_status = game->game_loop(); delete game; TTF_Quit(); diff --git a/src/Bob.hpp b/src/Bob.hpp index 17828f1..48a6ecc 100644 --- a/src/Bob.hpp +++ b/src/Bob.hpp @@ -14,7 +14,7 @@ const int SCREEN_WIDTH = 800; const int SCREEN_HEIGTH = 600; -const int SIDEBAR_WIDTH = 200; +const int SIDEBAR_WIDTH = 300; const std::string TITLE = "Bob - Battles of Bacteria"; class Game @@ -23,19 +23,18 @@ class Game public: Game(SDL_Rect *window_dimensions, Sint16 size) { - this->event_context = new EventContext(); - this->layout = new Layout(pointy_orientation, size, + this->layout = new Layout(pointy_orientation, 20, {window_dimensions->w / 2, window_dimensions->h / 2}, - {0, 0, window_dimensions->w - SIDEBAR_WIDTH, window_dimensions->h}); + {SIDEBAR_WIDTH, 0, window_dimensions->w - SIDEBAR_WIDTH, window_dimensions->h}); this->grid = new HexagonGrid(size, this->layout); for (int i = 0; i < 4; i++) { this->move[i] = false; } this->quit = false; + SDL_Color fg = {0x00, 0xff, 0x00, 0xff}; try { - this->font = load_font_from_file("/usr/share/fonts/dejavu/DejaVuSans.ttf", 12); this->window = new Window(TITLE, window_dimensions, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); this->renderer = new Renderer(this->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC @@ -43,10 +42,18 @@ public: SDL_Rect side_bar_dimensions = {window_dimensions->x - SIDEBAR_WIDTH, 0, SIDEBAR_WIDTH, window_dimensions->y}; this->side_bar = new Container(this->window, this->renderer, side_bar_dimensions); + this->field_box = new FieldBox(this->renderer, + {0, 20, SIDEBAR_WIDTH, SCREEN_HEIGTH}, + fg, + this->font, + this->grid->point_to_field({0.0, 0.0}) + ); this->test_box = new TextBox(this->renderer, - {SCREEN_WIDTH - SIDEBAR_WIDTH, 0, SIDEBAR_WIDTH, SCREEN_HEIGTH}, - {0x00, 0xff, 0x00, 0xff}, this->font); + {0, 0, SIDEBAR_WIDTH, SCREEN_HEIGTH}, + fg, this->font + ); this->side_bar->add(test_box); + this->side_bar->add(field_box); this->side_bar->set_visible(true); } catch (const SDL_Exception &sdl_except) @@ -60,6 +67,7 @@ public: ~Game() { delete this->test_box; + delete this->field_box; delete this->move_timer; delete this->frame_timer; delete this->side_bar; @@ -67,7 +75,7 @@ public: delete this->renderer; delete this->window; delete this->layout; - delete this->event_context; + //delete this->events; } void render(); @@ -77,7 +85,7 @@ public: int game_loop(); private: - EventContext *event_context; + FieldBox *field_box; TextBox *test_box; TTF_Font *font; Window *window; diff --git a/src/Events.cpp b/src/Events.cpp index 28052c5..a1c4f41 100644 --- a/src/Events.cpp +++ b/src/Events.cpp @@ -1,5 +1,9 @@ #include "Events.hpp" +const Uint32 BOB_NEXTTURNEVENT = register_events(1); +const Uint32 BOB_MARKERUPDATE = register_events(1); +const Uint32 BOB_FIELDUPDATEEVENT = register_events(1); + void Timer::start_timer() { this->timer_started = SDL_GetTicks(); @@ -18,7 +22,10 @@ Uint32 Timer::reset_timer() return ticks_passed; } -Uint32 EventContext::register_events(Uint32 num_events) +Uint32 register_events(Uint32 n) { - return SDL_RegisterEvents(num_events); + Uint32 base_event = SDL_RegisterEvents(n); + if (base_event == ((Uint32) - 1)) + throw SDL_Exception("Failed to register events!"); + return base_event; } \ No newline at end of file diff --git a/src/Events.hpp b/src/Events.hpp index d0e3d3a..fc49d34 100644 --- a/src/Events.hpp +++ b/src/Events.hpp @@ -3,27 +3,16 @@ #include #include +#include "Exceptions.hpp" -enum Bob_Event -{ - BOB_NEXTTURNEVENT, - BOB_FIELDUPDATEEVENT -}; +#ifndef _EVENT_TYPES +#define _EVENT_TYPES +extern const Uint32 BOB_NEXTTURNEVENT; +extern const Uint32 BOB_MARKERUPDATE; +extern const Uint32 BOB_FIELDUPDATEEVENT; +#endif -class EventContext -{ -public: - EventContext() - : base_event(register_events(num_events)) { } - - const Uint32 base_event; - -private: - - static const int num_events = 2; - - static Uint32 register_events(Uint32 n); -}; +Uint32 register_events(Uint32 n); class Timer { diff --git a/src/Gameplay.cpp b/src/Gameplay.cpp index 860f726..0b4efbf 100644 --- a/src/Gameplay.cpp +++ b/src/Gameplay.cpp @@ -45,9 +45,9 @@ double operator!(SDL_Point left) Field Field::cubic_round(double x, double y, double z) { - Sint8 round_x = (Sint8) std::round(x); - Sint8 round_y = (Sint8) std::round(y); - Sint8 round_z = (Sint8) std::round(z); + double round_x = std::round(x); + double round_y = std::round(y); + double round_z = std::round(z); double x_err = std::abs(round_x - x); double y_err = std::abs(round_y - y); double z_err = std::abs(round_z - z); @@ -61,7 +61,10 @@ Field Field::cubic_round(double x, double y, double z) { round_z = -round_x - round_y; } - return Field(round_x, round_y, round_z); + Sint16 x_out = (int) round_x; + Sint16 y_out = (int) round_y; + Sint16 z_out = (int) round_z; + return Field(x_out, y_out, z_out); } @@ -139,7 +142,7 @@ void FieldMeta::render(SDL_Renderer *renderer, Layout *layout) vx[i] = (Sint16) polygon[i].x; vy[i] = (Sint16) polygon[i].y; } - if (*(this->owner) == Player()) + if (this->owner->get_id().is_nil()) color = {0x77, 0x77, 0x77, 0x77}; filledPolygonRGBA(renderer, vx, vy, 6, color.r, color.g, color.b, 0x33); SDL_Color inverse; @@ -191,7 +194,7 @@ void FieldMeta::regenerate_resources() this->resources *= 2; } -Resource Grid::get_resources_of_cluster(const Cluster *cluster) +Resource HexagonGrid::get_resources_of_cluster(Cluster *cluster) { Resource res = {0, 0, 0}; for (FieldMeta *elem : *cluster) @@ -205,24 +208,21 @@ Resource Grid::get_resources_of_cluster(const Cluster *cluster) bool FieldMeta::upgrade(Upgrade upgrade) { // check available resources for cluster and consume resources - Cluster *cluster = this->grid->get_cluster(this); - Resource cluster_resources = this->grid->get_resources_of_cluster(this->grid->get_cluster(this, cluster)); - Resource remaining_costs; - try + Cluster *cluster = new Cluster(); + this->grid->get_cluster(this); + Resource cluster_resources = this->grid->get_resources_of_cluster(cluster); + auto pair = UPGRADE_COSTS.find(upgrade); + if (pair != UPGRADE_COSTS.end()) { - Resource costs = UPGRADE_COSTS.at(upgrade); - remaining_costs = this->grid->consume_resources_of_cluster(cluster, costs); - } - catch (const std::out_of_range &oor) - { - std::cerr << "Out of Range exception: " << oor.what() << std::endl; - remaining_costs = {1, 1, 1}; - } - static const Resource neutral = {0, 0, 0}; - if (remaining_costs == neutral) - { - this->upgrades[upgrade] = true; + Resource costs = pair->second; + Resource remaining_costs = this->grid->consume_resources_of_cluster(cluster, costs); + static const Resource neutral = {0, 0, 0}; + if (remaining_costs == neutral) + { + this->upgrades[upgrade] = true; + } } + delete cluster; return this->upgrades[upgrade]; } @@ -234,36 +234,38 @@ FieldMeta *FieldMeta::get_neighbor(Uint8 direction) FieldMeta *HexagonGrid::get_neighbor(FieldMeta *meta, Uint8 direction) { Field neighbor_field = meta->get_field().get_neighbor(direction); - try - { - return this->fields.at(neighbor_field); - } - catch (const std::out_of_range &oor) - { - std::cerr << "Tried to look up non-existing field: " << neighbor_field << std::endl; - } - return nullptr; + FieldMeta *neighbor = nullptr; + auto pair = this->fields.find(neighbor_field); + if (pair != this->fields.end()) + neighbor = pair->second; + return neighbor; } -Cluster *HexagonGrid::get_cluster(FieldMeta *field, Cluster *visited) +Cluster HexagonGrid::get_cluster(FieldMeta *field) { - if (visited == nullptr) - visited = new Cluster(); - if (visited->find(field) != visited->end()) // already been here before - return visited; - else - visited->insert(field); - for (Uint8 i = 0; i < 6; i++) + Cluster visited = Cluster(); + FieldMeta *current = nullptr; + std::set seen = {field}; + while (!seen.empty()) // still unvisited fields, that can be reached { - FieldMeta *neighbor = this->get_neighbor(field, i); - if (neighbor->get_owner() != field->get_owner()) // ignore meta if field not owned by specified owner - return visited; - this->get_cluster(neighbor, visited); + current = *(seen.begin()); + seen.erase(current); + for (Uint8 i = 0; i < 6; i++) + { + FieldMeta *neighbor = this->get_neighbor(current, i); + // neighbor is unvisited, unseen and inside same cluster + if (neighbor != nullptr && *(neighbor->get_owner()) == *(current->get_owner()) + && visited.find(neighbor) == visited.end() && seen.find(neighbor) == seen.end()) + { + seen.insert(neighbor); // discovered an unseen neighbor, will visit later + } + } + visited.insert(current); // have seen all of the neighbors for this field } return visited; } -Resource Grid::consume_resources_of_cluster(Cluster *cluster, Resource costs) +Resource HexagonGrid::consume_resources_of_cluster(Cluster *cluster, Resource costs) { for (FieldMeta *meta : *cluster) { @@ -272,7 +274,6 @@ Resource Grid::consume_resources_of_cluster(Cluster *cluster, Resource costs) costs -= meta->get_resources(); meta->consume_resources(tmp); } - delete cluster; return costs; // > {0, 0, 0} means there were not enough resources } @@ -282,7 +283,7 @@ bool Player::fight(FieldMeta *field) { return false; } - if (*(field->get_owner()) == Player()) // still to be had + if (field->get_owner()->get_id().is_nil()) // still to be had { field->set_owner(this); return true; @@ -311,16 +312,10 @@ bool Player::fight(FieldMeta *field) return false; } -void FieldMeta::handle_event(const SDL_Event *event, EventContext *context) +void FieldMeta::handle_event(const SDL_Event *event) { - switch (event->type - context->base_event) - { - case BOB_FIELDUPDATEEVENT: - this->regenerate_resources(); - break; - default: - break; - } + if (event->type == BOB_NEXTTURNEVENT) + this->regenerate_resources(); } bool HexagonGrid::render(SDL_Renderer *renderer) @@ -350,7 +345,7 @@ bool HexagonGrid::render(SDL_Renderer *renderer) return true; } -void Grid::handle_event(SDL_Event *event, EventContext *context) +void HexagonGrid::handle_event(SDL_Event *event) { SDL_Point mouse = {0, 0}; SDL_GetMouseState(&mouse.x, &mouse.y); @@ -360,32 +355,32 @@ void Grid::handle_event(SDL_Event *event, EventContext *context) switch (event->type) { case SDL_MOUSEWHEEL: - if (old_size + scroll < 10) - { - this->layout->size = 10; - } - else if (old_size + scroll > 100) - { - this->layout->size = 100; - } - else - { - this->layout->size += scroll; - } - this->move(((1.0 - (double) this->layout->size / old_size) * (mouse - old_origin))); + if (old_size + scroll < 10) + { + this->layout->size = 10; + } + else if (old_size + scroll > 100) + { + this->layout->size = 100; + } + else + { + this->layout->size += scroll; + } + this->move(((1.0 - (double) this->layout->size / old_size) * (mouse - old_origin))); + if (!on_rectangle(&layout->box)) + this->layout->size -= scroll; break; case SDL_MOUSEMOTION: - if (this->panning) - { - SDL_Point mouse = {0, 0}; - SDL_GetMouseState(&mouse.x, &mouse.y); - Point marker_pos = this->marker->get_field().field_to_point(this->layout); - SDL_Point p; - p.x = (int) marker_pos.x; - p.y = (int) marker_pos.y; - this->move(mouse - p); - } - this->update_marker(); + if (this->panning) + { + Point marker_pos = this->marker->get_field().field_to_point(this->layout); + SDL_Point p; + p.x = (int) marker_pos.x; + p.y = (int) marker_pos.y; + this->move(mouse - p); + } + this->update_marker(); break; case SDL_MOUSEBUTTONDOWN: switch (event->button.button) @@ -400,9 +395,13 @@ void Grid::handle_event(SDL_Event *event, EventContext *context) default: break; } + for (auto elem : this->fields) + { + elem.second->handle_event(event); + } } -void Grid::move(SDL_Point m) +void HexagonGrid::move(SDL_Point m) { this->layout->origin = this->layout->origin + m; // check if some part is inside layout->box @@ -411,7 +410,7 @@ void Grid::move(SDL_Point m) this->update_marker(); } -void Grid::update_marker() +void HexagonGrid::update_marker() { SDL_Point m = {0, 0}; SDL_GetMouseState(&(m.x), &(m.y)); @@ -420,26 +419,30 @@ void Grid::update_marker() p.y = m.y; FieldMeta *n_marker = this->point_to_field(p); if (n_marker != nullptr) + { this->marker = n_marker; + SDL_Event event; + SDL_memset(&event, 0, sizeof(event)); /* or SDL_zero(event) */ + event.type = BOB_MARKERUPDATE; + event.user.code = 0x0; + event.user.data1 = static_cast(n_marker); + event.user.data2 = 0; + SDL_PushEvent(&event); + } } -FieldMeta *Grid::point_to_field(const Point p) +FieldMeta *HexagonGrid::point_to_field(const Point p) { Field field = p.point_to_field(this->layout); FieldMeta *meta = nullptr; - try - { - meta = this->fields.at(field); - } - catch (const std::out_of_range &oor) - { - //std::cerr << "Tried to access non-existant field " << field << ": " << oor.what() << std::endl; - } + auto pair = this->fields.find(field); + if (pair != this->fields.end()) + meta = pair->second; return meta; } -bool Grid::on_rectangle(SDL_Rect *rect) +bool HexagonGrid::on_rectangle(SDL_Rect *rect) { // check if center inside rect for ANY field for (const auto &pair : this->fields) @@ -456,8 +459,9 @@ bool Grid::on_rectangle(SDL_Rect *rect) return false; } -void Grid::update_box(SDL_Point dimensions) +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; } diff --git a/src/Gameplay.hpp b/src/Gameplay.hpp index 8b65d6b..824fdea 100644 --- a/src/Gameplay.hpp +++ b/src/Gameplay.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -187,7 +188,7 @@ struct Field assert(x + y + z == 0); } - bool operator==(const Field &rhs) const + inline bool operator==(const Field &rhs) const { return (this->x == rhs.x && this->y == rhs.y); } @@ -306,8 +307,12 @@ struct Field }; // from upper right corner -const std::vector hex_directions = {Field(1, 0, -1), Field(0, 1, -1), Field(-1, 1, 0), Field(-1, 0, 1), - Field(-1, 1, 0)}; +const std::vector hex_directions = {{+1, -1, 0}, + {+1, 0, -1}, + {0, +1, -1}, + {-1, +1, 0}, + {-1, 0, +1}, + {0, -1, +1}}; Point field_corner_offset(Uint8 corner, const Layout *layout); @@ -492,9 +497,7 @@ public: std::string get_name() { std::ostringstream descriptor; - boost::uuids::uuid id = this->uuid; - uint8_t *data = id.data; - Uint16 number = (data[14] << 8) | (data[15]); + int number = (this->uuid.data[0] << 8) | this->uuid.data[1]; descriptor << this->name << " (" << std::hex << number << ")"; return descriptor.str(); } @@ -503,9 +506,14 @@ public: boost::uuids::uuid get_id() { return this->uuid; } - bool operator==(const Player &rhs) const + inline bool operator==(const Player &rhs) const { - return rhs.uuid == this->uuid; + return this->uuid == rhs.uuid; + } + + inline bool operator!=(const Player &rhs) const + { + return !(*this == rhs); } private: @@ -521,8 +529,8 @@ class HexagonGrid; class FieldMeta { public: - FieldMeta(Field field_, Player *owner_) - : field(field_), owner(owner_) + FieldMeta(HexagonGrid *grid_, Field field_, Player *owner_) + : grid(grid_), field(field_), owner(owner_) { this->upgrades = 0; static std::random_device rd; @@ -533,6 +541,7 @@ public: this->resources_base.square = distro(rng); this->offense = 1; this->defense = 1; + this->regenerate_resources(); } HexagonGrid *get_grid() { return this->grid; } @@ -559,7 +568,7 @@ public: bool upgrade(Upgrade upgrade); - void handle_event(const SDL_Event *event, EventContext *context); + void handle_event(const SDL_Event *event); FieldMeta *get_neighbor(Uint8 direction); @@ -576,20 +585,32 @@ private: typedef std::unordered_set Cluster; -class Grid +class HexagonGrid { - public: - Grid(Layout *layout_) - : layout(layout_) + HexagonGrid(Sint16 grid_radius, Layout *layout_) + : layout(layout_), radius(grid_radius) { - Field f = {0, 0, 0}; std::unordered_map fields = std::unordered_map(); this->default_player = new Player(); - this->marker = new FieldMeta(f, this->default_player); - }; + // first lower half, then upper half + Field new_field = {0, 0, 0}; + for (Sint16 x = -grid_radius; x <= grid_radius; x++) + { + Sint16 y_l = (-grid_radius > -x - grid_radius) ? -grid_radius : -x - grid_radius; + Sint16 y_u = (grid_radius < -x + grid_radius) ? grid_radius : -x + grid_radius; + for (Sint16 y = y_l; y <= y_u; y++) + { + Sint16 z = -x - y; + new_field = {x, y, z}; + FieldMeta *meta = new FieldMeta(this, new_field, this->default_player); + this->fields.insert({new_field, meta}); + } + } + this->marker = new FieldMeta(this, new_field, this->default_player); + } - ~Grid() + ~HexagonGrid() { for (auto const &elem : this->fields) { @@ -598,65 +619,36 @@ public: delete this->default_player; } - void move(SDL_Point move); - - void update_marker(); - - virtual bool render(SDL_Renderer *renderer) { return false; }; - - void handle_event(SDL_Event *event, EventContext *context); - - void update_box(SDL_Point dimensions); - - Resource get_resources_of_cluster(const Cluster *cluster); - - virtual FieldMeta *get_neighbor(FieldMeta *field, Uint8 direction) = 0; - - virtual Cluster *get_cluster(FieldMeta *field, Cluster *visited = nullptr) = 0; - - Resource consume_resources_of_cluster(Cluster *cluster, Resource costs); - - FieldMeta *point_to_field(const Point p); - -protected: - std::unordered_map fields; - Layout *layout; - FieldMeta *marker; - bool panning; - Player *default_player; - bool on_rectangle(SDL_Rect *rect); -}; - -class HexagonGrid : public Grid -{ -public: - HexagonGrid(Sint16 grid_radius, Layout *layout) - : Grid(layout), radius(grid_radius) - { - // first lower half, then upper half - for (Sint16 x = -grid_radius; x <= grid_radius; x++) - { - Sint16 y_l = (-grid_radius > -x - grid_radius) ? -grid_radius : -x - grid_radius; - Sint16 y_u = (grid_radius < -x + grid_radius) ? grid_radius : -x + grid_radius; - for (Sint16 y = y_l; y <= y_u; y++) - { - Sint16 z = -x - y; - Field new_field = {x, y, z}; - FieldMeta *meta = new FieldMeta(new_field, this->default_player); - this->fields.insert({new_field, meta}); - } - } - } - FieldMeta *get_neighbor(FieldMeta *field, Uint8 direction); - Cluster *get_cluster(FieldMeta *field, Cluster *visited = nullptr); + Cluster get_cluster(FieldMeta *field); bool render(SDL_Renderer *renderer); Sint16 get_radius() { return radius * layout->size; } + void move(SDL_Point move); + + void update_marker(); + + void update_dimensions(SDL_Point dimensions); + + Resource get_resources_of_cluster(Cluster *cluster); + + Resource consume_resources_of_cluster(Cluster *cluster, Resource costs); + + FieldMeta *point_to_field(const Point p); + + void handle_event(SDL_Event *event); + private: + std::unordered_map fields; + Layout *layout; + FieldMeta *marker; + bool panning; + Player *default_player; + + bool on_rectangle(SDL_Rect *rect); Sint16 radius; }; diff --git a/src/Gui.cpp b/src/Gui.cpp index 5a4bcd1..08758bc 100644 --- a/src/Gui.cpp +++ b/src/Gui.cpp @@ -21,8 +21,10 @@ TTF_Font *load_font_from_file(std::string path_to_file, int size) bool TextBox::load_text(std::string text) { - SDL_Surface *surface = TTF_RenderUTF8_Solid(this->font, text.c_str(), {0xff, 0xff, 0xff, 0xff}); - if (surface == nullptr || TTF_SizeUTF8(this->font, text.c_str(), &(this->dimensions.w), &(this->dimensions.h))) + const char *displayed_text = text.c_str(); + SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped(this->font, displayed_text, {0xff, 0xff, 0xff, 0xff}, + this->dimensions.w); + if (surface == nullptr) { SDL_FreeSurface(surface); throw SDL_TTFException(); @@ -31,6 +33,8 @@ bool TextBox::load_text(std::string text) { std::cerr << "Overfull TextBox!" << std::endl; } + this->dimensions.w = surface->w; + this->dimensions.h = surface->h; if (this->texture != nullptr) { SDL_DestroyTexture(this->texture); @@ -96,43 +100,49 @@ void Renderer::present() SDL_RenderPresent(this->renderer); } -void TextBox::handle_event(const SDL_Event *event, EventContext *context) +void Container::handle_event(SDL_Event *event) { + for (auto box : this->elements) + box->handle_event(event); } -void FieldBox::handle_event(const SDL_Event *event, EventContext *context) +void FieldBox::handle_event(const SDL_Event *event) { - std::ostringstream output; - Cluster *cluster = this->field->get_grid()->get_cluster(this->field); - Resource cluster_resources = this->field->get_grid()->get_resources_of_cluster(cluster); - Resource field_resources = this->field->get_resources(); - FieldUpdate *update = (FieldUpdate *) event->user.data1; -/* switch (event->type) + Field *field_update; + if (event->type == BOB_FIELDUPDATEEVENT) { - case (BOB_FIELD_UPDATE_EVENT): - output << this->field->get_owner()->get_name() << std::endl; - output << "● " << cluster_resources.circle << " (" << field_resources.circle << ")" << std::endl; - output << "▲ " << cluster_resources.triangle << " (" << field_resources.triangle << ")" << std::endl; - output << "■ " << cluster_resources.square << " (" << field_resources.square << ")" << std::endl; - this->field_info->load_text(output.str()); - break; - case (BOB_UPDATE_MARKER_EVENT): - this->field = update->field; - break; - default: - break; - }*/ + field_update = reinterpret_cast(event->user.data1); + if (*field_update == this->field->get_field()) + { + this->update(); + } + } + else if (event->type == BOB_MARKERUPDATE) + { + this->field = static_cast(event->user.data1); + this->update(); + } } -void ButtonInfoBox::handle_event(const SDL_Event *event, EventContext *context) +void FieldBox::update() +{ + HexagonGrid *grid = this->field->get_grid(); + Cluster cluster = grid->get_cluster(this->field); + Resource cluster_resources = grid->get_resources_of_cluster(&cluster); + Resource field_resources = this->field->get_resources(); + std::ostringstream output; + output << this->field->get_owner()->get_name() << "\n" + << "● " << (int) cluster_resources.circle << " (" << (int) field_resources.circle << ")" << "\n" + << "▲ " << (int) cluster_resources.triangle << " (" << (int) field_resources.triangle << ")" << "\n" + << "■ " << (int) cluster_resources.square << " (" << (int) field_resources.square << ")" << "\n"; + this->load_text(output.str()); +} + +void ButtonInfoBox::handle_event(const SDL_Event *event) { }; -void UpgradeBox::handle_event(const SDL_Event *event, EventContext *context) -{ -} - -void Box::handle_event(const SDL_Event *event, EventContext *context) +void UpgradeBox::handle_event(const SDL_Event *event) { } @@ -161,4 +171,15 @@ void Container::set_visible(bool visible) { box->set_visible(visible); } +} + +void Container::update_dimensions(SDL_Point dimensions) +{ + for (auto box : this->elements) + box->update_dimensions(dimensions); +} + +void Box::update_dimensions(SDL_Point dimensions) +{ + this->dimensions.x = 0; } \ No newline at end of file diff --git a/src/Gui.hpp b/src/Gui.hpp index 3479df7..c058e02 100644 --- a/src/Gui.hpp +++ b/src/Gui.hpp @@ -93,7 +93,7 @@ public: SDL_DestroyTexture(this->texture); } - virtual void handle_event(const SDL_Event *event, EventContext *context); + void update_dimensions(SDL_Point dimensions); virtual void render(Renderer *renderer); @@ -101,6 +101,7 @@ public: SDL_Rect get_dimensions() { return this->dimensions; } + virtual void handle_event(const SDL_Event *event) = 0; protected: Renderer *renderer; SDL_Texture *texture; @@ -115,9 +116,9 @@ public: TextBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font_) : Box(renderer, dimensions, color), font(font_) { } - virtual void handle_event(const SDL_Event *event, EventContext *context); + virtual bool load_text(std::string text); - bool load_text(std::string text); + virtual void handle_event(const SDL_Event *event) { }; protected: TTF_Font *font; @@ -129,7 +130,9 @@ public: FieldBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font, FieldMeta *field_) : TextBox(renderer, dimensions, color, font), field(field_) { } - void handle_event(const SDL_Event *event, EventContext *context); + void handle_event(const SDL_Event *event); + + void update(); private: FieldMeta *field; @@ -141,7 +144,7 @@ public: UpgradeBox(Renderer *renderer, SDL_Rect dimensions, FieldMeta *field_, SDL_Color color, TTF_Font *font) : TextBox(renderer, dimensions, color, font) { } - void handle_event(const SDL_Event *event, EventContext *context); + void handle_event(const SDL_Event *event); }; class ButtonInfoBox : public TextBox @@ -151,7 +154,7 @@ public: UpgradeBox *upgrade_box_) : TextBox(renderer, dimensions, color, font), upgrade_box(upgrade_box_) { } - void handle_event(const SDL_Event *event, EventContext *context); + void handle_event(const SDL_Event *event); private: UpgradeBox *upgrade_box; @@ -172,6 +175,10 @@ public: void set_visible(bool visible); + void handle_event(SDL_Event *event); + + void update_dimensions(SDL_Point dimensions); + private: Window *window; Renderer *renderer;