Search code examples
c++mathsfml

Finding the 4 corners of a rectangle which connects two moving objects


I am trying to make a line between two points, I am using sf::VertexArray shape(sf::Quads, 4); for this.

This is my entire draw function:

void Stick::draw(sf::RenderTarget& target, sf::RenderStates states) const {
sf::VertexArray shape(sf::Quads, 4);

sf::Vector2f p1Pos = this->p1->getPosition();
sf::Vector2f p2Pos = this->p2->getPosition();

shape[0].position = sf::Vector2f(p1Pos.x + 10.f, p1Pos.y + 10.f);
shape[1].position = sf::Vector2f(p1Pos.x - 10.f, p1Pos.y - 10.f);
shape[2].position = sf::Vector2f(p2Pos.x - 10.f, p2Pos.y - 10.f);
shape[3].position = sf::Vector2f(p2Pos.x + 10.f, p2Pos.y + 10.f);
shape[0].color = sf::Color::Green;
shape[1].color = sf::Color::Green;
shape[2].color = sf::Color::Green;
shape[3].color = sf::Color::Green;
target.draw(shape, states);
}

p1Pos and p2Pos are the center coordinates of the points.

What this gets me is a line which obviously won't work with moving objects, since the corner points of the rectangles are fixed, here's some examples: (the red dot isn't moving while the white one is in this example)

Example Example 2

I would like to implement a solution so that the 'Stick' (rectangle) works regardless of the positions of the two points, and I will later on be adding some sort of onClick event for the sticks, so that I can delete them by clicking on them, so the solution would need to be compatible with that as well... Thanks!


Solution

  • You can find the normal of the line. This can be done by subtracting the positions p1Pos and p2Pos (and flipping either sign of x or y to get a 90° rotation) and dividing that by the length of the line. The length of the line can be found via Pythagoras theorem, since it can be thought of as the hypotenuse of a right triangle.

    auto diff = p1Pos - p2Pos;
    auto length = std::sqrt(diff.x * diff.x + diff.y * diff.y);
    auto normal = sf::Vector2f(p1Pos.y - p2Pos.y, p2Pos.x - p1Pos.x) / length;
    auto thickness = 15.0f;
    
    shape[0].position = sf::Vector2f(p1Pos.x + normal.x * thickness, p1Pos.y + normal.y * thickness);
    shape[1].position = sf::Vector2f(p1Pos.x - normal.x * thickness, p1Pos.y - normal.y * thickness);
    shape[2].position = sf::Vector2f(p2Pos.x - normal.x * thickness, p2Pos.y - normal.y * thickness);
    shape[3].position = sf::Vector2f(p2Pos.x + normal.x * thickness, p2Pos.y + normal.y * thickness);
    

    and here's the result: the line