【问题标题】:2d tilemap collision for SFMLSFML 的 2d tilemap 碰撞
【发布时间】:2018-09-18 07:08:18
【问题描述】:

我目前正在使用 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 碰撞或 y 碰撞,并且即使玩家与实体对齐也会重置玩家的位置。

所以我想我的主要问题是:如何以更好的方式将垂直碰撞与水平碰撞分开,或者是否有另一种进行瓷砖碰撞的方法,允许玩家在保持两个方向的同时沿着墙壁滑动?

【问题讨论】:

    标签: c++ collision sfml


    【解决方案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);
        }
    

    这种方法确实有缺陷,但我认为它很容易理解。

    【讨论】:

    • 谢谢,它引导我朝着正确的方向前进。我确实必须添加一些布尔变量来检查是否发生碰撞,如果没有发生碰撞,则将玩家移动到新位置。
    猜你喜欢
    • 2014-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    相关资源
    最近更新 更多