Обнаружение столкновений между прямоугольниками (без перекрытия) - libgdx


Я был на этом в течение 2-3 недель, и я все еще не могу управлять, чтобы иметь правильное обнаружение столкновений. Я создал лабиринт, используя прямоугольники. Я хочу, чтобы мой объект (который находится в прямоугольнике) останавливался всякий раз, когда мой объект сталкивается с любой стеной, и был в состоянии двигаться в любом месте (или скользить вниз по стене). Мои стены (прямоугольники) имеют отрицательные координаты, такие как:

shapeRenderer.rect(0.9f, 12, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); //NORTH
shapeRenderer.rect(1, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // WEST
shapeRenderer.rect(2, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // EAST
shapeRenderer.rect(0.9f, 11, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); // SOUTH

В настоящее время я использую метод перекрытий, который я нашел в SO. Вот метод, который находится в моем CollisionManager класс:

private boolean overlaps (Rectangle collision, Rectangle wall) {
    return Math.min(collision.x, collision.x + collision.width) 
        < Math.max(wall.x, wall.x + wall.width) 
    && Math.max(collision.x, collision.x + collision.width) 
        > Math.min(wall.x, wall.x + wall.width) 
    && Math.min(collision.y, collision.y + collision.height) 
        < Math.max(wall.y, wall.y + wall.height) 
    && Math.max(collision.y, collision.y + collision.height) 
        > Math.min(wall.y, wall.y + wall.height);
}

У меня есть функция, которая сохраняет все перемещения позиции, сделанные объектом. Таким образом, когда происходит столкновение, объект восстанавливает предыдущий ход перед последним ходом (так как последний ход-это когда произошло столкновение) (пример ниже):

private void overlapsTop(Entity object, Rectangle wall){

    Rectangle r = new Rectangle();
    if(spritePositions.size() != 0){
        r = spritePositions.get(spritePositions.size()-1);
    }
    object.update(r.x, r.y, r.width, r.height);
    object.getObject().setBounds(r.x, r.y, r.width, r.height);
    spritePositions.clear();
}

Дополнительная информация: я перемещаю свой объект следующим образом:

public void moveRight(){
    position.x += 1f;
    update();
}

public void update(){

      boundingRectangle.set(position.x, position.y, object.getWidth(), object.getHeight());
}

Где я застрял - это моя функция перекрытия (та, которую я нашел в SO). Это работает в большинстве случаев; но, например, если объект движется вблизи стены на справа и касается его, функция возвращает true и все выполняется. Но предположим, что если я скольжу вдоль стены и двигаюсь прямо вниз, а стен нет, объект останавливается в одной точке, потому что он обнаруживает столкновение между нижней частью объекта и верхней частью стены (когда их нет) и столкновение между правой частью объекта и левой частью стены.

Я пытаюсь найти другое решение для этого. Я просто хочу, чтобы мой объект остановился у любой стены и мог двигаться. (или сползите вниз по стене), не подозревая, что может произойти столкновение там, где поблизости нет стен. Я чувствую, что очень близок к решению, но мне понадобится немного дополнительной помощи.

Обновить

Я обновил функцию moveRight и функцию update. @Эдриан шум и @Матфей Марк Миллер, я сделал все теперь с целочисленное значение (смысл, а не 0.01, ф, я использую 1-ый этаж).

Таким образом, следующий код, который я использую для перемещения объекта, выглядит следующим образом: это:
if(Gdx.input.isKeyPressed(Keys.RIGHT)){

                 if(collisionManager.canSpriteNotMoveRight(object)){
                     object.stopGoingRight();
                 }else{
                     object.moveRight();
                 }
             }

В моем классе collisionManager функция stopGoingRight имеет следующий вид:

public void stopGoingRight(){
    position.x -= 1f;
    update();
}

Пока все идет хорошо. Когда объект сталкивается со стеной, он останавливается и отскакивает назад. Это хорошо. Но у меня есть еще одна проблема (которая раздражает), которую я постараюсь описать как можно лучше. Если, например, я продолжаю перемещать объект вверх к стене, объект будет много раз отскакивать от этой стены; если я перестану нажимать клавишу вверх, объект иногда останется застрял в стене. Таким образом, когда я нажимаю клавишу вниз, она будет идти вверх, а не вниз (или если я нажимаю влево, объект будет идти вправо, а не влево), потому что функция перекрытия выполняется (так как и объект, и стена пересекаются).

Есть ли у меня способ решить эту проблему? Похоже, что Libgdx не очень хорошо подходит для такого типа обнаружения столкновений, но я просто глубоко погружен в построение своей игры прямо сейчас.
2 9

2 ответа:

Ваш алгоритм столкновения кажется многословным, но правильным (многословным, потому что min из x, X+ width всегда просто x, поскольку ширина должна быть >= 0, и обратное верно для max).

Рассматривали ли вы возможность того, что это проблема точности с плавающей точкой? Например, если вы добавляете 1 к числу fp, а затем удаляете 1 из результата, вы не гарантированно вернетесь к исходному значению. Вы можете быть немного больше или меньше, поскольку промежуточный результат не может быть представлен в виде поплавка.

Мой любимый пример:.1f + .2f > .3f

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

В основном я должен создать "поддельный" ход, чтобы увидеть, столкнется ли объект со стеной. Если происходит столкновение, я просто останавливаю объект и не выполняю новое движение.

Спасибо всем за помощь :)!! Это очень ценится!!