Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Mouse hover over graphic detection  (Read 7239 times)

0 Members and 1 Guest are viewing this topic.

Steven_Bersek

  • Newbie
  • *
  • Posts: 4
    • View Profile
Mouse hover over graphic detection
« on: December 26, 2016, 04:16:59 pm »
Hi, I am new to SFML and C++ in general.
I am building the Conway's Game of life for a school project.

As base objects for my grid, I have Squares (which are sf::RectangleShape as for base).
The grid is a std::vector<std::vector<Square>> (vector of vectors of Squares).

What I am trying to do at the moment is to change the color of a square when I hover over it with the cursor.
My way of doing it (see code below):
1- I get the position of cursor when I move it
2- I iterate through my matrix and check for each square if it contains the position of the cursor (with .getGlobalBounds().contains(cursorPos))

But this does not work. It iterates but it does not find any collision.

Can you see what is wrong?
Thanks.

int main()
{
        int width;
        int height;
        int numberSquareWidth = 15;
        int numberSquareHeight = 15;
        int squareSize = 20;
        int offset = 1;
        initializeWindowGridValues(width, height, numberSquareWidth, numberSquareHeight, squareSize, offset);

        sf::RenderWindow window(sf::VideoMode(width, height), "Stephan's Game Of Life!");
        std::vector<std::vector<Square>> matrix(numberSquareWidth, std::vector<Square>(numberSquareHeight));
        initiatlizeGrid(numberSquareWidth, numberSquareHeight, squareSize, offset, matrix);
       
        while (window.isOpen())
        {
                sf::Event event;
                sf::Vector2i cursorPos;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();

                        if (event.type == sf::Event::MouseMoved)
                        {
                                cursorPos = sf::Mouse::getPosition(window);
                                std::cout << "Position of cursor: " << cursorPos.x << "," << cursorPos.y << std::endl;
                        }
                        mouseHover(event, matrix, cursorPos);
                }
                window.clear(sf::Color::Black);
                drawGrid(window, matrix);
                window.display();
        }
        return 0;
}

void mouseHover(sf::Event &event, std::vector<std::vector<Square>> &matrix, const sf::Vector2i cursorPos)
{
        for (auto &vector : matrix)
        {
                for (auto &square : vector)
                {
                        if (square.getGlobalBounds().contains(static_cast<sf::Vector2f>(cursorPos))) //does square contain position of cursor?
                        {
                                std::cout << "Collision" << static_cast<sf::Vector2f>(cursorPos).x <<"," << static_cast<sf::Vector2f>(cursorPos).y << std::endl;
                                //square.setFillColor(sf::Color::Yellow);
                        }
                }
        }
}

Steven_Bersek

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Mouse hover over graphic detection
« Reply #1 on: December 26, 2016, 05:19:02 pm »
I applied a workaround that works: in mouseHover function, instead of
if (square.getGlobalBounds().contains(static_cast<sf::Vector2f>(cursorPos)))
I do
if (cursorPos.x >= square.getPosition().x
    && cursorPos.x <= (square.getPosition().x + squareSize)
    && cursorPos.y >= square.getPosition().y
    && cursorPos.y <= (square.getPosition().y + squareSize))

I still do not know why my previous predicate did not give the same result though...

Since now I know which square of my grid is under my cursor, I try to change its color with
square.setFillColor(sf::Color::Yellow);
but nothing happens to it.
Any thoughts?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Mouse hover over graphic detection
« Reply #2 on: December 26, 2016, 08:16:10 pm »
If all squares have the same size, and they are aligned on axes, then you can directly compute the indices of the square by dividing the mouse coordinates by the square size. No need to check all squares.
Laurent Gomila - SFML developer

Steven_Bersek

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Mouse hover over graphic detection
« Reply #3 on: December 26, 2016, 09:48:08 pm »
If all squares have the same size, and they are aligned on axes, then you can directly compute the indices of the square by dividing the mouse coordinates by the square size. No need to check all squares.
Indeed. Thank you Laurent. I changed my "mouseHover" function to calculate the indexes of the square below the cursor like you suggested.

But I do not understand why the square's color does not change (see my comment in code)?

int main()
{
        //[code ommited]
        int squareSize = 20;
        int offset = 1;

        sf::RenderWindow window(sf::VideoMode(width, height), "Stephan's Game Of Life!");
        std::vector<std::vector<Square>> matrix(numberSquareWidth, std::vector<Square>(numberSquareHeight));
        initiatlizeGrid(numberSquareWidth, numberSquareHeight, squareSize, offset, matrix);
       
        sf::Vector2i cursorPos;
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();

                        if (event.type == sf::Event::MouseMoved)
                        {
                                cursorPos = sf::Mouse::getPosition(window);
                        }
                }
                mouseHover(matrix, cursorPos, squareSize, offset);

                window.clear(sf::Color::Black);
                drawGrid(window, matrix);
                window.display();
        }
        return 0;
}

void mouseHover(std::vector<std::vector<Square>> &matrix, const sf::Vector2i &cursorPos, const int &squareSize, const int &offset)
{
        int rowIndex = floor((cursorPos.x - (offset * floor(cursorPos.x / squareSize))) / squareSize);
        int colIndex = floor((cursorPos.y - (offset * floor(cursorPos.y / squareSize))) / squareSize);
        matrix[rowIndex][colIndex].setFillColor(sf::Color::Blue); // I do not see this happening??!
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Mouse hover over graphic detection
« Reply #4 on: December 27, 2016, 09:22:06 am »
Did you first check that the indices were correct?
Laurent Gomila - SFML developer

Steven_Bersek

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Mouse hover over graphic detection
« Reply #5 on: December 27, 2016, 02:50:09 pm »
Problem found.

My custom class Square inherits from
sf::RectangleShape
but I had a class member
sf::RectangleShape square
inside it.
I removed this class member and now thinks are better.
Thanks