Added game map drawing.

This commit is contained in:
Tim Schubert 2016-01-11 23:56:50 +01:00
commit 692e9de011
16 changed files with 860 additions and 0 deletions

3
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,3 @@
add_executable(Bob Main.cpp)
add_library(GameMap GameMap.cpp)
target_link_libraries(Bob GameMap ${SDL2_LIBRARY} ${SDL2GFX_LIBRARY} ${Boost_LIBRARIES})

0
src/Field.cpp Normal file
View file

123
src/GameMap.cpp Normal file
View file

@ -0,0 +1,123 @@
#include "GameMap.hpp"
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) {
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);
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(int direction) {
assert (0 <= direction && direction <= 5);
return hex_directions[direction];
}
Field hex_neighbor(int8_t 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 Point(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_t 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));
//uint8_t i = (uint8_t) ((corner + layout->orientation.start_corner) % 6);
//return Point(layout->size * COS_ANGLES_HEX[i], layout->size * SIN_ANGLES_HEX[i]);
}
std::vector<Point> field_to_polygon(const Field *field, const Layout *layout) {
std::vector<Point> corners = {};
Point center = field_to_point(field, layout);
for (uint8_t i = 0; i < 6; i++) {
Point offset = field_corner_offset(i, layout);
corners.push_back(Point(center.x + offset.x, center.y + offset.y));
}
return corners;
}
Grid::Grid() {
this->fields = std::unordered_set<Field>();
}
HexagonGrid::HexagonGrid(Sint16 grid_radius)
: Grid() {
// 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;
this->fields.insert({x, y, z});
}
}
}
bool HexagonGrid::render(SDL_Renderer *renderer, const SDL_Color color, const Layout *layout) {
for (const Field &elem : this->fields) {
std::vector<Point> polygon = field_to_polygon(&elem, 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;
vy[i] = (Sint16) polygon[i].y;
}
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, color.r, color.g, color.b, color.a);
}
return true;
}

133
src/GameMap.hpp Normal file
View file

@ -0,0 +1,133 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <cmath>
#include <vector>
#include <assert.h>
#include <unordered_set>
#include "Player.hpp"
#ifndef Point
struct Point {
double x;
double y;
Point(double x_, double y_) : x(x_), y(y_) { }
};
#endif
#ifndef Orientation
struct Orientation {
// cubic to point
const double f0, f1, f2, f3;
// point to cubic
const double b0, b1, b2, b3;
// in multiples of 60 deg
const double start_angle;
Orientation(double f0_, double f1_, double f2_, double f3_, double b0_, double b1_, double b2_, double b3_,
double start_angle_)
: f0(f0_), f1(f1_), f2(f2_), f3(f3_), b0(b0_), b1(b1_), b2(b2_), b3(b3_),
start_angle(start_angle_) { }
};
const Orientation pointy_orientation = Orientation(sqrt(3.0), sqrt(3.0) / 2.0, 0.0, 3.0 / 2.0,
sqrt(3.0) / 3.0, -1.0 / 3.0, 0.0, 2.0 / 3.0,
0.5);
const Orientation flat_orientation = Orientation(3.0 / 2.0, 0.0, sqrt(3.0) / 2.0, sqrt(3.0),
2.0 / 3.0, 0.0, -1.0 / 3.0, sqrt(3.0) / 3.0,
0);
#endif
#ifndef Layout
struct Layout {
const Orientation orientation;
const double size;
const SDL_Point origin;
Layout(Orientation orientation_, double size_, SDL_Point origin_)
: orientation(orientation_), size(size_), origin(origin_) { }
};
#endif
#ifndef Field
struct Field {
const Sint16 x, y, z;
Field(Sint16 x_, Sint16 y_, Sint16 z_) : x(x_), y(y_), z(z_) {
assert(x + y + z == 0);
}
};
// 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)
};
namespace std {
template<>
struct hash<Field> {
size_t operator()(const Field &f) const {
hash<Sint16> int_hash;
size_t hx = int_hash(f.x);
size_t hy = int_hash(f.y);
// hz would be redundant, since f.z is redundant
// combine hashes
return hx ^ (hy + 0x9e3779b9 + (hx << 6) + (hx >> 2));
}
};
}
Field cubic_round(double x, double y, double z);
int cubic_distance(Field a, Field b);
bool operator==(Field left, Field right);
bool operator!=(Field left, Field right);
Field operator+(Field left, Field right);
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);
Field point_to_field(Point point, const Layout *layout);
Point field_corner_offset(Uint8 corner, const Layout *layout);
std::vector<Point> field_to_polygon(const Field *field, const Layout *layout);
#ifndef Grid
class Grid {
protected:
std::unordered_set<Field> fields;
public:
Grid();
};
#endif
#ifndef HexagonGrid
class HexagonGrid : public Grid {
public:
HexagonGrid(Sint16 grid_radius);
bool render(SDL_Renderer *renderer, const SDL_Color color, const Layout *layout);
};
#endif

