Pan, zoom, and mouse-to-gridsquare translation that I can be proud of. Cleanup required, though
This commit is contained in:
parent
b0ef1d2303
commit
a4b6c2c428
196
src/Grid.cpp
196
src/Grid.cpp
|
@ -14,7 +14,7 @@ void Grid::setSprite(int ti)
|
||||||
Grid::Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h):
|
Grid::Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h):
|
||||||
grid_size(gs),
|
grid_size(gs),
|
||||||
grid_x(gx), grid_y(gy),
|
grid_x(gx), grid_y(gy),
|
||||||
zoom(1.0f), center_x(gx), center_y(gy),
|
zoom(1.0f), center_x((gx/2) * gs), center_y((gy/2) * gs),
|
||||||
texture_width(12), texture_height(11)
|
texture_width(12), texture_height(11)
|
||||||
{
|
{
|
||||||
//grid_size = gs;
|
//grid_size = gs;
|
||||||
|
@ -49,12 +49,16 @@ bool Grid::inBounds(int x, int y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grid::screenToGrid(int sx, int sy, int& gx, int& gy) {
|
void Grid::screenToGrid(int sx, int sy, int& gx, int& gy) {
|
||||||
|
|
||||||
|
float center_x_sq = center_x / grid_size;
|
||||||
|
float center_y_sq = center_y / grid_size;
|
||||||
|
|
||||||
float width_sq = box.getSize().x / (grid_size * zoom);
|
float width_sq = box.getSize().x / (grid_size * zoom);
|
||||||
float height_sq = box.getSize().y / (grid_size * zoom);
|
float height_sq = box.getSize().y / (grid_size * zoom);
|
||||||
float left_edge = center_x - (width_sq / 2.0);
|
float left_edge = center_x_sq - (width_sq / 2.0);
|
||||||
float right_edge = center_x + (width_sq / 2.0);
|
float right_edge = center_x_sq + (width_sq / 2.0);
|
||||||
float top_edge = center_y - (height_sq / 2.0);
|
float top_edge = center_y_sq - (height_sq / 2.0);
|
||||||
float bottom_edge = center_y + (height_sq / 2.0);
|
float bottom_edge = center_y_sq + (height_sq / 2.0);
|
||||||
|
|
||||||
float grid_px = zoom * grid_size;
|
float grid_px = zoom * grid_size;
|
||||||
//std::cout << "##############################" <<
|
//std::cout << "##############################" <<
|
||||||
|
@ -70,6 +74,20 @@ void Grid::screenToGrid(int sx, int sy, int& gx, int& gy) {
|
||||||
float ans_x = mouse_x_sq + left_edge;
|
float ans_x = mouse_x_sq + left_edge;
|
||||||
float ans_y = mouse_y_sq + top_edge;
|
float ans_y = mouse_y_sq + top_edge;
|
||||||
|
|
||||||
|
// compare integer method with this (mostly working) one
|
||||||
|
//int diff_realpixel_x = box.getSize().x / 2.0 - sx;
|
||||||
|
//int diff_realpixel_y = box.getSize().y / 2.0 - sy;
|
||||||
|
int left_spritepixels = center_x - (box.getSize().x / 2.0 / zoom);
|
||||||
|
int top_spritepixels = center_y - (box.getSize().y / 2.0 / zoom);
|
||||||
|
|
||||||
|
std::cout << "Float method got ans (" << ans_x << ", " << ans_y << ")"
|
||||||
|
<< std::endl << "Int method px (" << left_spritepixels + (sx/zoom) << ", " <<
|
||||||
|
top_spritepixels + (sy/zoom) << ")" << std::endl <<
|
||||||
|
"Int grid (" << (left_spritepixels + (sx/zoom) ) / grid_size <<
|
||||||
|
", " << (top_spritepixels + (sy/zoom)) / grid_size << ")" <<
|
||||||
|
|
||||||
|
std::endl;
|
||||||
|
|
||||||
// casting float turns -0.5 to 0; I want any negative coord to be OOB
|
// casting float turns -0.5 to 0; I want any negative coord to be OOB
|
||||||
if (ans_x < 0) ans_x = -1;
|
if (ans_x < 0) ans_x = -1;
|
||||||
if (ans_y < 0) ans_y = -1;
|
if (ans_y < 0) ans_y = -1;
|
||||||
|
@ -89,68 +107,117 @@ void Grid::screenToGrid(int sx, int sy, int& gx, int& gy) {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Grid::renderPxToGrid(int sx, int sy, int& gx, int& gy) {
|
||||||
|
// just like screen px coversion, but no offset by grid's position
|
||||||
|
float center_x_sq = center_x / grid_size;
|
||||||
|
float center_y_sq = center_y / grid_size;
|
||||||
|
|
||||||
|
float width_sq = box.getSize().x / (grid_size * zoom);
|
||||||
|
float height_sq = box.getSize().y / (grid_size * zoom);
|
||||||
|
|
||||||
|
int width_px = box.getSize().x / 2.0;
|
||||||
|
int height_px = box.getSize().y / 2.0;
|
||||||
|
|
||||||
|
float left_edge = center_x_sq - (width_sq / 2.0);
|
||||||
|
float top_edge = center_y_sq - (height_sq / 2.0);
|
||||||
|
|
||||||
|
float grid_px = zoom * grid_size;
|
||||||
|
float sx_sq = sx / grid_px;
|
||||||
|
float sy_sq = sy / grid_px;
|
||||||
|
|
||||||
|
float ans_x = sx_sq + left_edge;
|
||||||
|
float ans_y = sy_sq + top_edge;
|
||||||
|
|
||||||
|
if (ans_x < 0) ans_x = -1;
|
||||||
|
if (ans_y < 0) ans_y = -1;
|
||||||
|
|
||||||
|
gx = ans_x;
|
||||||
|
gy = ans_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grid::integerGrid(float fx, float fy, int& gx, int& gy) {
|
||||||
|
if (fx < 0) fx -= 0.5;
|
||||||
|
if (fy < 0) fy -= 0.5;
|
||||||
|
gx = fx;
|
||||||
|
gy = fy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grid::gridToRenderPx(int gx, int gy, int& sx, int& sy) {
|
||||||
|
// integer grid square (gx, gy) - what pixel (on rendertexture)
|
||||||
|
// should it's top left corner be at (the sprite's position)
|
||||||
|
|
||||||
|
// eff_gridsize = grid_size * zoom
|
||||||
|
// if center_x = 161, and grid_size is 16, that's 10 + 1/16 sprites
|
||||||
|
// center_x - (box.getSize().x / 2 / zoom) = left edge (in px)
|
||||||
|
// gx * eff_gridsize = pixel position without panning
|
||||||
|
// pixel_gx - left_edge = grid's render position
|
||||||
|
|
||||||
|
sx = (gx * grid_size * zoom) - (center_x - (box.getSize().x / 2.0 / zoom));
|
||||||
|
sy = (gy * grid_size * zoom) - (center_y - (box.getSize().y / 2.0 / zoom));
|
||||||
|
}
|
||||||
|
|
||||||
void Grid::render(sf::RenderWindow & window)
|
void Grid::render(sf::RenderWindow & window)
|
||||||
{
|
{
|
||||||
renderTexture.clear();
|
renderTexture.clear();
|
||||||
//renderTexture.draw(box);
|
//renderTexture.draw(box);
|
||||||
|
|
||||||
// sprites that are visible according to zoom, center_x, center_y, and box width
|
// sprites that are visible according to zoom, center_x, center_y, and box width
|
||||||
|
float center_x_sq = center_x / grid_size;
|
||||||
|
float center_y_sq = center_y / grid_size;
|
||||||
|
|
||||||
float width_sq = box.getSize().x / (grid_size * zoom);
|
float width_sq = box.getSize().x / (grid_size * zoom);
|
||||||
float height_sq = box.getSize().y / (grid_size * zoom);
|
float height_sq = box.getSize().y / (grid_size * zoom);
|
||||||
float left_edge = center_x - (width_sq / 2.0);
|
float left_edge = center_x_sq - (width_sq / 2.0);
|
||||||
float right_edge = center_x + (width_sq / 2.0);
|
//float right_edge = center_x_sq + (width_sq / 2.0);
|
||||||
float top_edge = center_y - (height_sq / 2.0);
|
float top_edge = center_y_sq - (height_sq / 2.0);
|
||||||
float bottom_edge = center_y + (height_sq / 2.0);
|
//float bottom_edge = center_y_sq + (height_sq / 2.0);
|
||||||
|
|
||||||
//auto box_size = box.getSize();
|
|
||||||
//float view_width = box_size.x / (grid_size * zoom);
|
|
||||||
//float view_height = box_size.y / (grid_size * zoom);
|
|
||||||
|
|
||||||
//float top_offset = (center_y * grid_size) - box_size.y/2.0f;
|
int left_spritepixels = center_x - (box.getSize().x / 2.0 / zoom);
|
||||||
//float left_offset = (center_x * grid_size) - box_size.x/2.0f;
|
int top_spritepixels = center_y - (box.getSize().y / 2.0 / zoom);
|
||||||
|
|
||||||
sprite.setScale(sf::Vector2f(zoom, zoom));
|
sprite.setScale(sf::Vector2f(zoom, zoom));
|
||||||
sf::RectangleShape r; // for colors and overlays
|
sf::RectangleShape r; // for colors and overlays
|
||||||
r.setSize(sf::Vector2f(grid_size * zoom, grid_size * zoom));
|
r.setSize(sf::Vector2f(grid_size * zoom, grid_size * zoom));
|
||||||
r.setOutlineThickness(0);
|
r.setOutlineThickness(0);
|
||||||
|
|
||||||
//auto box_pos = box.getPosition();
|
int x_limit = left_edge + width_sq + 2;
|
||||||
|
|
||||||
//int x_start = std::floor(center_x - view_width/2.0f);
|
|
||||||
//int x_end = std::ceil(center_x + view_width/2.0f);
|
|
||||||
//int y_start = std::floor(center_y - view_height/2.0f);
|
|
||||||
//int y_end = std::ceil(center_y + view_height/2.0f);
|
|
||||||
int x_limit = left_edge + width_sq + 1;
|
|
||||||
if (x_limit > grid_x) x_limit = grid_x;
|
if (x_limit > grid_x) x_limit = grid_x;
|
||||||
|
|
||||||
int y_limit = top_edge + height_sq + 1;
|
int y_limit = top_edge + height_sq + 2;
|
||||||
if (y_limit > grid_y) y_limit = grid_y;
|
if (y_limit > grid_y) y_limit = grid_y;
|
||||||
|
|
||||||
for (float x = (left_edge >= 0 ? left_edge : 0);
|
//for (float x = (left_edge >= 0 ? left_edge : 0);
|
||||||
|
for (int x = (left_edge - 1 >= 0 ? left_edge - 1 : 0);
|
||||||
x < x_limit; //x < view_width;
|
x < x_limit; //x < view_width;
|
||||||
x+=1.0)
|
x+=1)
|
||||||
{
|
{
|
||||||
for (float y = (top_edge >= 0 ? top_edge : 0);
|
//for (float y = (top_edge >= 0 ? top_edge : 0);
|
||||||
|
for (int y = (top_edge - 1 >= 0 ? top_edge - 1 : 0);
|
||||||
y < y_limit; //y < view_height;
|
y < y_limit; //y < view_height;
|
||||||
y+=1.0)
|
y+=1)
|
||||||
{
|
{
|
||||||
|
// Converting everything to integer pixels to avoid jitter
|
||||||
|
//auto pixel_pos = sf::Vector2f(
|
||||||
|
// (x - left_edge) * (zoom * grid_size),
|
||||||
|
// (y - top_edge) * (zoom * grid_size));
|
||||||
|
|
||||||
|
// This failed horribly:
|
||||||
|
//int gx, gy; integerGrid(x, y, gx, gy);
|
||||||
|
//int px_x, px_y; gridToRenderPx(gx, gy, px_x, px_y);
|
||||||
|
//auto pixel_pos = sf::Vector2f(px_x, px_y);
|
||||||
|
|
||||||
|
// this draws coherently, but the coordinates
|
||||||
|
// don't match up with the mouse cursor function
|
||||||
|
// jitter not eliminated
|
||||||
auto pixel_pos = sf::Vector2f(
|
auto pixel_pos = sf::Vector2f(
|
||||||
(x - left_edge) * (zoom * grid_size),
|
(x*grid_size - left_spritepixels) * zoom,
|
||||||
(y - top_edge) * (zoom * grid_size));
|
(y*grid_size - top_spritepixels) * zoom );
|
||||||
|
|
||||||
auto gridpoint = at(std::floor(x), std::floor(y));
|
auto gridpoint = at(std::floor(x), std::floor(y));
|
||||||
|
|
||||||
// convert grid's coordinate to pixel coords to draw
|
|
||||||
//float window_x = (x_start + x) * grid_size * zoom;
|
|
||||||
//float window_y = (y_start + y) * grid_size * zoom;
|
|
||||||
//float natural_x = x * grid_size * zoom;
|
|
||||||
//float natural_y = y * grid_size * zoom;
|
|
||||||
sprite.setPosition(pixel_pos);
|
sprite.setPosition(pixel_pos);
|
||||||
//sf::Vector2f(natural_x - left_offset,
|
|
||||||
// natural_y - top_offset));
|
|
||||||
|
|
||||||
// color?
|
|
||||||
//r.setPosition(sf::Vector2f(natural_x - left_offset,
|
|
||||||
// natural_y - top_offset));
|
|
||||||
r.setPosition(pixel_pos);
|
r.setPosition(pixel_pos);
|
||||||
r.setFillColor(gridpoint.color);
|
r.setFillColor(gridpoint.color);
|
||||||
renderTexture.draw(r);
|
renderTexture.draw(r);
|
||||||
|
@ -198,56 +265,3 @@ GridPoint& Grid::at(int x, int y)
|
||||||
{
|
{
|
||||||
return points[y * grid_x + x];
|
return points[y * grid_x + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
GridPoint* Grid::atScreenPixel(int sx, int sy, int* gx=NULL, int* gy=NULL) {
|
|
||||||
|
|
||||||
int _x, _y;
|
|
||||||
screenToGrid(sx, sy, _x, _y);
|
|
||||||
std::cout << "screenToGrid gave: (" << _x << ", " << _y << ")" << std::endl;
|
|
||||||
|
|
||||||
auto p = box.getPosition();
|
|
||||||
auto s = box.getSize();
|
|
||||||
|
|
||||||
// debug render values
|
|
||||||
int x_start = std::floor(center_x - s.x/2.0f);
|
|
||||||
int x_end = std::ceil(center_x + s.x/2.0f);
|
|
||||||
int y_start = std::floor(center_y - s.y/2.0f);
|
|
||||||
int y_end = std::ceil(center_y + s.y/2.0f);
|
|
||||||
std::cout << "Center: " << center_x << ", " << center_y << std::endl <<
|
|
||||||
"Start grid: " << x_start << ", " << y_start << std::endl <<
|
|
||||||
"End grid: " << x_end << ", " << y_end << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
// check if the mouse is even over the grid
|
|
||||||
if (sx < p.x || sx > p.x+s.x || sy < p.y || sy > p.y+s.y) {
|
|
||||||
std::cout << "(" << sx << ", " << sy << ") not over grid" << std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// get dx, dy to box's center
|
|
||||||
int dx = sx - (s.x/2.0 + p.x),
|
|
||||||
dy = sy - (s.y/2.0 + p.y);
|
|
||||||
|
|
||||||
// divide dx, dy by (gridsize * zoom) to get # in boxes
|
|
||||||
int gdx = dx / (grid_size * zoom),
|
|
||||||
gdy = dy / (grid_size * zoom);
|
|
||||||
|
|
||||||
int targetx = gdx + center_x,
|
|
||||||
targety = gdy + center_y;
|
|
||||||
// return
|
|
||||||
if (gx) {
|
|
||||||
*gx = targetx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gy) {
|
|
||||||
*gy = targety;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetx >= 0 && targetx <= grid_x && targety >= 0 && targety <= grid_y) {
|
|
||||||
return &points[targety * grid_x + targetx];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "(" << sx << ", " << sy << ") not over actual grid content" << std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,14 +29,16 @@ public:
|
||||||
Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h);
|
Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h);
|
||||||
int grid_x, grid_y; // rectangle map size (integer - sprites)
|
int grid_x, grid_y; // rectangle map size (integer - sprites)
|
||||||
int grid_size; // pixel size of 1 sprite
|
int grid_size; // pixel size of 1 sprite
|
||||||
float zoom, center_x, center_y; // center in fractional sprites
|
float zoom;
|
||||||
|
int center_x, center_y; // center in 1.0x Pixels
|
||||||
|
|
||||||
std::vector<GridPoint> points; // grid visible contents
|
std::vector<GridPoint> points; // grid visible contents
|
||||||
void render(sf::RenderWindow&); // draw to screen
|
void render(sf::RenderWindow&); // draw to screen
|
||||||
GridPoint& at(int, int);
|
GridPoint& at(int, int);
|
||||||
bool inBounds(int, int);
|
bool inBounds(int, int);
|
||||||
void screenToGrid(int, int, int&, int&);
|
void screenToGrid(int, int, int&, int&);
|
||||||
GridPoint* atScreenPixel(int, int, int*, int*);
|
|
||||||
|
|
||||||
|
void renderPxToGrid(int, int, int&, int&);
|
||||||
|
void gridToRenderPx(int, int, int&, int&);
|
||||||
|
void integerGrid(float, float, int&, int&);
|
||||||
};
|
};
|
||||||
|
|
|
@ -253,16 +253,16 @@ void UITestScene::doAction(std::string name, std::string type)
|
||||||
if (ACTION("sound_test", "start")) { sound.play(); }
|
if (ACTION("sound_test", "start")) { sound.play(); }
|
||||||
|
|
||||||
if (ACTION("left", "start")) {
|
if (ACTION("left", "start")) {
|
||||||
grid.center_x -= 0.5;
|
grid.center_x -= 1;
|
||||||
}
|
}
|
||||||
if (ACTION("right", "start")) {
|
if (ACTION("right", "start")) {
|
||||||
grid.center_x += 0.5;
|
grid.center_x += 1;
|
||||||
}
|
}
|
||||||
if (ACTION("up", "start")) {
|
if (ACTION("up", "start")) {
|
||||||
grid.center_y -= 0.5;
|
grid.center_y -= 1;
|
||||||
}
|
}
|
||||||
if (ACTION("down", "start")) {
|
if (ACTION("down", "start")) {
|
||||||
grid.center_y += 0.5;
|
grid.center_y += 1;
|
||||||
}
|
}
|
||||||
if (ACTION("zoom_down", "start")) {
|
if (ACTION("zoom_down", "start")) {
|
||||||
if (grid.zoom > 0.75f) grid.zoom -= 0.25f;
|
if (grid.zoom > 0.75f) grid.zoom -= 0.25f;
|
||||||
|
@ -293,7 +293,7 @@ void UITestScene::doAction(std::string name, std::string type)
|
||||||
grid.screenToGrid(mousepos.x, mousepos.y, tx, ty);
|
grid.screenToGrid(mousepos.x, mousepos.y, tx, ty);
|
||||||
if (grid.inBounds(tx, ty)) {
|
if (grid.inBounds(tx, ty)) {
|
||||||
auto gridsq = grid.at(tx, ty);
|
auto gridsq = grid.at(tx, ty);
|
||||||
std::cout << "At (" << tx << ", " << ty << "): " << gridsq.tilesprite << std::endl;
|
std::cout << "At (" << tx << ", " << ty << "): " << gridsq.tilesprite << " Center: (" << grid.center_x << ", " << grid.center_y << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue