diff --git a/src/GameMap.cpp b/src/GameMap.cpp index d080d9b..5de97fa 100644 --- a/src/GameMap.cpp +++ b/src/GameMap.cpp @@ -1,5 +1,91 @@ #include "GameMap.hpp" +SDL_Point operator+(SDL_Point left, SDL_Point right) +{ + return {left.x + right.x, left.y + right.y}; +} + +SDL_Point operator-(SDL_Point left, SDL_Point right) +{ + return {left.x - right.x, left.y - right.y}; +} + +SDL_Point operator*(SDL_Point left, SDL_Point right) +{ + return {left.x * right.x, left.y * right.y}; +} + +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) +{ + return {left * right.x, left * right.y}; +} + +SDL_Point operator*(SDL_Point left, int right) +{ + return right * left; +} + +SDL_Point operator/(SDL_Point left, int right) +{ + return {left.x / right, left.y / right}; +} + +int operator!(SDL_Point left) +{ + int length = (int) std::sqrt(left.x * left.x + left.y * left.y); + return length; +} + +Point operator+(Point left, Point right) +{ + return Point(left.x + right.x, left.y + right.y); +} + +Point operator-(Point left, Point right) +{ + return Point(left.x - right.x, left.y - right.y); +} + +Point operator*(Point left, Point right) +{ + return Point(left.x * right.x, left.y * right.y); +} + +Point operator/(Point left, Point right) +{ + return Point(left.x / right.x, left.y / right.y); +} + +Point operator*(double left, Point right) +{ + return Point(left * right.x, left * right.y); +} + +Point operator*(Point left, double right) +{ + return Point(left.x * right, left.y * right); +} + +Point operator/(double left, Point right) +{ + return Point(left * right.x, left * right.y); +} + +Point operator/(Point left, double right) +{ + return Point(left.x * right, left.y * right); +} + +double operator!(Point left) +{ + return std::sqrt(left.x * left.x + left.y * left.y); +} + bool operator==(Field left, Field right) { return left.x == right.x && left.y == right.y; @@ -32,9 +118,9 @@ Field operator/(Field left, Field right) Field cubic_round(double x, double y, double z) { - int8_t round_x = (int8_t) std::round(x); - int8_t round_y = (int8_t) std::round(y); - int8_t round_z = (int8_t) std::round(z); + Sint8 round_x = (Sint8) std::round(x); + Sint8 round_y = (Sint8) std::round(y); + Sint8 round_z = (Sint8) 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); @@ -103,8 +189,8 @@ std::vector field_to_polygon(const Field field, const Layout layout) return corners; } -HexagonGrid::HexagonGrid(Sint16 grid_radius, Layout layout, SDL_Color color) - : Grid(layout, color) +HexagonGrid::HexagonGrid(Sint16 grid_radius, Layout layout) + : Grid(layout) { // first lower half, then upper half for (Sint16 x = -grid_radius; x <= grid_radius; x++) @@ -114,27 +200,95 @@ HexagonGrid::HexagonGrid(Sint16 grid_radius, Layout layout, SDL_Color color) for (Sint16 y = y_l; y <= y_u; y++) { Sint16 z = -x - y; - this->fields.insert({x, y, z}); + 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); } } } 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); + assert(polygon.size() > 5); + Sint16 vx[6]; + Sint16 vy[6]; + for (uint8_t i = 0; i < 6; i++) + { + vx[i] = (Sint16) (polygon[i].x - center.x); + vy[i] = (Sint16) (polygon[i].y - center.y); + } for (const Field &elem : this->fields) { - std::vector polygon = field_to_polygon(elem, this->layout); - assert(polygon.size() > 5); - Sint16 vx[6]; - Sint16 vy[6]; + center = field_to_point(elem, this->layout); + Sint16 x[6]; + Sint16 y[6]; for (uint8_t i = 0; i < 6; i++) { - vx[i] = (Sint16) polygon[i].x; - vy[i] = (Sint16) polygon[i].y; + x[i] = vx[i] + (Sint16) center.x; + y[i] = vy[i] + (Sint16) center.y; + } + polygonRGBA(renderer, x, y, 6, 0xff, 0xff, 0xff, 0xff); + if (elem == this->marker) + { + filledPolygonRGBA(renderer, x, y, 6, 0xff, 0x0, 0x0, 0xff); } - const Sint16 x[6] = {vx[0], vx[1], vx[2], vx[3], vx[4], vx[5]}; - const Sint16 y[6] = {vy[0], vy[1], vy[2], vy[3], vy[4], vy[5]}; - aapolygonRGBA(renderer, x, y, 6, this->color.r, this->color.g, this->color.b, this->color.a); } 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; + + 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->set_origin(old_origin + (10 * scroll * (old_origin - mouse) / !(old_origin - mouse))); + } + } + if (event->type == SDL_MOUSEMOTION) + { + this->update_marker(); + } +} + +void Grid::set_origin(SDL_Point dm) +{ + this->layout.origin = dm; + this->update_marker(); +} + +void Grid::update_marker() +{ + SDL_Point m; + 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); +} diff --git a/src/GameMap.hpp b/src/GameMap.hpp index 06bd369..9050b6a 100644 --- a/src/GameMap.hpp +++ b/src/GameMap.hpp @@ -1,11 +1,32 @@ +#include +#include #include #include #include #include #include #include +#include #include "Player.hpp" +SDL_Point operator+(SDL_Point left, SDL_Point right); + +SDL_Point operator-(SDL_Point left, SDL_Point right); + +SDL_Point operator*(SDL_Point left, SDL_Point right); + +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*(SDL_Point left, int right); + +SDL_Point operator/(SDL_Point left, int right); + +int operator!(SDL_Point left); + #ifndef Point struct Point @@ -17,6 +38,24 @@ struct Point { } }; +Point operator+(Point left, Point right); + +Point operator-(Point left, Point right); + +Point operator*(Point left, Point right); + +Point operator/(Point left, Point right); + +Point operator*(double left, Point right); + +Point operator*(Point left, double right); + +Point operator/(double left, Point right); + +Point operator/(Point left, double right); + +double operator!(Point left); + #endif #ifndef Orientation @@ -50,10 +89,10 @@ const Orientation flat_orientation = Orientation(3.0 / 2.0, 0.0, sqrt(3.0) / 2.0 struct Layout { const Orientation orientation; - const double size; - const SDL_Point origin; + Uint16 size; + SDL_Point origin; - Layout(Orientation orientation_, double size_, SDL_Point origin_) + Layout(Orientation orientation_, Uint16 size_, SDL_Point origin_) : orientation(orientation_), size(size_), origin(origin_) { } }; @@ -64,7 +103,7 @@ struct Layout struct Field { - const Sint16 x, y, z; + Sint16 x, y, z; Field(Sint16 x_, Sint16 y_, Sint16 z_) : x(x_), y(y_), z(z_) { @@ -116,25 +155,59 @@ Point field_to_point(const Field f, const Layout layout); Field point_to_field(Point point, const Layout layout); -Point field_corner_offset(Uint8 corner, const Layout layout); +Point field_corner_offset(int corner, const Layout layout); std::vector field_to_polygon(const Field field, const Layout layout); +#ifndef FieldMeta + +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; - SDL_Color color; + std::unordered_map fields_meta; Layout layout; + Field marker; public: - Grid(Layout layout_, SDL_Color color_) : layout(layout_), color(color_) + Grid(Layout layout_) : layout(layout_), marker(0, 0, 0) { this->fields = std::unordered_set(); + this->fields_meta = std::unordered_map(); }; + ~Grid() + { + for (const Field &elem : this->fields) + { + delete this->fields_meta.at(elem); + } + } + + void set_origin(SDL_Point origin); + + void move(SDL_Point move); + + void update_marker(); + virtual bool render(SDL_Renderer *renderer) = 0; + + void handle_event(SDL_Event *event); + }; #endif @@ -143,8 +216,10 @@ public: class HexagonGrid : public Grid { +private: + Sint16 radius; public: - HexagonGrid(Sint16 grid_radius, Layout layout, SDL_Color color); + HexagonGrid(Sint16 grid_radius, Layout layout); bool render(SDL_Renderer *renderer); }; diff --git a/src/Main.cpp b/src/Main.cpp index 2934d8d..74eaccc 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,4 +1,5 @@ #include +#include #include "Main.hpp" @@ -9,9 +10,9 @@ 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, - SCREEN_WIDTH, - SCREEN_HEIGHT, SDL_WINDOW_OPENGL); + SCREEN_WIDTH, SCREEN_HEIGTH, SDL_WINDOW_OPENGL); if (window == NULL) { logSDLError(std::cout, "SDL_CreateWindow"); @@ -32,50 +33,120 @@ SDL_Renderer *init_renderer(SDL_Window *window) return renderer; } -SDL_Surface *init_surface(int width, int height) +void Timer::start_timer() { - - //SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); - SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0); - if (surface == NULL) - { - logSDLError(std::cout, "SDL_CreateSurface"); - } - return surface; + this->timer_started = SDL_GetTicks(); } -SDL_Texture *init_texture(SDL_Renderer *renderer, SDL_Surface *surface) +Uint32 Timer::get_timer() { - SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); - if (texture == NULL) + Uint32 ticks_passed = SDL_GetTicks() - this->timer_started; + return ticks_passed; +} + +Uint32 Timer::reset_timer() +{ + Uint32 ticks_passed = this->get_timer(); + this->timer_started = SDL_GetTicks(); + return ticks_passed; +} + +void Game::toggle_fullscreen() +{ + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(this->window), &dm); + if (!this->full_screen) { - logSDLError(std::cout, "SDL_CreateTexture"); + this->full_screen = true; + SDL_SetWindowSize(this->window, dm.w, dm.h); + SDL_SetWindowFullscreen(this->window, SDL_WINDOW_FULLSCREEN); + } + else + { + this->full_screen = false; + SDL_SetWindowFullscreen(this->window, 0); + SDL_SetWindowSize(this->window, SCREEN_WIDTH, SCREEN_HEIGTH); + SDL_SetWindowPosition(this->window, dm.w / 4, dm.h / 4); + } +} + +void Game::handle_event(SDL_Event *event) +{ + if (event->type == SDL_KEYDOWN) + { + SDL_Keycode key = event->key.keysym.sym; + if (key == SDLK_w) + this->move[0] = true; + if (key == SDLK_a) + this->move[1] = true; + if (key == SDLK_s) + this->move[2] = true; + if (key == SDLK_d) + this->move[3] = true; + if (key == SDLK_f) + { + toggle_fullscreen(); + } + if (key == SDLK_ESCAPE) + { + this->quit = true; + } + } + if (event->type == SDL_KEYUP) + { + SDL_Keycode key = event->key.keysym.sym; + if (key == SDLK_w) + this->move[0] = false; + if (key == SDLK_a) + this->move[1] = false; + if (key == SDLK_s) + this->move[2] = false; + if (key == SDLK_d) + this->move[3] = false; } - return texture; } int Game::game_loop() { - bool quit = false; - while (!quit) + Timer *frame_timer = new Timer(); + frame_timer->start_timer(); + double fps; + Uint32 frame_counter = 0; + while (!this->quit) { + if (frame_timer->get_timer() > 1000.0) + { + fps = frame_counter / (frame_timer->reset_timer() / 1000.0); + frame_counter = 0; + std::cout << fps << std::endl; + } SDL_Event event; while (SDL_PollEvent(&event)) { + if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) + { + this->handle_event(&event); + } if (event.type == SDL_QUIT) { quit = true; - } else if (event.type == SDL_MOUSEBUTTONDOWN) + break; + } + if (event.type == SDL_MOUSEMOTION || event.type == SDL_MOUSEWHEEL) { - quit = true; + 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); SDL_RenderPresent(renderer); + frame_counter++; } + delete frame_timer; return 0; } @@ -104,6 +175,9 @@ int main(int, char **) Game *game = new Game(window, renderer); int exit_status = game->game_loop(); delete game; + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); return exit_status; } diff --git a/src/Main.hpp b/src/Main.hpp index 2dfae4a..36ba32b 100644 --- a/src/Main.hpp +++ b/src/Main.hpp @@ -4,12 +4,9 @@ #include "GameMap.hpp" #ifndef DEFAULTS +const Sint16 GRID_SIZE = 20; const int SCREEN_WIDTH = 800; -const int SCREEN_HEIGHT = 800; -const SDL_Point CENTER = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2}; -const Layout LAYOUT = Layout(pointy_orientation, 20.0, CENTER); -const Sint16 GRID_SIZE = 6; -const SDL_Color COLOR = {0, 255, 255, 255}; +const int SCREEN_HEIGTH = 600; #endif #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -24,25 +21,54 @@ Uint32 bmask = 0x00ff0000; Uint32 amask = 0xff000000; #endif +#ifndef Timer -//template +class Timer +{ +private: + Uint32 timer_started; +public: + void start_timer(); + + Uint32 get_timer(); + + Uint32 reset_timer(); +}; + +#endif + +#ifndef Game class Game { private: SDL_Window *window; SDL_Renderer *renderer; HexagonGrid *grid; + bool move[4]; + bool full_screen; + bool quit; public: Game(SDL_Window *window_, SDL_Renderer *renderer_) : window(window_), renderer(renderer_) { - this->grid = new HexagonGrid(GRID_SIZE, LAYOUT, COLOR); + 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; } + void toggle_fullscreen(); + ~Game() { delete this->grid; } + void handle_event(SDL_Event *event); int game_loop(); }; + +#endif diff --git a/src/Player.hpp b/src/Player.hpp index e69de29..7f2ba8e 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -0,0 +1,9 @@ +#ifndef Player + +struct Player +{ + const SDL_Color color; + const std::string name; +}; + +#endif \ No newline at end of file