104
src/Main.cpp Normal file
View file

@ -0,0 +1,104 @@
#include <string>
#include "Main.hpp"
void logSDLError(std::ostream &os, const std::string &msg) {
os << msg << " error:" << SDL_GetError() << std::endl;
}
SDL_Window *init_window() {
SDL_Window *window = SDL_CreateWindow("Hello World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT, SDL_WINDOW_OPENGL);
if (window == NULL) {
logSDLError(std::cout, "SDL_CreateWindow");
SDL_DestroyWindow(window);
SDL_Quit();
}
return window;
}
SDL_Renderer *init_renderer(SDL_Window *window) {
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
logSDLError(std::cout, "SDL_CreateRenderer");
}
return renderer;
}
SDL_Surface *init_surface(int width, int height) {
//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;
}
SDL_Texture *init_texture(SDL_Renderer *renderer, SDL_Surface *surface) {
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
if (texture == NULL) {
logSDLError(std::cout, "SDL_CreateTexture");
}
return texture;
}
int main(int, char **) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
logSDLError(std::cout, "SDL_init");
return 1;
}
SDL_Window *window = init_window();
if (!window) {
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_Renderer *renderer = init_renderer(window);
if (!renderer) {
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_Surface *surface = init_surface(SCREEN_WIDTH, SCREEN_HEIGHT);
if (!surface) {
SDL_FreeSurface(surface);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_Texture *texture = init_texture(renderer, surface);
if (!texture) {
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
const SDL_Point center = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
const Layout standard = Layout(pointy_orientation, 20.0, center);
const SDL_Color color = {0, 255, 255, 255};
HexagonGrid *grid = new HexagonGrid(4);
bool quit = false;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
} else if (event.type == SDL_MOUSEBUTTONDOWN) {
quit = true;
}
}
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff);
grid->render(renderer, color, &standard);
SDL_RenderPresent(renderer);
}
delete grid;
return 0;
}

27
src/Main.hpp Normal file
View file

@ -0,0 +1,27 @@
#include <iostream>
#include <utility>
#include <SDL2/SDL.h>
#include "GameMap.hpp"
#ifndef DATA_PATH
#endif
#ifndef SCREEN_WIDTH
const int SCREEN_WIDTH = 800;
#endif
#ifndef SCREEN_HEIGHT
const int SCREEN_HEIGHT = 800;
#endif
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 rmask = 0xff000000;
Uint32 gmask = 0x00ff0000;
Uint32 bmask = 0x0000ff00;
Uint32 amask = 0x000000ff;
#else
Uint32 rmask = 0x000000ff;
Uint32 gmask = 0x0000ff00;
Uint32 bmask = 0x00ff0000;
Uint32 amask = 0xff000000;
#endif

0
src/Player.cpp Normal file
View file

0
src/Player.hpp Normal file
View file

0
src/Upgrades.cpp Normal file
View file

19
src/Upgrades.hpp Normal file
View file

@ -0,0 +1,19 @@
#include <SDL2/SDL.h>
#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