当前位置: 首页 > 知识库问答 >
问题:

轴独立碰撞

龙弘盛
2023-03-14

我已经在我的游戏中实现了tilemap碰撞,它起作用了,但是当我在一个轴上碰撞而试图在另一个轴上移动时,问题就来了。我不能沿着墙滑行。

在player.cpp中

void Player::update(float delta, std::vector<Tile>& tiles) {
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Joystick::getAxisPosition(0, sf::Joystick::Y) < -20) {
        newPos.y -= speed * delta;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Joystick::getAxisPosition(0, sf::Joystick::X) < -20) {
        newPos.x -= speed * delta;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Joystick::getAxisPosition(0, sf::Joystick::Y) > 20) {
        newPos.y += speed * delta;
    }
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right) || sf::Joystick::getAxisPosition(0, sf::Joystick::X) > 20) {
        newPos.x += speed * delta;
    }

    sf::Vector2f oldPos = sprite.getPosition();
    move(delta, newPos);

    for (int i = 0; i < tiles.size(); i++) {
        if (Collision::PixelPerfectTest(sprite, tiles[i].sprite) && tiles[i].collision) {
            sprite.setPosition(oldPos);
            newPos = oldPos;
        }
    }
}

void Player::move(float delta, sf::Vector2f position) {
    sprite.setPosition(position);
}

在Collision.cpp中

bool PixelPerfectTest(const sf::Sprite& Object1, const sf::Sprite& Object2, sf::Uint8 AlphaLimit) {
        sf::FloatRect Intersection;
        if (Object1.getGlobalBounds().intersects(Object2.getGlobalBounds(), Intersection)) {
            sf::IntRect O1SubRect = Object1.getTextureRect();
            sf::IntRect O2SubRect = Object2.getTextureRect();

            sf::Uint8* mask1 = Bitmasks.GetMask(Object1.getTexture());
            sf::Uint8* mask2 = Bitmasks.GetMask(Object2.getTexture());

            // Loop through our pixels
            for (int i = Intersection.left; i < Intersection.left + Intersection.width; i++) {
                for (int j = Intersection.top; j < Intersection.top + Intersection.height; j++) {

                    sf::Vector2f o1v = Object1.getInverseTransform().transformPoint(i, j);
                    sf::Vector2f o2v = Object2.getInverseTransform().transformPoint(i, j);

                    // Make sure pixels fall within the sprite's subrect
                    if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 &&
                        o1v.x < O1SubRect.width && o1v.y < O1SubRect.height &&
                        o2v.x < O2SubRect.width && o2v.y < O2SubRect.height) {

                        if (Bitmasks.GetPixel(mask1, Object1.getTexture(), (int)(o1v.x) + O1SubRect.left, (int)(o1v.y) + O1SubRect.top) > AlphaLimit &&
                            Bitmasks.GetPixel(mask2, Object2.getTexture(), (int)(o2v.x) + O2SubRect.left, (int)(o2v.y) + O2SubRect.top) > AlphaLimit)
                            return true;

                    }
                }
            }
        }
        return false;
    }

共有1个答案

凌意
2023-03-14

那是因为你的碰撞测试要么全有要么全无。我会做额外的碰撞测试,看看x或y新位置是否有效,比如:

if (tiles[i].collision && Collision::PixelPerfectTest(sprite, tiles[i].sprite))
{
    sf::Vector2f checkPosX = newPos;
    sf::Vector2f checkPosY = newPos;

    checkPosX.y = oldPos.y;
    checkPosY.x = oldPos.x;

    sprite.setPosition(checkPosX);

    if (!Collision::PixelPerfectTest(sprite, tiles[i].sprite))
    {
        newPos = checkPosX;
    }
    else
    {
        sprite.setPosition(checkPosY);

        if (!Collision::PixelPerfectTest(sprite, tiles[i].sprite))
        {
            newPos = checkPosY;
        }
        else
        {
            sprite.setPosition(oldPos);
            newPos = oldPos;
        }
    }
}

顺便说一句,如果您首先测试tiles[i].collistion,您将跳过更昂贵的PixelPerfectTest()非冲突tiles测试,这是因为表达式短路。

 类似资料:
  • 我的任务是比较一些当前时期的日志和旧的日志。例如——本周日志和前一周日志。但是当我创建这样的第二个轴时 我有一个空的部分,因为我所有的xAx都是“时间”类型的,并且点的时间不一样(这是绝对正常的行为)。我有这种情况 但是我需要制作独立的轴,例如:顶部轴开始于30sep,结束于3oct底部轴开始于7oxt,结束于10oct,它们的长度都相同 我试着创造这样的斧头 但是如果没有“ticks”属性,我会

  • 创建验证 任何时候,都可以直接使用think\Validate类而不需要定义验证器类进行独立的验证操作,例如: $validate = Validate::make([ 'name' => 'require|max:25', 'email' => 'email' ]); $data = [ 'name' => 'thinkphp', 'email' => 't

  • 工人出现在图片上。为了运行我的代码,我使用了以下命令:

  • 开发者可以在脱离Spring容器的情况下利用RepositoryFactory来使用Spring Data repository(比如在CDI环境下),但仍然需要将某些Spring的依赖包加到classpath中。 Example 14. Standalone usage of repository factory(独立使用) RepositoryFactorySupport factory =

  • 问题内容: 我试图从另一个python脚本访问我的Django(v1.10)应用程序数据库,但遇到了一些麻烦。 这是我的文件和文件夹结构: 根据Django的文档,我看起来像这样: 但它会生成运行时错误: 我应该注意,我的INSTALLED_APPS列表包含了它的最后一个元素。 相反,如果我尝试通过这样的配置: 我得到: 如果我进行编辑和添加,LOGGING_CONFIG=None则会遇到另一个有

  • 独立部署即为在后端运行程序,让程序跑在后台。 linux 在 linux 下面部署,我们可以利用 nohup 命令,把应用部署在后端,如下所示: nohup ./beepkg & 这样你的应用就跑在了 Linux 系统的守护进程 Windows 在 Windows 系统中,设置开机自动,后台运行,有如下几种方式: 制作 bat 文件,放在“启动”里面 制作成服务