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

Author Topic: How to detect collision when RenderWindow has an sf::View?  (Read 1507 times)

0 Members and 1 Guest are viewing this topic.

jfknyc

  • Newbie
  • *
  • Posts: 5
    • View Profile
How to detect collision when RenderWindow has an sf::View?
« on: August 12, 2020, 10:16:06 pm »
Hello. I'm working on a game that uses sf::View to let the user pan and scroll around the map. However, despite lots of work, I can't find a way to have any type of collision detection (either FloatRect methods or simple math) work with sf::View.

Let's say I start with a rectangle in the center of the window, and pan such that it's now at the bottom right corner. Using .getGlobalBounds().intersects... doesn't register anything when I click the rectangle in the bottom right — only when I click where the rectangle started. Using math (mouse.x > rect.getPosition().x) doesn't work either; I don't think any aspect of a RectangleShape changes when it moves on the window due to an sf::View.

So, is there any way for me to factor a View into the calculations when I want to do collision detection?

(Any help would be appreciated!)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Laurent Gomila - SFML developer

jfknyc

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: How to detect collision when RenderWindow has an sf::View?
« Reply #2 on: August 13, 2020, 03:30:02 pm »
You most likely need this function: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1RenderTarget.php#a2d3e9d7c4a1f5ea7e52b06f53e3011f9

Thank you, but it's still not working. Here's what I have to detect whether the mouse is within a rectangle that's affected by an sf::View:

bool pointRect(const sf::Vector2i& point, sf::RectangleShape& rect, const sf::RenderWindow& window) {
    auto pos = window.mapPixelToCoords(point);
    auto topleft = window.mapPixelToCoords((sf::Vector2i)rect.getPosition());
    auto bottomright = window.mapPixelToCoords(sf::Vector2i(rect.getPosition() + rect.getSize()));
   
    return pos.x > topleft.x && pos.x < bottomright.x && pos.y > topleft.y && pos.y < bottomright.y;
}
 

Helping me figure out what I've missed would be great!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: How to detect collision when RenderWindow has an sf::View?
« Reply #3 on: August 13, 2020, 03:39:12 pm »
That doesn't make much sense: you're trying to convert a rectangle in scene coordinates to scene coordinates (the fact that you have to cast your vector types is a good hint that something's wrong -- Vector2i defines pixels) ;)

I assume that "point" is mouse coordinates, as given by sf::Mouse::getPosition. I also assume that rect is the absolute bounding rect of an entity, as given by getGlobalBounds(). I also assume that the view that you mentioned is active in "window" when you call this function. (I wish I hadn't to assume so much stuff ;))

Then it's simple: you just have to convert mouse coordinates to "scene" coordinates, that is, coordinates in the current window's view.

bool pointRect(const sf::Vector2i& point, sf::RectangleShape& rect, const sf::RenderWindow& window) {
    return rect.contains(window.mapPixelToCoords(point));
}
« Last Edit: August 13, 2020, 03:41:55 pm by Laurent »
Laurent Gomila - SFML developer

jfknyc

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: How to detect collision when RenderWindow has an sf::View?
« Reply #4 on: August 13, 2020, 03:55:16 pm »
That doesn't make much sense: you're trying to convert a rectangle in scene coordinates to scene coordinates (the fact that you have to cast your vector types is a good hint that something's wrong -- Vector2i defines pixels) ;)

I assume that "point" is mouse coordinates, as given by sf::Mouse::getPosition. I also assume that rect is the absolute bounding rect of an entity, as given by getGlobalBounds(). I also assume that the view that you mentioned is active in "window" when you call this function. (I wish I hadn't to assume so much stuff ;))

Then it's simple: you just have to convert mouse coordinates to "scene" coordinates, that is, coordinates in the current window's view.

bool pointRect(const sf::Vector2i& point, sf::RectangleShape& rect, const sf::RenderWindow& window) {
    return rect.getGlobalBounds().contains(window.mapPixelToCoords(point));
}

All your assumptions are correct, and I see the problem in converting the rectangle. Thanks again! This is very helpful.