【问题标题】:How to prevent objects from intersecting in C++?如何防止对象在 C++ 中相交?
【发布时间】:2020-12-17 00:34:55
【问题描述】:

我一直致力于用 C++ 创建一个乒乓球游戏,但我面临着我的球和桨如何碰撞的问题。实际上,当球从顶部击中球拍时,球会弹开。但是如果球从侧面击中桨,球会像被抓住一样沿着桨滑动,并且只有在到达另一端时才会弹回。我试过弄乱桨的碰撞框的尺寸,并使用时钟方法来尝试计算球与桨碰撞的时间,但都没有奏效。有人可以帮忙吗?

我的主要代码:

#include "RealBat.h"
#include <sstream>
#include <string>
#include <cstdlib>
#include <SFML/Graphics.hpp>
#include <iostream>


using namespace sf;

int windowWidth = 1024;
int windowHeight = 868;


Bat bat(windowWidth / 2, windowHeight - 50);

sf::Vector2f ballUpdate(sf::Vector2f ballPosition, int windowWidth, int windowHeight, float *velocityX, float *velocityY){
    sf::Vector2f ballPosition2 = sf::Vector2f(ballPosition.x, ballPosition.y);
    
    ballPosition2.x += *velocityX;
    ballPosition2.y += *velocityY;

    if (ballPosition2.x >= windowWidth || ballPosition2.x <= 0) {
        *velocityX *= -1.0f;
    }
    if (ballPosition2.y >= windowHeight || ballPosition2.y <= 0) {
        *velocityY *= -1.0f;
    }
    int ballBottomLeft = ballPosition2.y + 9;
    int ballRight = ballPosition2.x + 9;

    int batRight = bat.getVector().x + 100;
    
    int score = 0;

    if (ballBottomLeft >= bat.getVector().y) {
        if (ballPosition2.x >= bat.getVector().x && ballRight <= batRight) {
            std::cout << "collisionTracker" << std::endl;
            *velocityY *= -1.0f;
            score = score + 1;
        }
        else {
            score = 0;
        }

    return ballPosition2;
}       

int main()
{
    float velocityX = 0.05;
    float velocityY = 0.05;

    sf::Vector2f position = sf::Vector2f(10, 10);
    RectangleShape ball = RectangleShape();
    ball.setSize(sf::Vector2f (10, 10));
    RenderWindow window(VideoMode(windowWidth, windowHeight), "ID PONG");
    


    while (window.isOpen()) {
        Event event;
        while (window.pollEvent(event)) {
            if (event.type == Event::Closed) {
                window.close();
            }
        }
        if (Keyboard::isKeyPressed(Keyboard::Left)) {
            bat.moveLeft();
        }
        else if (Keyboard::isKeyPressed(Keyboard::Right)) {
            bat.moveRight();
        }

        bat.update();

        position = ballUpdate(position, windowWidth, windowHeight, &velocityX, &velocityY);

        ball.setPosition(position);

        window.clear(Color(148, 213, 0, 255));
        window.draw(bat.getShape());
        window.draw(ball);
        window.display();
    }
}
 

我的蝙蝠头文件:

#pragma once
#include <SFML/Graphics.hpp>

using namespace sf;

class Bat {
private:
    Vector2f position;
    RectangleShape batShape;
    float batSpeed = .3f;

public:
    Bat(float startX, float startY);
    FloatRect getPosition();
    RectangleShape getShape();
    Vector2f getVector();
    void moveLeft();
    void moveRight();
    void update();
};

我的蝙蝠 cpp:

#include "RealBat.h"

Bat::Bat(float startX, float startY)
{
    position.x = startX;
    position.y = startY;
    batShape.setSize(sf::Vector2f(100, 10));
    batShape.setPosition(position);
}

FloatRect Bat::getPosition()
{
    return batShape.getGlobalBounds();
}


RectangleShape Bat::getShape()
{
    return batShape;
}

void Bat::moveLeft()
{
    position.x -= batSpeed;
}

void Bat::moveRight()
{
    position.x += batSpeed;
}

void Bat::update()
{
    batShape.setPosition(position);
}
sf::Vector2f Bat::getVector () {
    return position;
}

【问题讨论】:

    标签: c++ oop sfml


    【解决方案1】:

    最有可能发生的情况是,在下一次循环时,球仍在球棒的边界内。 将球和球棒想象成这种可怕的 ascii 表示(+ 表示球棒,0 表示球),球刚刚击中球棒的右侧,向下和向左移动

    +--------------+
    +              +
    +              O
    +              +
    +--------------+
    

    球的 y 速度将被反转,下一次迭代将是

    +--------------+
    +             O+
    +              +
    +              +
    +--------------+
    

    这仍然在球的边界内,所以它的 y 速度将再次反转

    +--------------+
    +              +
    +            O +
    +              +
    +--------------+
    

    所以球会在球棒内上下弹跳,直到击中左手边缘。

    +--------------+
    + O O O O O O O+
    +O O O O O O O O
    +              +
    +--------------+
    

    解决此问题的一种方法是仅在球向下时反转 Y 速度,这样即使球仍在球棒内,球也会继续向上。可能通过添加:

     if (*velocityY > 0.0) {
    

    就在collisionTracker cout 调用上方,因此您在向上移动时不会得分或反弹。

    【讨论】:

      【解决方案2】:

      几年前我在制作乒乓球游戏时遇到了类似的问题。这是因为我们只检查交叉点并改变 x 轴的速度方向。因此,当它从侧面撞击时,速度会不断反转每一帧。我当时解决它的方法是检查我的球中心相对于桨的边界(侧面)的位置。因此,当球击中任何一侧时,我只需反转 y 轴上的速度方向。这样球击中了球拍,然后就离开了。

      我很确定有更好的方法可以做到这一点,但我当时只是一个初学者,这是我能想到的最好的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-21
        • 1970-01-01
        • 2020-02-11
        • 2010-11-22
        • 1970-01-01
        相关资源
        最近更新 更多