Display upgrade information.

This commit is contained in:
Tim Schubert 2016-01-26 00:33:48 +01:00
parent 21249de7d6
commit 78c33d84b6
9 changed files with 340 additions and 67 deletions

View file

@ -23,12 +23,16 @@ void Game::handle_event(SDL_Event *event)
break;
case SDL_MOUSEMOTION:
grid->handle_event(event);
this->side_bar->handle_event(event);
this->upgrade_box->handle_event(event);
break;
case SDL_MOUSEWHEEL:
grid->handle_event(event);
break;
case SDL_MOUSEBUTTONDOWN:
grid->handle_event(event);
this->grid->handle_event(event);
this->side_bar->handle_event(event);
this->upgrade_box->handle_event(event);
break;
case SDL_KEYDOWN:
switch (event->key.keysym.sym)
@ -48,7 +52,8 @@ void Game::handle_event(SDL_Event *event)
case SDLK_f:
window_size = this->window->toggle_fullscreen();
this->grid->update_dimensions(window_size);
this->side_bar->update_dimensions(window_size);
this->field_box->update_position({0, 20});
this->upgrade_box->set_visible(false);
break;
case SDLK_ESCAPE:
this->quit = true;
@ -78,10 +83,11 @@ void Game::handle_event(SDL_Event *event)
break;
default:
if (event->type == BOB_MARKERUPDATE || event->type == BOB_NEXTTURNEVENT ||
event->type == BOB_FIELDUPDATEEVENT)
event->type == BOB_FIELDUPDATEEVENT || event->type == BOB_FIELDSELECTED)
{
this->grid->handle_event(event);
this->side_bar->handle_event(event);
this->upgrade_box->handle_event(event);
}
break;
}
@ -127,6 +133,7 @@ void Game::render()
this->renderer->clear();
this->grid->render(this->renderer->get_renderer());
this->side_bar->render(this->renderer);
this->upgrade_box->render(this->renderer);
this->renderer->present();
}
catch (const SDL_RendererException &err)
@ -165,7 +172,8 @@ int main(int, char **)
}
SDL_Rect window_dimensions = {SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGTH};
Game *game = new Game(&window_dimensions, 2);
int exit_status = game->game_loop();
int exit_status = 1;
exit_status = game->game_loop();
delete game;
TTF_Quit();
SDL_Quit();

View file

