Обнаружено столкновение ошибок - PullRequest
2 голосов
/ 17 января 2011

У меня возникла проблема, что всякий раз, когда я касаюсь земли, моя скорость устанавливается на 0. Это происходит потому, что моя функция, которая выталкивает меня, толкает меня точно к краю. Поэтому, когда я делю на высоту блока, он все еще думает, что я в этом блоке. Это также происходит, когда я прыгаю к самой правой стене.

пример: там есть блок с координатами 0,720 и мой у = 723

723/5 = 144 (округлено в меньшую сторону)

тогда меня выталкивают на 720. но потом, когда я делю на высоту блока, он все еще думает, что касаюсь блока на 720, пока не скажем 725

720/5 = 144

Как я могу это исправить, я имею в виду, что я знаю, в чем проблема, но я не вижу способа ее исправить.

Также, когда я не прыгаю и точно на правом краю уровня, я могу пройти через стену, пройдя вправо, но как только я прыгаю, обнаруживается обнаружение столкновений.

Я понятия не имею, почему и как возникает эта последняя проблема, может кто-нибудь взглянуть и посмотреть, что происходит.

Код:

void DoCollisions()
{
    onGround = false;
    Position.Y += Velocity.Y;
    Vector2 tileCollision = GetTileCollision();
    if (tileCollision.X != -1 || tileCollision.Y != -1)
    {
        onGround = true;
        Vector2 collisionDepth = CollisionRectangle.DepthIntersection(
            new Rectangle(
                tileCollision.X * World.tileEngine.TileWidth,
                tileCollision.Y * World.tileEngine.TileHeight,
                World.tileEngine.TileWidth,
                World.tileEngine.TileHeight
            )
        );
        Velocity.Y = 0;
        Position.Y += collisionDepth.Y;

    }

    Position.X += Velocity.X;
    tileCollision = GetTileCollision();
    if (tileCollision.X != -1 || tileCollision.Y != -1)
    {
        Vector2 collisionDepth = CollisionRectangle.DepthIntersection(
            new Rectangle(
                tileCollision.X * World.tileEngine.TileWidth,
                tileCollision.Y * World.tileEngine.TileHeight,
                World.tileEngine.TileWidth,
                World.tileEngine.TileHeight
            )
        );
        Velocity.X = 0;
        Position.X += collisionDepth.X;

    }
}

Vector2 GetTileCollision()
{
    int topLeftTileX = (int)(CollisionRectangle.TopLeft.X / World.tileEngine.TileWidth);
    int topLeftTileY = (int)(CollisionRectangle.TopLeft.Y / World.tileEngine.TileHeight);
    int BottomRightTileX = (int)(CollisionRectangle.DownRight.X / World.tileEngine.TileWidth);
    int BottomRightTileY = (int)(CollisionRectangle.DownRight.Y / World.tileEngine.TileHeight);

    for (int i = topLeftTileX; i <= BottomRightTileX; i++)
    {
        for (int j = topLeftTileY; j <= BottomRightTileY; j++)
        {
            if (World.tileEngine.TileIsSolid(i, j))
            {
                return new Vector2(i,j);
            }
        }
    }

    return new Vector2(-1,-1);
}

Ответы [ 3 ]

4 голосов
/ 17 января 2011

Ваша стратегия реализации движется до конца, а затем извлекается, если столкновение в значительной степени гарантирует ошибку, потому что нет простого способа убедиться, что код выброса отбрасывает вас обратно в точку, где вы должны столкнулись. Часто он выбрасывается в другом направлении, отсюда и ошибки.

Это не только вы: профессионалы тоже сталкиваются с этой проблемой. См. Tasvideos.org для коллекции ошибок столкновений в Super Mario Bros играх, которые вызваны этой стратегией move-then-eject .

Так что не делай этого. Определите точную точку столкновения и двигайтесь только так далеко. В наши дни компьютеры достаточно быстрые.


Вы попросили рекомендовать метод для столкновения персонажа с тайлами. Ну, начнем с рассмотрения одного шага движения вашего персонажа, скажем ( dx , dy ):

alt text

Я преувеличил расстояние, чтобы сделать пример интересным: обычно вы ожидаете, что шаги движения будут довольно малы по сравнению с размером плитки.

Персонаж потенциально касается всех тайлов, которые пересекают протяженный путь хитбокса персонажа, показанный заштрихованным ниже. Используйте подход по линиям алгоритма линии Ву , чтобы найти эти плитки.

alt text

Сортируйте плитки по порядку, когда они поражены:

alt text

Персонаж сталкивается с плиткой с наименьшим номером, которая является твердой.

0 голосов
/ 17 января 2011

Для тех, кто справляется с той же проблемой, что и я, мне удалось это исправить, и я подумал, что ссылка на вставку с моим кодом будет полезна: http://pastebin.com/t8PdtDEK

Добавил это в мой код:

        if (previousPos.X == Position.X)
            Velocity.X = 0;
        if (previousPos.Y == Position.Y)
            Velocity.Y = 0;

и добавил это к моему методу получения коллизий:

        if (CollisionRectangle.DownRight.Y % World.tileEngine.TileHeight == 0)
            BottomRightTileY -= 1;
        if (CollisionRectangle.DownRight.X % World.tileEngine.TileWidth == 0)
            BottomRightTileX -= 1;

Что он делает, если его точно по краю вычитает 1, поэтому он не добавляет эту плитку.

Такжессылка на pastebin не содержит интерполяции, чтобы убедиться, что объект не движется быстро.

Спасибо всем за помощь!

0 голосов
/ 17 января 2011

Вы пытались использовать скорректированную координату y?Переместитесь на один только вверх для расчета.

...