Monogame Basic Collision Detection не работает

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

Таким образом, мое движение за моего игрока находится в моем классе Player.cs, и в этом классе содержится метод Update(), который вызывается в моем основном игровом цикле в Game1.cs. Я настроил его так, чтобы когда хитбокс моего игрока "Прямоугольный хитбокс"; пересекается с плиткой столкновения, она переключает логическое значение с именем 'inAir' на false. Когда это логическое значение ложно, сила тяжести должна быть равна нулю. Код в методе Update моего Player.cs выглядит следующим образом:

public void Update(GameTime gameTime) {

    //In my constructor for the Player class
    //Position is set equal to a new Vector2(0, 0)
    //Velocity is set equal to Vector2.Zero
    //Acceleration is set equal to a new Vector2(0, 100.0f);

    float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

    Velocity += Acceleration * deltaTime;
    Position += Velocity * deltaTime;

    HitBox = new Rectangle(new Point((int)Position.X, (int)Position.Y), new Point(Width, Height));

    foreach (SpriteTile t in gameMap.CollisionSprites) {
        if (HitBox.Intersects(t.Bounds))
            inAir = false;
        else if (!HitBox.Intersects(t.Bounds))
            inAir = true;
    }

    if (!inAir) {
        Velocity.Y = -Acceleration.Y * deltaTime;
    }

}

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

В моем классе Player.cs выше, объект SpriteTile хранит только 2 вещи, Texture2D и Position, которые предопределены, когда я загружаю столкновения из моего Tiled Collision Layer.

Однако метод Bounds просто возвращает прямоугольник, показывающий границы текущей плитки. Он определяется следующим образом:

public Rectangle Bounds {
    get {
        return new Rectangle(
            (int)Position.X,
            (int)Position.Y,
            Texture.Width,
            Texture.Height);
    }
}

Загадочная часть всего этого для меня заключается в том, что когда я добавил простой отладочный код для рисования этих значений на экране и проверки работоспособности столкновения, я получил следующее:

В соответствии с ограничивающими рамками, которые я рисую, он должен пересекаться, поэтому останавливать падение. Даже если я неправильно понял код ответа на столкновение, булево значение 'inAir' должно быть установлено в true. (Да, потому что строка выводится на экран следующим образом: "Пересекается: " +!Player.inAir, означая, что если пересечение будет иметь место, оно будет отображаться на экране true.

Если потребуется дополнительная информация о моем коде, дайте мне знать, и я отредактирую сообщение и предоставлю его.

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

1 ответ

Решение

Скорее всего, проблема связана с тем, как во время обновления определяется "inAir". Согласно предоставленному циклу, только последний спрайт в столкновении CollisionSprites может вызвать inAir, чтобы быть ложным.

Допустим, gameMap.CollisionSprites содержит 2 спрайта. Первый спрайт, с которым вы пересекаетесь. Второе, что вы не делаете. На первом проходе цикла HitBox.Intersects(t.Bounds) Значение true, в результате чего inAir будет установлено в значение false, как вы ожидаете Однако цикл не заканчивается и HitBox.Intersects(t.Bounds) запускается на втором спрайте, который имеет значение false, и устанавливает inAir в значение false.

Есть несколько способов исправить это. Вот один из способов:

inAir = true; // assume you're in the air
foreach (SpriteTile t in gameMap.CollisionSprites) {
    if (HitBox.Intersects(t.Bounds))
    {
        inAir = false; 
        break; // you've collided, no reason to check any others
    }
}

Упрощено с использованием методов расширения Linq...

inAir = !gameMap.CollisionSprites.Any(t => HitBox.Intersects(t.Bounds));

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

Другие вопросы по тегам