Added resource generation and resource display. Should commit more often...
This commit is contained in:
parent
189e840f25
commit
0d523b6541
11 changed files with 605 additions and 162 deletions
318
src/Grid.cpp
Normal file
318
src/Grid.cpp
Normal file
|
@ -0,0 +1,318 @@
|
|||
#include "Grid.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*(double left, SDL_Point right)
|
||||
{
|
||||
int x = (int) (left * right.x);
|
||||
int y = (int) (left * right.y);
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
SDL_Point operator*(SDL_Point left, double right)
|
||||
{
|
||||
return right * left;
|
||||
}
|
||||
|
||||
SDL_Point operator/(SDL_Point left, double right)
|
||||
{
|
||||
return (1 / right) * left;
|
||||
}
|
||||
|
||||
double operator!(SDL_Point left)
|
||||
{
|
||||
double length = 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;
|
||||
}
|
||||
|
||||
bool operator!=(Field left, Field right)
|
||||
{
|
||||
return left == right;
|
||||
}
|
||||
|
||||
Field operator+(Field left, Field right)
|
||||
{
|
||||
return Field(left.x + right.x, left.y + right.y, left.z + right.z);
|
||||
}
|
||||
|
||||
Field operator-(Field left, Field right)
|
||||
{
|
||||
return Field(left.x - right.x, left.y - right.y, left.z - right.z);
|
||||
}
|
||||
|
||||
Field operator*(Field left, Field right)
|
||||
{
|
||||
return Field(left.x * right.x, left.y * right.y, left.z * right.z);
|
||||
}
|
||||
|
||||
Field operator/(Field left, Field right)
|
||||
{
|
||||
return cubic_round(left.x / right.x, left.y / right.y, right.z / left.z);
|
||||
}
|
||||
|
||||
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 x_err = std::abs(round_x - x);
|
||||
double y_err = std::abs(round_y - y);
|
||||
double z_err = std::abs(round_z - z);
|
||||
if (x_err > y_err && x_err > z_err)
|
||||
{
|
||||
round_x = -round_y - round_z;
|
||||
} else if (y_err > z_err)
|
||||
{
|
||||
round_y = -round_x - round_z;
|
||||
} else
|
||||
{
|
||||
round_z = -round_x - round_y;
|
||||
}
|
||||
return Field(round_x, round_y, round_z);
|
||||
}
|
||||
|
||||
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(Uint8 direction)
|
||||
{
|
||||
assert (0 <= direction && direction <= 5);
|
||||
return hex_directions[direction];
|
||||
}
|
||||
|
||||
Field hex_neighbor(Uint8 direction, Field f)
|
||||
{
|
||||
return hex_direction(direction) + f;
|
||||
}
|
||||
|
||||
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 {x + layout->origin.x, y + layout->origin.y};
|
||||
}
|
||||
|
||||
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;
|
||||
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 corner, const Layout *layout)
|
||||
{
|
||||
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<Point> field_to_polygon(const Field field, const Layout *layout)
|
||||
{
|
||||
std::vector<Point> corners = field_to_polygon_normalized(field, layout);
|
||||
Point center = field_to_point(field, layout);
|
||||
for (Point &p : corners)
|
||||
{
|
||||
p = p + center;
|
||||
}
|
||||
return corners;
|
||||
}
|
||||
|
||||
std::vector<Point> field_to_polygon_normalized(const Field field, const Layout *layout)
|
||||
{
|
||||
std::vector<Point> 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++)
|
||||
{
|
||||
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};
|
||||
this->fields->insert(new_field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HexagonGrid::render(SDL_Renderer *renderer)
|
||||
{
|
||||
Field some_field = {0, 0, 0};
|
||||
std::vector<Point> polygon = field_to_polygon_normalized(some_field, this->layout);
|
||||
assert(polygon.size() > 5);
|
||||
Sint16 x[6];
|
||||
Sint16 y[6];
|
||||
for (const Field &elem : *(this->fields))
|
||||
{
|
||||
Point center = field_to_point(elem, this->layout);
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
{
|
||||
x[i] = (Sint16) (center.x + polygon[i].x);
|
||||
y[i] = (Sint16) (center.y + polygon[i].y);
|
||||
}
|
||||
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, 0x77, 0x77, 0x77, 0x77);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
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 (event->type == SDL_MOUSEMOTION)
|
||||
{
|
||||
this->update_marker();
|
||||
}
|
||||
}
|
||||
|
||||
void Grid::move(SDL_Point m)
|
||||
{
|
||||
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 = {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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue