SFML的2d tilemap冲突

时间:2018-04-08 22:53:59

标签: c++ collision sfml

我目前正在使用SFML进行2D RPG游戏,我正试图让玩家与某些牌块发生碰撞。我已经达到了玩家可以与我想要的瓷砖碰撞以及沿着墙壁滑动以下代码的程度:

sf::Vector2f movement(0.f, 0.f);
if (isMovingUp)
    movement.y -= 1.f;
if (isMovingDown)
    movement.y += 1.f;
if (isMovingLeft)
    movement.x -= 1.f;
if (isMovingRight)
    movement.x += 1.f;

sf::Vector2f oldpos = Player.getPosition();
sf::Vector2f newpos = Player.getPosition() + movement*speed*dt.asSeconds();
Player.setPosition(newpos); // the player is an sf::sprite that is 16*24px

for (int i = 0; i < tiler.solids.size(); i++) // each solid is an sf::FloatRect that is 16*16px
{
    if (Player.getPosition().x + 16 >= tiler.solids[i].left && Player.getPosition().x <= tiler.solids[i].left + tiler.solids[i].width && Player.getPosition().y + 24 >= tiler.solids[i].top && Player.getPosition().y <= tiler.solids[i].top + tiler.solids[i].height) // if the player is touching the tile
    {
        Player.setPosition(oldpos);
    }
}

它基本上做的是迭代每个实体并测试玩家是否与其中任何一个相交。如果有一个交叉点,当没有碰撞时,玩家将返回到之前的位置。

我遇到的主要问题是,当我同时按下两个方向时(例如,在向右和向上移动时向右碰撞墙壁),玩家会因为重置x和y坐标而卡住。大多数代码都基于This question。提出问题的人也有同样的问题。对答案的最后评论表明他们尝试将垂直与水平运动分开。我在我的代码中尝试了但是这没有用,因为它基本上测试是否存在x-collision或y-collision并且即使玩家与实体一致也会重置玩家的位置。

所以我猜我的主要问题是:如何以更好的方式将垂直与水平碰撞分开?还是有另一种方法可以让玩家在按住两个方向的同时沿着墙壁滑动吗?

1 个答案:

答案 0 :(得分:1)

你想要做的是单独测试两个轴上的碰撞。这意味着您可以保护播放器的当前位置,然后计算两个边界框。其中一个是玩家的边界框,其中添加了水平偏移,另一个添加了垂直偏移。

sf::FloatRect oldBounds = Player.getPosition();

sf::FloatRect newBoundsH = (oldBounds.left + movement.x *speed*dt.asSeconds(), oldBounds.top, oldBounds.width, oldBounds.height);

sf::FloatRect newBoundsV = (oldBounds.left, oldBounds.top + movement.y *speed*dt.asSeconds(), oldBounds.width, oldBounds.height);

所以你可以写:

    // Test horizontal collision.
    if(tiler.intersects(newBoundsH)){
        Player.setPosition(oldpos.x, Player.getPositions().y);
    }

// Test vertical collision.
    if(tiler.intersects(newBoundsV)){
        Player.setPosition(Player.getPositions().x, oldpos.y);
    }

这种方法绝对存在缺陷,但我认为这很容易理解。