Как добавить столкновение в SFML

Я работаю над созданием понга, но у меня возникли проблемы с Collision. Как я могу добавить Collision с точностью до пикселя? Я создал коллизию при использовании только основного файла, но не могу понять это при использовании заголовочных файлов. Может кто-нибудь написать код для Collision и добавить его в Collision.h и Collision.cpp для удобства хранения и модификации.

main.cpp

#include "stdafx.h"
#include <SFML\Graphics.hpp>
#include "Paddle.h"
#include "Ball.h"
#include <iostream>
int main()
{
    sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "Pong", 
    sf::Style::Close| sf::Style::Resize| sf::Style::Titlebar);
    Paddle paddle1;
    Paddle paddle2;
    Ball ball;
    while (window.isOpen()) {
        sf::Event evnt;
        while (window.pollEvent(evnt))
        {
            switch (evnt.type)
            {  
            case sf::Event::Closed:
                window.close();
                break;
            }
        }
        paddle1.Update();
        paddle2.Update();
        ball.Update(ballDirectionX,ballDirectionY);
        window.clear();
        paddle1.Draw(window);
        paddle2.Draw(window);
        ball.Draw(window);
        window.display();
   }
   return 0;
}

Paddle.h

#pragma once
#include <SFML\Graphics.hpp>
class Paddle
{
public:
    Paddle();
    ~Paddle();
    void Draw(sf::RenderWindow& window);
    void Update();
    sf::RectangleShape paddle1;
    sf::RectangleShape paddle2;
private:
};

Paddle.cpp

#include "stdafx.h"
#include "Paddle.h"
Paddle::Paddle()
{
    paddle1.setSize(sf::Vector2f(20.0f, 120.0f));
    paddle1.setFillColor(sf::Color::Red);
    paddle2.setSize(sf::Vector2f(20.0f, 120.0f));
    paddle2.setFillColor(sf::Color::Green);
    paddle2.setPosition(sf::Vector2f(1900.0f, 0.0f));
}
Paddle::~Paddle()
{
} 
void Paddle::Draw(sf::RenderWindow& window)
{
    window.draw(paddle1);
    window.draw(paddle2);
}
void Paddle::Update()
{
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
        paddle1.move(sf::Vector2f(0, -3));
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
        paddle1.move(sf::Vector2f(0, 3));
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
        paddle2.move(sf::Vector2f(0, -3));
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
        paddle2.move(sf::Vector2f(0, 3));
    }
}

Ball.h

#pragma once
#include <SFML\Graphics.hpp>
class Ball
{
public:
     Ball();
     ~Ball();
     void Draw(sf::RenderWindow& window);
     void Update() {
     }
     sf::CircleShape ball;
private:    

};

Ball.cpp

#include "stdafx.h"
#include "Ball.h"
Ball::Ball()
{
    ball.setRadius(20);
    ball.setPosition(sf::Vector2f(400, 540));
}
Ball::~Ball()
{
}
void Ball::Draw(sf::RenderWindow & window)
{
window.draw(ball);
}
void Ball::Update()
{
}

1 ответ

Поскольку Pong - очень простая игра, я предлагаю вам создать функцию пересечения с sf::CircleShape и sf::RectangleShape в качестве аргументов, потому что именно так вы представляете свой мяч и весла соответственно.

Я предлагаю вам следующую реализацию, но есть и лучшие:

bool intersects(const sf::CircleShape &c, const sf::RectangleShape &r){
    sf::FloatRect fr = r.getGlobalBounds();
    sf::Vector2f topLeft(fr.left, fr.top);
    sf::Vector2f topRight(fr.left + fr.width, fr.top);
    sf::Vector2f botLeft(fr.left, fr.top + fr.height);
    sf::Vector2f botRight(fr.left + fr.width, fr.top + fr.height);

    return contains(c, topLeft) || 
        contains(c, topRight) || 
        contains(c, botLeft) || 
        contains(c, botRight);
}

Это легко, просто проверьте, находится ли каждый угол прямоугольника внутри круга, если ни один из них не содержится, этот круг и этот прямоугольник не пересекаются.

Если какой-либо из углов содержится в круге, они пересекаются.

contains() функция довольно простая на самом деле:

bool contains(const sf::CircleShape &c, const sf::Vector2f &p){
    sf::Vector2f center = c.getPosition();
    float a = (p.x - center.x);
    float b = (p.y - center.y);
    a *= a;
    b *= b;
    float r = c.getRadius() * c.getRadius();

    return (( a + b ) < r);
}

Основан на этом вопросе, но я разделил его на каждом шаге для лучшего понимания.


РЕДАКТИРОВАТЬ

Обратите внимание, что этот метод работает, только если прямоугольники находятся в вертикальной / горизонтальной ориентации, то есть без поворотов.

Другие вопросы по тегам