@ -32,29 +32,39 @@ public:
this->move[i] = false;
}
this->quit = false;
SDL_Color fg = {0x00, 0xff, 0x00, 0xff};
SDL_Color fg = {0xff, 0xff, 0xff, 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
| SDL_RENDERER_TARGETTEXTURE);
FieldMeta *center = this->grid->get_field({0, 0, 0});
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},
{0, 20, 0, 0},
fg,
this->font,
this->grid->point_to_field({0.0, 0.0})
center
);
this->upgrade_box = new UpgradeBox(this->renderer,
{0, 0, 210, 140},
fg,
this->font,
center
);
this->test_box = new TextBox(this->renderer,
{0, 0, SIDEBAR_WIDTH, SCREEN_HEIGTH},
fg, this->font
fg,
this->font
);
this->test_box->set_visible(true);
this->side_bar->add(test_box);
this->side_bar->add(field_box);
this->side_bar->set_visible(true);
//this->side_bar->add(upgrade_box);
//this->side_bar->set_visible(true);
}
catch (const SDL_Exception &sdl_except)
{
@ -85,6 +95,7 @@ public:
int game_loop();
private:
UpgradeBox *upgrade_box;
FieldBox *field_box;
TextBox *test_box;
TTF_Font *font;

View file

@ -1,2 +1,2 @@
add_executable(Bob Bob.cpp Bob.hpp Gameplay.cpp Gameplay.hpp Gui.hpp Gui.cpp Events.cpp Exceptions.hpp)
add_executable(Bob Bob.cpp Bob.hpp Gameplay.cpp Gameplay.hpp Gui.hpp Gui.cpp Events.cpp Exceptions.hpp Pixelmask.h)
target_link_libraries(Bob ${SDL2_LIB} ${SDL2_GFX_LIB} ${SDL2_TTF_LIB} ${Boost_LIBRARIES})

View file

@ -3,6 +3,7 @@
const Uint32 BOB_NEXTTURNEVENT = register_events(1);
const Uint32 BOB_MARKERUPDATE = register_events(1);
const Uint32 BOB_FIELDUPDATEEVENT = register_events(1);
const Uint32 BOB_FIELDSELECTED = register_events(1);
void Timer::start_timer()
{

View file

@ -10,6 +10,7 @@
extern const Uint32 BOB_NEXTTURNEVENT;
extern const Uint32 BOB_MARKERUPDATE;
extern const Uint32 BOB_FIELDUPDATEEVENT;
extern const Uint32 BOB_FIELDSELECTED;
#endif
Uint32 register_events(Uint32 n);

View file

@ -183,6 +183,17 @@ void FieldMeta::render(SDL_Renderer *renderer, Layout *layout)
}
}
void FieldMeta::trigger_event(Uint32 type, Sint32 code)
{
SDL_Event event;
SDL_memset(&event, 0, sizeof(event)); /* or SDL_zero(event) */
event.type = type;
event.user.code = code;
event.user.data1 = static_cast<void *>(this);
event.user.data2 = 0;
SDL_PushEvent(&event);
}
void FieldMeta::regenerate_resources()
{
this->resources = resources_base;
@ -192,6 +203,7 @@ void FieldMeta::regenerate_resources()
this->resources *= 2;
if (this->upgrades[Regeneration_3])
this->resources *= 2;
this->trigger_event(BOB_FIELDUPDATEEVENT, 0);
}
Resource HexagonGrid::get_resources_of_cluster(Cluster *cluster)
@ -208,21 +220,24 @@ Resource HexagonGrid::get_resources_of_cluster(Cluster *cluster)
bool FieldMeta::upgrade(Upgrade upgrade)
{
// check available resources for cluster and consume resources
Cluster *cluster = new Cluster();
this->grid->get_cluster(this);
Resource cluster_resources = this->grid->get_resources_of_cluster(cluster);
if (this->upgrades[upgrade])
return this->upgrades[upgrade];
Cluster 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 = pair->second;
Resource remaining_costs = this->grid->consume_resources_of_cluster(cluster, costs);
if (costs > cluster_resources) // too expensive for you
return this->upgrades[upgrade];
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;
this->trigger_event(BOB_FIELDUPDATEEVENT, 0);
return this->upgrades[upgrade];
}
@ -265,6 +280,12 @@ Cluster HexagonGrid::get_cluster(FieldMeta *field)
return visited;
}
void FieldMeta::consume_resources(Resource costs)
{
this->resources -= costs;
this->trigger_event(BOB_FIELDUPDATEEVENT, 0);
}
Resource HexagonGrid::consume_resources_of_cluster(Cluster *cluster, Resource costs)
{
for (FieldMeta *meta : *cluster)
@ -388,6 +409,12 @@ void HexagonGrid::handle_event(SDL_Event *event)
case SDL_BUTTON_MIDDLE:
this->panning = !(this->panning);
break;
case SDL_BUTTON_RIGHT:
this->marker->trigger_event(BOB_FIELDSELECTED, 0);
break;
//case SDL_BUTTON_LEFT:
// this->marker->trigger_event(BOB_FIELDSELECTED, 1);
// break;
default:
break;
}
@ -421,13 +448,11 @@ void HexagonGrid::update_marker()
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);
n_marker->trigger_event(BOB_MARKERUPDATE, 0);
}
else
{
marker->trigger_event(BOB_MARKERUPDATE, 1);
}
}
@ -442,6 +467,15 @@ FieldMeta *HexagonGrid::point_to_field(const Point p)
}
FieldMeta *HexagonGrid::get_field(Field field)
{
FieldMeta *meta = nullptr;
auto pair = this->fields.find(field);
if (pair != this->fields.end())
meta = pair->second;
return meta;
}
bool HexagonGrid::on_rectangle(SDL_Rect *rect)
{
// check if center inside rect for ANY field
@ -465,3 +499,8 @@ void HexagonGrid::update_dimensions(SDL_Point dimensions)
this->layout->box.w = dimensions.x;
this->layout->box.h = dimensions.y;
}
Point HexagonGrid::field_to_point(FieldMeta *field)
{
return field->get_field().field_to_point(this->layout);
}

View file

