Search code examples
c++sfml

C++ SFML how to change view on a grid (implementing infinite grid)


I'm trying to create a simulation of Game of Life, using a grid of rectangles in C++'s SFML library. For that, I need to implement an "infinite" grid. What I was thinking is simply drawing a really really big grid, and the window would only show a small part of it, while the user can change the view with the keyboard (moving the prespective up, down, right and left).

For that I have the following code. I created a grid which is ten times the size it would be normally (without implementing the view logic). Then I created a window in a certain size, and the view object which is the same size.

#include <iostream>
#include <SFML/Graphics.hpp>
#include "game_logic.h"

int main() {    
    // Create the grid of cells
    std::vector< std::vector<sf::RectangleShape> > grid;
    for (int i = 0; i < WINDOW_HEIGHT * 10 / GRID_SIZE; i++) {
        std::vector<sf::RectangleShape> row;
        for (int j = 0; j < WINDOW_WIDTH * 10 / GRID_SIZE; j++) {
            sf::RectangleShape cell(sf::Vector2f(GRID_SIZE, GRID_SIZE));
            cell.setFillColor(DEAD_CELL_COLOR);
            cell.setOutlineColor(sf::Color(200, 200, 200)); // Beige
            cell.setOutlineThickness(1.25);
            row.push_back(cell);
        }
        grid.push_back(row);
    }

    sf::RenderWindow window(sf::VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT), "Game of life", sf::Style::Default);
    sf::View view(sf::Vector2f(WINDOW_HEIGHT / 2, WINDOW_WIDTH / 2), sf::Vector2f(WINDOW_HEIGHT, WINDOW_WIDTH));

    getUserInput(window, grid, WINDOW_WIDTH, WINDOW_HEIGHT, GRID_SIZE);

    while (window.isOpen()) {
        sf::Event evnt;
        while (window.pollEvent(evnt)) {
            switch(evnt.type) {
                case sf::Event::KeyPressed:
                    if (evnt.key.code == sf::Keyboard::D){
                        view.move(sf::Vector2f(10, 0));
                        window.setView(view);
                    }
                    break;
            }
        }

        updateGrid(grid); // This simply change the grid values, based on Game of Life logic

        sf::sleep(sf::milliseconds(SLEEP_DURATION));
        window.clear();
        drawGrid(window, grid, GRID_SIZE);
        window.display();
    }

    return 0;
}

and this is 'drawGrid()':

void drawGrid(sf::RenderWindow& window, std::vector< std::vector<sf::RectangleShape> >& grid, int grid_size){
    for (int i = 0; i < grid.size(); i++) {
        for (int j = 0; j < grid[0].size(); j++) {
            // Set cell position based on its grid coordinates
            grid[i][j].setPosition(j * grid_size, i * grid_size);
            window.draw(grid[i][j]);
        }
    }
}

My problem is, this code doesn't shift the perspective when pressing 'D', it simply warps the entire grid. When pressing 'D', I go from this: enter image description here To this: enter image description here

Would appreciate the help, thanks in advance


Solution

  • As per the documentation, if setView isn't called, things are drawn to the default view. This means that the view you have at first and the view you have when pressing D are two different views and this can explain the change in perspective you get. I would try calling setView right after initialisation of your Window and View and see what happens.

    EDIT: I think we both missed this and this might actually be your problem: Your view is set with WINDOW_WIDTH and WINDOW_HEIGHT mixed up. Since the view isn't the same aspect ratio than your window, then this is surely what is causing the warping issue