Fixed issues with events and SideBar text.
This commit is contained in:
parent
100065e158
commit
21249de7d6
8 changed files with 272 additions and 243 deletions
31
src/Bob.cpp
31
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();
|
||||
|
|
26
src/Bob.hpp
26
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -3,27 +3,16 @@
|
|||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#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
|
||||
{
|
||||
|
|
190
src/Gameplay.cpp
190
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<FieldMeta *> 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<void *>(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;
|
||||
}
|
||||
|
|
132
src/Gameplay.hpp
132
src/Gameplay.hpp
|
@ -10,6 +10,7 @@
|
|||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
#include <set>
|
||||
#include <bitset>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
@ -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<Field> 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<Field> 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<FieldMeta *> 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<Field, FieldMeta *> fields = std::unordered_map<Field, FieldMeta *>();
|
||||
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<Field, FieldMeta *> 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<Field, FieldMeta *> fields;
|
||||
Layout *layout;
|
||||
FieldMeta *marker;
|
||||
bool panning;
|
||||
Player *default_player;
|
||||
|
||||
bool on_rectangle(SDL_Rect *rect);
|
||||
Sint16 radius;
|
||||
};
|
||||
|
||||
|
|
79
src/Gui.cpp
79
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<Field *>(event->user.data1);
|
||||
if (*field_update == this->field->get_field())
|
||||
{
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
else if (event->type == BOB_MARKERUPDATE)
|
||||
{
|
||||
this->field = static_cast<FieldMeta *>(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;
|
||||
}
|
19
src/Gui.hpp
19
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue