C++;SFML冲突不准确 我在用C++制作一个带有SFML的2D游戏,我遇到了一个碰撞问题。我有一个播放器和一张用瓷砖做成的地图。不起作用的是我的碰撞检测不准确。当我向上移动播放器,然后向下移动到瓷砖上时,结果会不同

C++;SFML冲突不准确 我在用C++制作一个带有SFML的2D游戏,我遇到了一个碰撞问题。我有一个播放器和一张用瓷砖做成的地图。不起作用的是我的碰撞检测不准确。当我向上移动播放器,然后向下移动到瓷砖上时,结果会不同,c++,collision,sfml,C++,Collision,Sfml,我知道这个问题的根源可能是使用帧间的增量时间来计算球员的移动,所以它不是常数。但它平滑运动,所以我不知道如何做它的其他方式。我尝试使用恒定速度值,使碰撞完全准确-速度必须非常低,我对此不满意 void Player::move() { sf::Vector2f offsetVec; if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) offsetVec += sf::Vector2f(0, -10); if

我知道这个问题的根源可能是使用帧间的增量时间来计算球员的移动,所以它不是常数。但它平滑运动,所以我不知道如何做它的其他方式。我尝试使用恒定速度值,使碰撞完全准确-速度必须非常低,我对此不满意

void Player::move() {
    sf::Vector2f offsetVec;

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
        offsetVec += sf::Vector2f(0, -10);

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
        offsetVec += sf::Vector2f(0, 10);

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
        offsetVec += sf::Vector2f(-10, 0);

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
        offsetVec += sf::Vector2f(10, 0);

    this->moveVec += offsetVec;
}

void Player::update(float dt, Map *map) {
    sf::Vector2f offset = sf::Vector2f(this->moveVec.x * this->playerSpeed * dt,
                                       this->moveVec.y * this->playerSpeed * dt);
    sf::Sprite futurePos = this->sprite;
    futurePos.move(offset);
    if (map->isCollideable(this->pos.x, this->pos.y, futurePos.getGlobalBounds())) {
        this->moveVec = sf::Vector2f(0, 0);
        return;
    }
    this->sprite.move(offset);
    this->pos += offset;
    this->moveVec = sf::Vector2f(0, 0);
    return;
}
玩家位置更新中我创建了未来的精灵对象,即应用移动后的对象,以获取其边界并将其传递给碰撞检查器。对于碰撞检查器我还传递了玩家位置,因为我的地图存储在二维平铺指针数组中,所以我只在玩家范围内检查这些

bool Map::isCollideable(float x, float y, const sf::FloatRect &playerBounds) {
    int startX = int(x) / Storage::tileSize;
    int startY = int(y) / Storage::tileSize;
    Tile *tile;
    for (int i = startX - 10; i <= startX + 10; ++i) {
        for (int j = startY - 10; j <= startY + 10; ++j) {
            if (i >= 0 && j >= 0) {
                tile = getTile(i, j);
                if (tile != nullptr && playerBounds.intersects(tile->getGlobalBounds()))
                    return true;
            }
        }
    }
    return false;
}

我还不得不对iscollidable方法做了一些修改,这样它就可以接受sf::Sprite和offset vector,这样它就可以自己计算边界。

这只是一个想法,但是当你将浮点x和y输入整数,然后将它们除以时,碰撞检测可能会有一些不准确的地方。这可能会导致问题,因为浮点中的一些数据可能会丢失。如果浮点数为3.5或3.3或3.9,则它将变为3,从而放弃碰撞计算

当玩家与瓷砖碰撞时,您应该计算穿透力,即“玩家进入瓷砖的程度”的值。当你有这个值时,把你的播放器往回推一推。

我只会将x、y浮动到int,以计算我应该在播放器周围检查哪些分片。碰撞计算是使用浮点值进行的。虽然你可能检查了错误的磁贴,但是因为这个想法,我实际上做了其他操作,但是多亏了你的想法。我没有想到如何获得smfl穿透值(这会很复杂,因为我需要专门检查每一侧)。虽然我对偏移向量做了一些操作,但我知道前一个会产生碰撞。
void Player::update(float dt, Map *map) {
    int repeats = 0;
    sf::Vector2f offset = sf::Vector2f(this->moveVec.x * this->playerSpeed * dt,
                                       this->moveVec.y * this->playerSpeed * dt);
    sf::Sprite futurePos = this->sprite;
    while (map->isCollideable(this->pos.x, this->pos.y, futurePos, offset)) {
        offset = 0.7f * offset;
        repeats++;
        if (repeats > 5) {
            this->moveVec = sf::Vector2f(0, 0);
            return;
        }
    }
    this->sprite.move(offset);
    this->pos += offset;
    this->moveVec = sf::Vector2f(0, 0);
    return;
}