如何在 SFML 中添加冲突

How to add collision in SFML

本文关键字:添加 冲突 SFML      更新时间:2023-10-16

我正在努力创建乒乓球,但我一直遇到碰撞问题。如何添加像素准确的碰撞?我在仅使用主文件时创建了冲突,但在使用头文件时无法弄清楚。有人可以写出 Collision 的代码并添加到 Collision.h 和 Collision 中.cpp以便于存储和修改。

主.cpp

#include "stdafx.h"
#include <SFMLGraphics.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;
}

划桨.h

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

划桨.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));
    }
}

鲍尔·

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

球.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()
{
}

由于 Pong 是一个非常简单的游戏,我建议你创建一个以sf::CircleShapesf::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);
}

基于这个问题,但我在每一步中都将其分开以更好地理解。


编辑

请注意,此方法仅在矩形处于垂直/水平方向时才有效,即没有旋转。