@ -23,8 +23,6 @@
#include <SDL2/SDL2_gfxPrimitives.h>
#include "Events.hpp"
#define NUM_UPGRADES 10
SDL_Point operator+(SDL_Point left, SDL_Point right);
SDL_Point operator-(SDL_Point left, SDL_Point right);
@ -339,8 +337,6 @@ inline std::ostream &operator<<(std::ostream &os, const Field &rhs)
return os;
}
typedef std::bitset<NUM_UPGRADES> UpgradeFlags;
struct Resource
{
Uint8 circle;
@ -441,7 +437,6 @@ struct Resource
enum Upgrade
{
First_Upgrade = 0,
Regeneration_1,
Regeneration_2,
Regeneration_3,
@ -450,6 +445,13 @@ enum Upgrade
Reproduction_3
};
const std::vector<Upgrade> UPGRADES = {Regeneration_1, Regeneration_2, Regeneration_3, Reproduction_1, Reproduction_2,
Reproduction_3};
const int NUM_UPGRADES = 6;
typedef std::bitset<NUM_UPGRADES> UpgradeFlags;
namespace std
{
template<>
@ -475,6 +477,28 @@ const std::unordered_map<Upgrade, Resource> UPGRADE_COSTS(
}
);
const std::unordered_map<Upgrade, std::string> UPGRADE_NAMES(
{
{Regeneration_1, "Regeneration 1"},
{Regeneration_2, "Regeneration 2"},
{Regeneration_3, "Regeneration 3"},
{Reproduction_1, "Reproduction 1"},
{Reproduction_2, "Reproduction 2"},
{Reproduction_3, "Reproduction 3"}
}
);
const std::unordered_map<Upgrade, std::string> UPGRADE_TEXTS(
{
{Regeneration_1, "Resources yield 2x their base resources per turn."},
{Regeneration_2, "Resources yield 4x their base resources per turn."},
{Regeneration_3, "Resources yield 8x their base resources per turn."},
{Reproduction_1, "Not used yet!"},
{Reproduction_2, "Not used yet!"},
{Reproduction_3, "Not used yet!"}
}
);
class FieldMeta;
class Player
@ -562,7 +586,7 @@ public:
UpgradeFlags get_upgrades() { return this->upgrades; }
void consume_resources(Resource costs) { this->resources -= costs; }
void consume_resources(Resource costs);
void regenerate_resources();
@ -572,6 +596,8 @@ public:
FieldMeta *get_neighbor(Uint8 direction);
void trigger_event(Uint32 type, Sint32 code);
private:
const Field field;
HexagonGrid *grid;
@ -639,6 +665,10 @@ public:
FieldMeta *point_to_field(const Point p);
Point field_to_point(FieldMeta *field);
FieldMeta *get_field(Field field);
void handle_event(SDL_Event *event);
private:

View file

@ -22,17 +22,17 @@ TTF_Font *load_font_from_file(std::string path_to_file, int size)
bool TextBox::load_text(std::string text)
{
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);
SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped(this->font, displayed_text, this->color, 100);
if (surface == nullptr)
{
SDL_FreeSurface(surface);
throw SDL_TTFException();
}
else if (surface->w > this->dimensions.w || surface->h > this->dimensions.h)
/*else if (surface->w > this->dimensions.w || surface->h > this->dimensions.h)
{
std::cerr << "Overfull TextBox!" << std::endl;
}
*/
this->dimensions.w = surface->w;
this->dimensions.h = surface->h;
if (this->texture != nullptr)
@ -73,11 +73,10 @@ SDL_Point Window::toggle_fullscreen()
return window_size;
}
bool Window::position_inside_window(SDL_Point position)
bool inside_target(const SDL_Rect *target, const SDL_Point *position)
{
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(this->window), &dm);
return position.x > 0 && position.x < dm.w && position.y > 0 && position.y < dm.h;
return target->x < position->x && target->x + target->w > position->x && target->y < position->y &&
target->y + target->h > position->y;
}
int Window::get_window_id()
@ -108,17 +107,20 @@ void Container::handle_event(SDL_Event *event)
void FieldBox::handle_event(const SDL_Event *event)
{
Field *field_update;
if (event->type == BOB_FIELDUPDATEEVENT)
{
field_update = reinterpret_cast<Field *>(event->user.data1);
if (*field_update == this->field->get_field())
FieldMeta *field_update = reinterpret_cast<FieldMeta *>(event->user.data1);
if (field_update == this->field)
{
this->update();
}
}
else if (event->type == BOB_MARKERUPDATE)
{
if (event->user.code == 0)
this->visible = true;
else
this->visible = false;
this->field = static_cast<FieldMeta *>(event->user.data1);
this->update();
}
@ -138,12 +140,112 @@ void FieldBox::update()
this->load_text(output.str());
}
void ButtonInfoBox::handle_event(const SDL_Event *event)
void UpgradeButtonBox::set_active(bool state)
{
};
this->active = state;
if (state)
{
this->color = {0x0, 0x0, 0xff, this->color.a};
this->load_text(UPGRADE_NAMES.at(this->upgrade));
}
}
void UpgradeBox::handle_event(const SDL_Event *event)
{
if (event->type == SDL_MOUSEBUTTONDOWN && this->visible)
{
SDL_Point m_pos;
SDL_GetMouseState(&m_pos.x, &m_pos.y);
if (inside_target(&(this->dimensions), &m_pos))
{
if (marked_upgrade != nullptr)
{
this->marked_upgrade->handle_event(event);
}
}
else
{
this->set_visible(false);
}
}
else if (event->type == BOB_FIELDSELECTED)
{
FieldMeta *selected = static_cast<FieldMeta *>(event->user.data1);
if (selected != nullptr && event->user.code == 0x0)
{
this->set_visible(true);
this->field = selected;
Point p_pos = selected->get_grid()->field_to_point(selected);
SDL_Point point = {(int) p_pos.x, (int) p_pos.y};
this->update_position(point);
}
else
{
this->set_visible(false);
}
}
else if (event->type == BOB_FIELDUPDATEEVENT)
{
// mark updates active / inactive
this->field = static_cast<FieldMeta *>(event->user.data1);
UpgradeFlags updated_upgrades = this->field->get_upgrades();
for (auto upgrade : this->upgrades)
{
upgrade->set_active(updated_upgrades[upgrade->get_upgrade()]);
}
}
else if (event->type == SDL_MOUSEMOTION && this->visible)
{
SDL_Point pos;
SDL_GetMouseState(&(pos.x), &(pos.y));
// update the info text field for the selected update
for (auto box : this->upgrades)
{
SDL_Rect target = box->get_dimensions();
if (this->marked_upgrade != box && inside_target(&target, &pos))
{
this->marked_upgrade = box;
Resource costs = UPGRADE_COSTS.at(box->get_upgrade());
std::ostringstream output;
output //<< UPGRADE_NAMES.at(box->get_upgrade()) << "\n"
<< "" << (int) costs.circle << "\n"
<< "" << (int) costs.triangle << "\n"
<< "" << (int) costs.square << "\n"
<< UPGRADE_TEXTS.at(box->get_upgrade());
this->upgrade_info->load_text(output.str());
}
}
}
}
void UpgradeButtonBox::handle_event(const SDL_Event *event)
{
SDL_Point pos;
SDL_GetMouseState(&(pos.x), &(pos.y));
if (event->type == SDL_MOUSEBUTTONDOWN && this->visible)
{
if (inside_target(&(this->dimensions), &pos))
{
this->box->get_field()->upgrade(this->upgrade);
}
}
}
void UpgradeBox::render(Renderer *ext_renderer)
{
if (this->visible && this->texture != nullptr)
{
// copy background
if (SDL_RenderCopy(ext_renderer->get_renderer(), this->texture, nullptr, &(this->dimensions)) < 0)
{
throw SDL_RendererException();
}
this->upgrade_info->render(ext_renderer);
for (auto box : this->upgrades)
{
box->render(ext_renderer);
}
}
}
void Container::render(Renderer *renderer)
@ -173,13 +275,37 @@ void Container::set_visible(bool visible)
}
}
void Container::update_dimensions(SDL_Point dimensions)
void Container::update_position(SDL_Point dimensions)
{
for (auto box : this->elements)
box->update_dimensions(dimensions);
box->update_position(dimensions);
}
void Box::update_dimensions(SDL_Point dimensions)
void Box::update_position(SDL_Point pos)
{
this->dimensions.x = 0;
}
this->dimensions.x = pos.x;
this->dimensions.y = pos.y;
}
void UpgradeBox::update_position(SDL_Point pos)
{
SDL_Point d_pos = pos;
this->dimensions.x = pos.x;
this->dimensions.y = pos.y;
for (auto box : this->upgrades)
{
box->update_position(d_pos);
d_pos.y += 20;
}
this->upgrade_info->update_position({pos.x + 110, pos.y});
}
void UpgradeBox::set_visible(bool status)
{
this->visible = status;
this->upgrade_info->set_visible(status);
for (UpgradeButtonBox *box : this->upgrades)
{
box->set_visible(status);
}
}

View file

@ -12,6 +12,7 @@
#include "Exceptions.hpp"
#include "Gameplay.hpp"
#include "Events.hpp"
#include "Pixelmask.h"
SDL_Color operator!(const SDL_Color &color);
@ -43,8 +44,6 @@ public:
SDL_Point toggle_fullscreen();
bool position_inside_window(SDL_Point position);
int get_window_id();
};
@ -88,19 +87,21 @@ public:
this->visible = false;
}
~Box()
virtual ~Box()
{
SDL_DestroyTexture(this->texture);
}
void update_dimensions(SDL_Point dimensions);
virtual void update_position(SDL_Point dimensions);
virtual void render(Renderer *renderer);
void set_visible(bool visibility) { this->visible = visibility; }
virtual void set_visible(bool visibility) { this->visible = visibility; }
SDL_Rect get_dimensions() { return this->dimensions; }
void set_dimensions(SDL_Rect dimensions) { this->dimensions = dimensions; }
virtual void handle_event(const SDL_Event *event) = 0;
protected:
Renderer *renderer;
@ -118,7 +119,7 @@ public:
virtual bool load_text(std::string text);
virtual void handle_event(const SDL_Event *event) { };
virtual void handle_event(const SDL_Event *event) { }
protected:
TTF_Font *font;
@ -132,32 +133,88 @@ public:
void handle_event(const SDL_Event *event);
void update();
virtual void update();
private:
protected:
FieldMeta *field;
};
class UpgradeBox : public TextBox
class UpgradeBox;
class UpgradeButtonBox : public TextBox
{
public:
UpgradeBox(Renderer *renderer, SDL_Rect dimensions, FieldMeta *field_, SDL_Color color, TTF_Font *font)
: TextBox(renderer, dimensions, color, font) { }
UpgradeButtonBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font, UpgradeBox *box_,
Upgrade upgrade)
: TextBox(renderer, dimensions, color, font), box(box_), upgrade(upgrade) { }
Upgrade get_upgrade() { return this->upgrade; }
void handle_event(const SDL_Event *event);
};
class ButtonInfoBox : public TextBox
{
public:
ButtonInfoBox(Renderer *renderer, SDL_Rect dimensions, FieldMeta *field_, SDL_Color color, TTF_Font *font,
UpgradeBox *upgrade_box_)
: TextBox(renderer, dimensions, color, font), upgrade_box(upgrade_box_) { }
void handle_event(const SDL_Event *event);
void set_active(bool state);
private:
UpgradeBox *upgrade_box;
UpgradeBox *box;
Upgrade upgrade;
bool active; // this upgrade has been unlocked
};
class UpgradeBox : public Box
{
public:
UpgradeBox(Renderer *renderer, SDL_Rect dimensions, SDL_Color color, TTF_Font *font, FieldMeta *field_)
: Box(renderer, dimensions, color), field(field_)
{
;
this->texture = SDL_CreateTexture(renderer->get_renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,
dimensions.w, dimensions.h);
int y = dimensions.y;
for (Upgrade upgrade : UPGRADES)
{
UpgradeButtonBox *box = new UpgradeButtonBox(renderer, {0, y, 0, 0}, color, font, this, upgrade);
box->load_text(UPGRADE_NAMES.at(upgrade));
y += 20;
this->marked_upgrade = box;
this->upgrades.push_back(box);
}
this->upgrade_info = new TextBox(renderer, {0, 0, 0, 0}, color, font);
renderer->set_draw_color({0x77, 0x77, 0x77, 0x77});
SDL_SetRenderTarget(renderer->get_renderer(), this->texture);
const SDL_Rect bg = dimensions;
if (SDL_RenderFillRect(renderer->get_renderer(), &bg) < 0)
{
SDL_DestroyTexture(this->texture);
SDL_SetRenderTarget(renderer->get_renderer(), nullptr);
throw SDL_RendererException();
}
SDL_SetRenderTarget(renderer->get_renderer(), nullptr);
}
~UpgradeBox()
{
for (auto box : upgrades)
{
delete box;
}
delete upgrade_info;
}
void handle_event(const SDL_Event *event);
void render(Renderer *renderer);
FieldMeta *get_field() { return this->field; }
void update_position(SDL_Point pos);
void set_visible(bool status);
private:
std::vector<UpgradeButtonBox *> upgrades;
UpgradeButtonBox *marked_upgrade;
TextBox *upgrade_info;
FieldMeta *field;
};
class Container
@ -177,7 +234,7 @@ public:
void handle_event(SDL_Event *event);
void update_dimensions(SDL_Point dimensions);
void update_position(SDL_Point dimensions);
private:
Window *window;