From 0d523b6541623466452734220508888cfe8f46b6 Mon Sep 17 00:00:00 2001 From: Tim Schubert Date: Mon, 18 Jan 2016 22:56:26 +0100 Subject: [PATCH] Added resource generation and resource display. Should commit more often... --- src/CMakeLists.txt | 5 +- src/Gameplay.cpp | 162 +++++++++++++++++++++++ src/Gameplay.hpp | 235 ++++++++++++++++++++++++++++++++++ src/{GameMap.cpp => Grid.cpp} | 158 +++++++++++++---------- src/{GameMap.hpp => Grid.hpp} | 79 +++++------- src/Main.cpp | 60 +++++++-- src/Main.hpp | 36 +++++- src/Player.cpp | 0 src/Player.hpp | 9 -- src/Upgrades.cpp | 0 src/Upgrades.hpp | 23 ---- 11 files changed, 605 insertions(+), 162 deletions(-) create mode 100644 src/Gameplay.cpp create mode 100644 src/Gameplay.hpp rename src/{GameMap.cpp => Grid.cpp} (57%) rename src/{GameMap.hpp => Grid.hpp} (77%) delete mode 100644 src/Player.cpp delete mode 100644 src/Player.hpp delete mode 100644 src/Upgrades.cpp delete mode 100644 src/Upgrades.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd156bc..cdad6df 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,2 @@ -add_executable(Bob Main.cpp) -add_library(GameMap GameMap.cpp) -target_link_libraries(Bob GameMap ${SDL2_LIBRARY} ${SDL2GFX_LIBRARY} ${Boost_LIBRARIES}) +add_executable(Bob Main.cpp Main.hpp Grid.cpp Grid.hpp Gameplay.cpp Gameplay.hpp Gui.hpp Gui.cpp) +target_link_libraries(Bob ${SDL2_LIBRARY} ${SDL2GFX_LIBRARY} ${Boost_LIBRARIES}) diff --git a/src/Gameplay.cpp b/src/Gameplay.cpp new file mode 100644 index 0000000..34b67a8 --- /dev/null +++ b/src/Gameplay.cpp @@ -0,0 +1,162 @@ +#include "Gameplay.hpp" + +Player Player::default_player = Player("Default"); + +std::unordered_map FieldMeta::fields = std::unordered_map(); + +Player *FieldMeta::get_owner() +{ + return this->owner; +} + +void FieldMeta::set_owner(Player *player) +{ + this->owner = player; +} + +Field FieldMeta::get_field() { return this->field; } + +void FieldMeta::render(SDL_Renderer *renderer, Layout *layout) +{ + Point precise_location = field_to_point(this->field, layout); + SDL_Point location; + location.x = (int) precise_location.x; + location.y = (int) precise_location.y; + std::vector polygon = field_to_polygon(this->field, layout); + SDL_Color color = this->owner->get_color(); + Sint16 vx[6]; + Sint16 vy[6]; + for (int i = 0; i < 6; i++) + { + vx[i] = (Sint16) polygon[i].x; + vy[i] = (Sint16) polygon[i].y; + } + filledPolygonRGBA(renderer, vx, vy, 6, color.r, color.g, color.b, 0x22); + SDL_Color inverse; + inverse.r = (Uint8) (0xff - color.r); + inverse.g = (Uint8) (0xff - color.g); + inverse.b = (Uint8) (0xff - color.b); + inverse.a = 0xff; + + Uint16 resource_size = (Uint16) (layout->size / 3); + if (this->resources_base.circle > 0) + { + circleRGBA(renderer, (Sint16) (location.x), (Sint16) (location.y), (Sint16) (resource_size), inverse.r, + inverse.g, inverse.b, inverse.a); + } + if (this->resources_base.triangle > 0) + { + static const SDL_Point trigon[] = {{-1, 1}, + {1, 1}, + {0, -1}}; + for (int i = 0; i < 3; i++) + { + vx[i] = (Sint16) (location.x + (trigon[i].x) * resource_size); + vy[i] = (Sint16) (location.y + (trigon[i].y) * resource_size); + } + trigonRGBA(renderer, vx[0], vy[0], vx[1], vy[1], vx[2], vy[2], inverse.r, inverse.g, inverse.b, inverse.a); + } + + if (this->resources_base.square > 0) + { + + static const SDL_Point square[] = {{-1, -1}, + {-1, 1}, + {1, 1}, + {1, -1}}; + for (int i = 0; i < 4; i++) + { + vx[i] = (Sint16) (location.x + (square[i].x) * resource_size); + vy[i] = (Sint16) (location.y + (square[i].y) * resource_size); + } + polygonRGBA(renderer, vx, vy, 4, inverse.r, inverse.g, inverse.b, inverse.a); + } +} + + +void FieldMeta::regenerate_resources() +{ + resources = resources_base; + switch (this->upgrades) + { + case (UPGRADE_REGENERATION_1): + resources *= 2; + case (UPGRADE_REGENERATION_2): + resources *= 2; + case (UPGRADE_REGENERATION_3): + resources *= 2; + default: + break; + } +} + +Resource FieldMeta::get_resources() +{ + return this->resources; +} + +Resource FieldMeta::get_resources_of_cluster() +{ + Resource res = {0, 0, 0}; + std::unordered_set *cluster = new std::unordered_set(); + this->get_cluster(cluster); + for (FieldMeta *elem : *cluster) + { + Resource r_plus = elem->get_resources(); + res += r_plus; + } + delete cluster; + return res; +} + +Uint32 FieldMeta::get_upgrades() { return this->upgrades; } + +bool FieldMeta::upgrade(Upgrade upgrade) +{ + // check available resources for cluster and consume resources + Resource cluster_resources = this->get_resources_of_cluster(); + Resource costs; + switch (upgrade) + { + case UPGRADE_REGENERATION_1: + costs = {(1 << 1), (1 << 1), (1 << 1)}; + break; + case UPGRADE_REGENERATION_2: + costs = {(1 << 2), (1 << 2), (1 << 2)}; + break; + case UPGRADE_REGENERATION_3: + costs = {(1 << 3), (1 << 3), (1 << 3)}; + + break; + default: + std::cout << "Unknown update: " << upgrade; + break; + } + if (cluster_resources > costs) + { + this->resources -= costs; + this->upgrades |= upgrade; + } + return false; +} + +std::unordered_set *FieldMeta::get_cluster(std::unordered_set *visited) +{ + assert(visited != nullptr); + + if (visited->find(this) != visited->end()) // already been here before + return visited; + + visited->insert(this); + + for (Uint8 i = 0; i < 6; i++) + { + auto neighbor_pair = FieldMeta::fields.find(hex_neighbor(i, this->get_field())); + FieldMeta *neighbor = neighbor_pair->second; + if (neighbor->get_owner() != this->get_owner()) // ignore meta if field not owned by specified owner + return visited; + else + return neighbor->get_cluster(visited); + } + return visited; +} diff --git a/src/Gameplay.hpp b/src/Gameplay.hpp new file mode 100644 index 0000000..49bc46c --- /dev/null +++ b/src/Gameplay.hpp @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Grid.hpp" + +typedef enum +{ + UPGRADE_FIRST_UPGRADE = 0, + UPGRADE_REGENERATION_1, + UPGRADE_REGENERATION_2, + UPGRADE_REGENERATION_3, + UPGRADE_REPRODUCTION +} Upgrade; + +#ifndef Tagged + +class Tagged +{ +private: + boost::uuids::uuid tag; + + int state; +public: + // construct new + Tagged() + : tag(boost::uuids::random_generator()()), state(0) { } + + // construct with state + explicit Tagged(int state) + : tag(boost::uuids::random_generator()()), state(state) { } + + // clone + Tagged(Tagged const &rhs) + : tag(rhs.tag), state(rhs.state) { } + + bool operator==(Tagged const &rhs) const + { + return tag == rhs.tag; + } + + bool operator!=(Tagged const &rhs) const + { + return !(tag == rhs.tag); + } + + int get_state() const { return state; } + + void set_state(int new_state) { state = new_state; } + + boost::uuids::uuid get_tag() { return tag; } + + void set_tag(boost::uuids::uuid uuid_) { tag = uuid_; } +}; + +#endif + +#ifndef Player + +class Player : public Tagged +{ +private: + SDL_Color color; + std::string name; + +public: + Player(std::string name_) + : name(name_), Tagged() + { + // use the last 24 bits of the tag for the color + boost::uuids::uuid id = get_tag(); + uint8_t *data = id.data; + this->color = {data[13], data[14], data[15], 0xff}; + } + + Player(std::string name_, boost::uuids::uuid tag_) + : Tagged(), name(name_) + { + this->set_tag(tag_); + } + + SDL_Color get_color() { return color; } + + std::string get_name() + { + std::ostringstream descriptor; + boost::uuids::uuid id = get_tag(); + uint8_t *data = id.data; + Uint16 number = (data[14] << 8) | (data[15]); + descriptor << this->name << " (" << std::hex << number << ")"; + return descriptor.str(); + } + + static Player default_player; +}; + +#endif + +#ifndef Resource + +struct Resource +{ + Uint8 circle; + Uint8 triangle; + Uint8 square; + + Resource &operator+=(const Resource &rhs) + { + this->circle += rhs.circle; + this->triangle += rhs.triangle; + this->square += rhs.square; + return *this; + } + + friend Resource operator+(Resource lhs, const Resource &rhs) + { + lhs += rhs; + return lhs; + } + + Resource &operator-=(const Resource &rhs) + { + this->circle -= rhs.circle; + this->triangle -= rhs.triangle; + this->square -= rhs.square; + return *this; + } + + friend Resource operator-(Resource lhs, const Resource &rhs) + { + lhs -= rhs; + return lhs; + } + + Resource &operator*=(const Resource &rhs) + { + this->circle *= rhs.circle; + this->triangle *= rhs.triangle; + this->square *= rhs.square; + return *this; + } + + friend Resource operator*(Resource lhs, const Resource &rhs) + { + lhs *= rhs; + return lhs; + } + + Resource &operator*=(const double rhs) + { + this->circle *= rhs; + this->triangle *= rhs; + this->square *= rhs; + return *this; + } + + friend Resource operator*(const double lhs, Resource rhs) + { + rhs *= lhs; + return rhs; + } + + friend Resource operator*(Resource lhs, const double rhs) + { + return rhs * lhs; + } + + bool operator<(const Resource &rhs) const + { + return (this->circle < rhs.circle || this->triangle < rhs.triangle || this->square < rhs.square); + } + + inline bool operator>(const Resource &rhs) const { return rhs < *this; } + + inline bool operator<=(const Resource &rhs) const { return !(*this > rhs); } + + inline bool operator>=(const Resource &rhs) const { return !(*this < rhs); } +}; + +#endif + +#ifndef FieldMeta + +class FieldMeta +{ +public: + FieldMeta(Field field_, Player *owner_ = &(Player::default_player)) + : field(field_), owner(owner_) + { + this->upgrades = 0; + static std::random_device rd; + std::mt19937 rng(rd()); + std::uniform_int_distribution distro(0, 1); + this->resources_base.circle = distro(rng); + this->resources_base.triangle = distro(rng); + this->resources_base.square = distro(rng); + std::pair pair(field, this); + this->fields.insert(pair); + } + + Field get_field(); + + Player *get_owner(); + + void set_owner(Player *player); + + void render(SDL_Renderer *renderer, Layout *layout); + + Resource get_resources(); + + Resource get_resources_of_cluster(); + + std::unordered_set *get_cluster(std::unordered_set *visited); + + Uint32 get_upgrades(); + + void regenerate_resources(); + + bool upgrade(Upgrade upgrade); + +private: + const Field field; + static std::unordered_map fields; + Player *owner; + Uint32 upgrades; + Resource resources_base; // without upgrades applied, used as basis of regeneration + Resource resources; // actual current resources +}; + +#endif \ No newline at end of file diff --git a/src/GameMap.cpp b/src/Grid.cpp similarity index 57% rename from src/GameMap.cpp rename to src/Grid.cpp index 5de97fa..c84b3b8 100644 --- a/src/GameMap.cpp +++ b/src/Grid.cpp @@ -1,4 +1,4 @@ -#include "GameMap.hpp" +#include "Grid.hpp" SDL_Point operator+(SDL_Point left, SDL_Point right) { @@ -20,24 +20,26 @@ SDL_Point operator/(SDL_Point left, SDL_Point right) return {(left.x / right.x), (left.x / right.y)}; } -SDL_Point operator*(int left, SDL_Point right) +SDL_Point operator*(double left, SDL_Point right) { - return {left * right.x, left * right.y}; + int x = (int) (left * right.x); + int y = (int) (left * right.y); + return {x, y}; } -SDL_Point operator*(SDL_Point left, int right) +SDL_Point operator*(SDL_Point left, double right) { return right * left; } -SDL_Point operator/(SDL_Point left, int right) +SDL_Point operator/(SDL_Point left, double right) { - return {left.x / right, left.y / right}; + return (1 / right) * left; } -int operator!(SDL_Point left) +double operator!(SDL_Point left) { - int length = (int) std::sqrt(left.x * left.x + left.y * left.y); + double length = std::sqrt(left.x * left.x + left.y * left.y); return length; } @@ -142,55 +144,67 @@ int cubic_distance(Field a, Field b) return (abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z)) / 2; } -Field hex_direction(int direction) +Field hex_direction(Uint8 direction) { assert (0 <= direction && direction <= 5); return hex_directions[direction]; } -Field hex_neighbor(int8_t direction, Field f) +Field hex_neighbor(Uint8 direction, Field f) { return hex_direction(direction) + f; } -Point field_to_point(const Field f, const Layout layout) +Point field_to_point(const Field f, const Layout *layout) { - const Orientation m = layout.orientation; - double x = (m.f0 * f.x + m.f1 * f.y) * layout.size; - double y = (m.f2 * f.x + m.f3 * f.y) * layout.size; - return Point(x + layout.origin.x, y + layout.origin.y); + const Orientation m = layout->orientation; + double x = (m.f0 * f.x + m.f1 * f.y) * layout->size; + double y = (m.f2 * f.x + m.f3 * f.y) * layout->size; + return {x + layout->origin.x, y + layout->origin.y}; } -Field point_to_field(Point point, const Layout layout) +Field point_to_field(Point point, const Layout *layout) { - const Orientation m = layout.orientation; - double rel_x = (point.x - layout.origin.x) / layout.size; - double rel_y = (point.y - layout.origin.y) / layout.size; + const Orientation m = layout->orientation; + double rel_x = (point.x - layout->origin.x) / layout->size; + double rel_y = (point.y - layout->origin.y) / layout->size; double x = m.b0 * rel_x + m.b1 * rel_y; double y = m.b2 * rel_x + m.b3 * rel_y; return cubic_round(x, y, -x - y); } -Point field_corner_offset(uint8_t corner, const Layout layout) +Point field_corner_offset(Uint8 corner, const Layout *layout) { - double angle = 2.0 * M_PI * (corner + layout.orientation.start_angle) / 6; - return Point(layout.size * cos(angle), layout.size * sin(angle)); + double angle = 2.0 * M_PI * (corner + layout->orientation.start_angle) / 6; + double x = (layout->size * cos(angle)); + double y = (layout->size * sin(angle)); + return {x, y}; } -std::vector field_to_polygon(const Field field, const Layout layout) +std::vector field_to_polygon(const Field field, const Layout *layout) { - std::vector corners = {}; + std::vector corners = field_to_polygon_normalized(field, layout); Point center = field_to_point(field, layout); - for (uint8_t i = 0; i < 6; i++) + for (Point &p : corners) { - Point offset = field_corner_offset(i, layout); - corners.push_back(Point(center.x + offset.x, center.y + offset.y)); + p = p + center; } return corners; } -HexagonGrid::HexagonGrid(Sint16 grid_radius, Layout layout) - : Grid(layout) +std::vector field_to_polygon_normalized(const Field field, const Layout *layout) +{ + std::vector corners; + for (uint8_t i = 0; i < 6; i++) + { + Point offset = field_corner_offset(i, layout); + corners.push_back(offset); + } + return corners; +} + +HexagonGrid::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++) @@ -201,10 +215,7 @@ HexagonGrid::HexagonGrid(Sint16 grid_radius, Layout layout) { Sint16 z = -x - y; Field new_field = {x, y, z}; - FieldMeta *meta = new FieldMeta(nullptr); - this->fields.insert(new_field); - std::pair field_pair(new_field, meta); - this->fields_meta.insert(field_pair); + this->fields->insert(new_field); } } } @@ -212,64 +223,51 @@ HexagonGrid::HexagonGrid(Sint16 grid_radius, Layout layout) bool HexagonGrid::render(SDL_Renderer *renderer) { Field some_field = {0, 0, 0}; - std::vector polygon = field_to_polygon(some_field, this->layout); - Point center = field_to_point(some_field, this->layout); + std::vector polygon = field_to_polygon_normalized(some_field, this->layout); assert(polygon.size() > 5); - Sint16 vx[6]; - Sint16 vy[6]; - for (uint8_t i = 0; i < 6; i++) + Sint16 x[6]; + Sint16 y[6]; + for (const Field &elem : *(this->fields)) { - vx[i] = (Sint16) (polygon[i].x - center.x); - vy[i] = (Sint16) (polygon[i].y - center.y); - } - for (const Field &elem : this->fields) - { - center = field_to_point(elem, this->layout); - Sint16 x[6]; - Sint16 y[6]; + Point center = field_to_point(elem, this->layout); for (uint8_t i = 0; i < 6; i++) { - x[i] = vx[i] + (Sint16) center.x; - y[i] = vy[i] + (Sint16) center.y; + x[i] = (Sint16) (center.x + polygon[i].x); + y[i] = (Sint16) (center.y + polygon[i].y); } - polygonRGBA(renderer, x, y, 6, 0xff, 0xff, 0xff, 0xff); + const SDL_Color color = {0xff, 0xff, 0xff, 0xff}; + polygonRGBA(renderer, x, y, 6, color.r, color.g, color.b, color.a); if (elem == this->marker) { - filledPolygonRGBA(renderer, x, y, 6, 0xff, 0x0, 0x0, 0xff); + filledPolygonRGBA(renderer, x, y, 6, 0x77, 0x77, 0x77, 0x77); } } return true; } -void Grid::move(SDL_Point move) -{ - this->set_origin(this->layout.origin + move); -} - void Grid::handle_event(SDL_Event *event) { - if (event->type == SDL_MOUSEWHEEL) { SDL_Point mouse = {0, 0}; SDL_GetMouseState(&mouse.x, &mouse.y); - int scroll = event->wheel.y; - Uint16 old_size = this->layout.size; - SDL_Point old_origin = this->layout.origin; - + int scroll = this->layout->size / 10 * event->wheel.y; + double old_size = this->layout->size; + SDL_Point old_origin = this->layout->origin; if (old_size + scroll < 10) { - this->layout.size = 10; + this->layout->size = 10; } else if (old_size + scroll > 100) { - this->layout.size = 100; + this->layout->size = 100; } else { - this->layout.size += scroll; - this->set_origin(old_origin + (10 * scroll * (old_origin - mouse) / !(old_origin - mouse))); + this->layout->size += scroll; + } + this->move(((1.0 - (double) this->layout->size / old_size) * (mouse - old_origin))); } if (event->type == SDL_MOUSEMOTION) { @@ -277,18 +275,44 @@ void Grid::handle_event(SDL_Event *event) } } -void Grid::set_origin(SDL_Point dm) +void Grid::move(SDL_Point m) { - this->layout.origin = dm; + this->layout->origin = this->layout->origin + m; + // check if some part is inside layout->box + if (!on_rectangle(&layout->box)) + this->layout->origin = this->layout->origin - m; this->update_marker(); } void Grid::update_marker() { - SDL_Point m; + SDL_Point m = {0, 0}; SDL_GetMouseState(&(m.x), &(m.y)); Point p = {0.0, 0.0}; p.x = m.x; p.y = m.y; this->marker = point_to_field(p, this->layout); } + +bool Grid::on_rectangle(SDL_Rect *rect) +{ + // check if center inside rect for ANY field + for (const Field &f : *(this->fields)) + { + Point precise_p = field_to_point(f, layout); + SDL_Point p; + p.x = (int) precise_p.x; + p.y = (int) precise_p.y; + if (p.x > rect->x && p.y > rect->y && p.x < (rect->x + rect->w) && p.y < (rect->y + rect->h)) + { + return true; + } + } + return false; +} + +void Grid::update_box(int x, int y) +{ + this->layout->box.w = x; + this->layout->box.h = y; +} \ No newline at end of file diff --git a/src/GameMap.hpp b/src/Grid.hpp similarity index 77% rename from src/GameMap.hpp rename to src/Grid.hpp index 9050b6a..2582ef7 100644 --- a/src/GameMap.hpp +++ b/src/Grid.hpp @@ -6,9 +6,9 @@ #include #include #include -#include -#include "Player.hpp" +#ifndef POINT_OPERATORS +#define POINT_OPERATORS SDL_Point operator+(SDL_Point left, SDL_Point right); SDL_Point operator-(SDL_Point left, SDL_Point right); @@ -19,16 +19,17 @@ SDL_Point operator/(SDL_Point left, SDL_Point right); SDL_Point operator/(SDL_Point left, SDL_Point right); -SDL_Point operator*(int left, SDL_Point right); +SDL_Point operator*(double left, SDL_Point right); -SDL_Point operator*(SDL_Point left, int right); +SDL_Point operator*(SDL_Point left, double right); -SDL_Point operator/(SDL_Point left, int right); +SDL_Point operator/(SDL_Point left, double right); -int operator!(SDL_Point left); +double operator!(SDL_Point left); + +#endif #ifndef Point - struct Point { double x; @@ -38,6 +39,8 @@ struct Point { } }; +#endif + Point operator+(Point left, Point right); Point operator-(Point left, Point right); @@ -56,10 +59,7 @@ Point operator/(Point left, double right); double operator!(Point left); -#endif - #ifndef Orientation - struct Orientation { // cubic to point @@ -91,16 +91,16 @@ struct Layout const Orientation orientation; Uint16 size; SDL_Point origin; + SDL_Rect box; - Layout(Orientation orientation_, Uint16 size_, SDL_Point origin_) - : orientation(orientation_), size(size_), origin(origin_) + Layout(Orientation orientation_, Uint16 size_, SDL_Point origin_, SDL_Rect box_) + : orientation(orientation_), size(size_), origin(origin_), box(box_) { } }; #endif #ifndef Field - struct Field { Sint16 x, y, z; @@ -116,6 +116,8 @@ 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) }; +Field hex_direction(Uint8 direction); + namespace std { template<> @@ -133,6 +135,8 @@ namespace std }; } +Field hex_neighbor(Uint8 direction, Field f); + Field cubic_round(double x, double y, double z); int cubic_distance(Field a, Field b); @@ -148,57 +152,42 @@ Field operator-(Field left, Field right); Field operator*(Field left, Field right); Field operator/(Field left, Field right); - #endif -Point field_to_point(const Field f, const Layout layout); +Point field_to_point(const Field f, const Layout *layout); -Field point_to_field(Point point, const Layout layout); +Field point_to_field(Point point, const Layout *layout); -Point field_corner_offset(int corner, const Layout layout); +Point field_corner_offset(Uint8 corner, const Layout *layout); -std::vector field_to_polygon(const Field field, const Layout layout); +std::vector field_to_polygon_normalized(const Field field, const Layout *layout); -#ifndef FieldMeta +std::vector field_to_polygon(const Field field, const Layout *layout); -class FieldMeta -{ -private: - Player *owner; -public: - FieldMeta(Player *owner_) : owner(owner_) - { } -// Player *get_owner(); -// bool set_owner(Player *owner); -}; - -#endif #ifndef Grid class Grid { protected: - std::unordered_set fields; - std::unordered_map fields_meta; - Layout layout; + std::unordered_set *fields; + Layout *layout; Field marker; + + bool on_rectangle(SDL_Rect *rect); public: - Grid(Layout layout_) : layout(layout_), marker(0, 0, 0) + Grid(Layout *layout_) + : layout(layout_), marker(0, 0, 0) { - this->fields = std::unordered_set(); - this->fields_meta = std::unordered_map(); + this->fields = new std::unordered_set(); }; ~Grid() { - for (const Field &elem : this->fields) - { - delete this->fields_meta.at(elem); - } + delete this->fields; } - void set_origin(SDL_Point origin); + std::unordered_set *get_fields() { return this->fields; } void move(SDL_Point move); @@ -208,20 +197,22 @@ public: void handle_event(SDL_Event *event); + void update_box(int x, int y); }; #endif #ifndef HexagonGrid - class HexagonGrid : public Grid { private: Sint16 radius; public: - HexagonGrid(Sint16 grid_radius, Layout layout); + HexagonGrid(Sint16 grid_radius, Layout *layout); bool render(SDL_Renderer *renderer); + + Sint16 get_radius() { return radius * layout->size; } }; #endif diff --git a/src/Main.cpp b/src/Main.cpp index 74eaccc..0e14d5b 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,5 +1,3 @@ -#include -#include #include "Main.hpp" @@ -11,7 +9,7 @@ void logSDLError(std::ostream &os, const std::string &msg) SDL_Window *init_window() { - SDL_Window *window = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + SDL_Window *window = SDL_CreateWindow(TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGTH, SDL_WINDOW_OPENGL); if (window == NULL) { @@ -60,6 +58,7 @@ void Game::toggle_fullscreen() this->full_screen = true; SDL_SetWindowSize(this->window, dm.w, dm.h); SDL_SetWindowFullscreen(this->window, SDL_WINDOW_FULLSCREEN); + this->grid->update_box(dm.w, dm.h); } else { @@ -67,6 +66,7 @@ void Game::toggle_fullscreen() SDL_SetWindowFullscreen(this->window, 0); SDL_SetWindowSize(this->window, SCREEN_WIDTH, SCREEN_HEIGTH); SDL_SetWindowPosition(this->window, dm.w / 4, dm.h / 4); + this->grid->update_box(SCREEN_WIDTH, SCREEN_HEIGTH); } } @@ -104,21 +104,45 @@ void Game::handle_event(SDL_Event *event) if (key == SDLK_d) this->move[3] = false; } + if (event->type == SDL_WINDOWEVENT) + { + if (event->window.windowID == SDL_GetWindowID(this->window)) + { + switch (event->window.event) + { + case SDL_WINDOWEVENT_SIZE_CHANGED: + { + this->grid->update_box(event->window.data1, event->window.data2); + break; + } + default: + break; + } + } + } } int Game::game_loop() { Timer *frame_timer = new Timer(); frame_timer->start_timer(); + Timer *move_timer = new Timer(); + move_timer->start_timer(); double fps; Uint32 frame_counter = 0; while (!this->quit) { + if (move_timer->get_timer() > 10) + { + move_timer->reset_timer(); + SDL_Point move_by = {(this->move[1] - this->move[3]) * 10, (this->move[0] - this->move[2]) * 10}; + this->grid->move(move_by); + } if (frame_timer->get_timer() > 1000.0) { fps = frame_counter / (frame_timer->reset_timer() / 1000.0); frame_counter = 0; - std::cout << fps << std::endl; + std::cout << fps << " fps" << std::endl; } SDL_Event event; while (SDL_PollEvent(&event)) @@ -130,26 +154,35 @@ int Game::game_loop() if (event.type == SDL_QUIT) { quit = true; - break; } if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL) { grid->handle_event(&event); } } - SDL_Point move_by = {(this->move[1] - this->move[3]) * 10, (this->move[0] - this->move[2]) * 10}; - this->grid->move(move_by); SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); + SDL_RenderClear(renderer); SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff); - this->grid->render(renderer); + this->render(renderer); SDL_RenderPresent(renderer); frame_counter++; } + SDL_RenderClear(renderer); + delete move_timer; delete frame_timer; return 0; } +void Game::render(SDL_Renderer *renderer) +{ + this->grid->render(renderer); + for (FieldMeta *meta : this->fields_meta) + { + meta->render(renderer, this->layout); + } +} + int main(int, char **) { if (SDL_Init(SDL_INIT_VIDEO) != 0) @@ -172,12 +205,21 @@ int main(int, char **) SDL_Quit(); return -1; } - Game *game = new Game(window, renderer); + Layout *layout = new Layout(pointy_orientation, GRID_SIZE, {5 * SCREEN_WIDTH / 12, 5 * SCREEN_HEIGTH / 12}, + {0, 0, 5 * SCREEN_WIDTH / 6, 5 * SCREEN_HEIGTH / 6}); + Game *game = new Game(window, renderer, layout); int exit_status = game->game_loop(); delete game; + delete layout; SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return exit_status; } +bool position_in_window(SDL_Point position, SDL_Window *window) +{ + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(window), &dm); + return position.x > 0 && position.x < dm.w && position.y > 0 && position.y < dm.h; +} diff --git a/src/Main.hpp b/src/Main.hpp index 36ba32b..bd3f696 100644 --- a/src/Main.hpp +++ b/src/Main.hpp @@ -1,12 +1,16 @@ #include +#include #include #include -#include "GameMap.hpp" +#include +#include "Gameplay.hpp" +#include #ifndef DEFAULTS -const Sint16 GRID_SIZE = 20; +const Sint16 GRID_SIZE = 4; const int SCREEN_WIDTH = 800; const int SCREEN_HEIGTH = 600; +char TITLE[] = "Bob - Battles of Bacteria"; #endif #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -44,31 +48,49 @@ private: SDL_Window *window; SDL_Renderer *renderer; HexagonGrid *grid; + // only deal with meta information + std::unordered_set fields_meta; + Layout *layout; bool move[4]; bool full_screen; bool quit; + public: - Game(SDL_Window *window_, SDL_Renderer *renderer_) - : window(window_), renderer(renderer_) + Game(SDL_Window *window_, SDL_Renderer *renderer_, Layout *layout_) + : window(window_), renderer(renderer_), layout(layout_) { - Layout layout = {pointy_orientation, GRID_SIZE, {SCREEN_WIDTH / 2, SCREEN_HEIGTH / 2}}; this->grid = new HexagonGrid(GRID_SIZE, layout); for (int i = 0; i < 4; i++) { this->move[i] = false; } this->quit = false; + // create meta information for every field on the grid + for (const Field &elem : *(grid->get_fields())) + { + FieldMeta *meta = new FieldMeta(elem); + fields_meta.insert(meta); + } } - void toggle_fullscreen(); - ~Game() { + for (const FieldMeta *elem : this->fields_meta) + { + delete elem; + } delete this->grid; } + void render(SDL_Renderer *renderer); + + void toggle_fullscreen(); + void handle_event(SDL_Event *event); + int game_loop(); }; #endif + +bool position_in_window(SDL_Point position, SDL_Window *window); diff --git a/src/Player.cpp b/src/Player.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/Player.hpp b/src/Player.hpp deleted file mode 100644 index 7f2ba8e..0000000 --- a/src/Player.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef Player - -struct Player -{ - const SDL_Color color; - const std::string name; -}; - -#endif \ No newline at end of file diff --git a/src/Upgrades.cpp b/src/Upgrades.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/Upgrades.hpp b/src/Upgrades.hpp deleted file mode 100644 index 6f7d0ef..0000000 --- a/src/Upgrades.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#include - -#ifndef Upgrade - -class Upgrade -{ - SDL_Color color; -public: - static Upgrade *Instance(); - -private: - Upgrade() - { }; - - Upgrade(Upgrade const &) - { }; - - Upgrade &operator=(Upgrade const &) - { }; - static Upgrade *m_pInstance; -}; - -#endif \ No newline at end of file