#include "Grid.h" #include GridPoint::GridPoint(): color(0, 0, 0, 0), walkable(true), tilesprite(-1), transparent(true), visible(false), discovered(false), color_overlay(0,0,0,255), tile_overlay(-1), uisprite(-1) {}; void Grid::setSprite(int ti) { int tx = ti % texture_width, ty = ti / texture_width; sprite.setTextureRect(sf::IntRect(tx * grid_size, ty * grid_size, grid_size, grid_size)); } Grid::Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h): grid_size(gs), grid_x(gx), grid_y(gy), zoom(1.0f), center_x((gx/2) * gs), center_y((gy/2) * gs), texture_width(12), texture_height(11), visible(false) { //grid_size = gs; //zoom = 1.0f; //grid_x = gx; //grid_y = gy; points.resize(gx*gy); box.setSize(sf::Vector2f(_w, _h)); box.setPosition(sf::Vector2f(_x, _y)); box.setFillColor(sf::Color(0,0,0,0)); renderTexture.create(_w, _h); texture.loadFromFile("./assets/kenney_tinydungeon.png"); texture.setSmooth(false); sprite.setTexture(texture); //output.setSize(box.getSize()); output.setTextureRect( sf::IntRect(0, 0, box.getSize().x, box.getSize().y)); output.setPosition(box.getPosition()); // textures are upside-down inside renderTexture output.setTexture(renderTexture.getTexture()); // Show one texture at a time sprite.setTexture(texture); } bool Grid::inBounds(int x, int y) { return (x >= 0 && y >= 0 && x < grid_x && y < grid_y); } 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 height_sq = box.getSize().y / (grid_size * zoom); float left_edge = center_x_sq - (width_sq / 2.0); float right_edge = center_x_sq + (width_sq / 2.0); float top_edge = center_y_sq - (height_sq / 2.0); float bottom_edge = center_y_sq + (height_sq / 2.0); float grid_px = zoom * grid_size; //std::cout << "##############################" << // "\nscreen coord: (" << sx << ", " << sy << ")" << std::endl; sx -= box.getPosition().x; sy -= box.getPosition().y; //std::cout << "box coord: (" << sx << ", " << sy << ")" << std::endl; float mouse_x_sq = sx / grid_px; float mouse_y_sq = sy / grid_px; float ans_x = mouse_x_sq + left_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 if (ans_x < 0) ans_x = -1; if (ans_y < 0) ans_y = -1; gx = ans_x; gy = ans_y; /* std::cout << "C: (" << center_x << ", " << center_y << ")" << std::endl << "W: " << width_sq << " H: " << height_sq << std::endl << "L: " << left_edge << " T: " << top_edge << std::endl << "R: " << right_edge << " B: " << bottom_edge << std::endl << "Grid Px: " << grid_px << "( zoom: " << zoom << ")" << std::endl << "answer: G(" << ans_x << ", " << ans_y << ")" << std::endl << "##############################" << std::endl; */ } 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) { renderTexture.clear(); //renderTexture.draw(box); // 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 height_sq = box.getSize().y / (grid_size * zoom); float left_edge = center_x_sq - (width_sq / 2.0); //float right_edge = center_x_sq + (width_sq / 2.0); float top_edge = center_y_sq - (height_sq / 2.0); //float bottom_edge = center_y_sq + (height_sq / 2.0); int left_spritepixels = center_x - (box.getSize().x / 2.0 / zoom); int top_spritepixels = center_y - (box.getSize().y / 2.0 / zoom); sprite.setScale(sf::Vector2f(zoom, zoom)); sf::RectangleShape r; // for colors and overlays r.setSize(sf::Vector2f(grid_size * zoom, grid_size * zoom)); r.setOutlineThickness(0); int x_limit = left_edge + width_sq + 2; if (x_limit > grid_x) x_limit = grid_x; int y_limit = top_edge + height_sq + 2; if (y_limit > grid_y) y_limit = grid_y; //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+=1) { //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+=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( (x*grid_size - left_spritepixels) * zoom, (y*grid_size - top_spritepixels) * zoom ); auto gridpoint = at(std::floor(x), std::floor(y)); sprite.setPosition(pixel_pos); r.setPosition(pixel_pos); r.setFillColor(gridpoint.color); renderTexture.draw(r); // tilesprite // if discovered but not visible, set opacity to 90% // if not discovered... just don't draw it? if (gridpoint.tilesprite != -1) { setSprite(gridpoint.tilesprite); renderTexture.draw(sprite); } // overlay // uisprite } } // grid lines for testing & validation /* sf::Vertex line[] = { sf::Vertex(sf::Vector2f(0, 0), sf::Color::Red), sf::Vertex(box.getSize(), sf::Color::Red), }; renderTexture.draw(line, 2, sf::Lines); sf::Vertex lineb[] = { sf::Vertex(sf::Vector2f(0, box.getSize().y), sf::Color::Blue), sf::Vertex(sf::Vector2f(box.getSize().x, 0), sf::Color::Blue), }; renderTexture.draw(lineb, 2, sf::Lines); */ // render to window renderTexture.display(); window.draw(output); } GridPoint& Grid::at(int x, int y) { return points[y * grid_x + x]; }