Обнаружение столкновений между прямоугольниками (без перекрытия) - 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 ответа:
Ваш алгоритм столкновения кажется многословным, но правильным (многословным, потому что min из x, X+ width всегда просто x, поскольку ширина должна быть >= 0, и обратное верно для max).
Рассматривали ли вы возможность того, что это проблема точности с плавающей точкой? Например, если вы добавляете 1 к числу fp, а затем удаляете 1 из результата, вы не гарантированно вернетесь к исходному значению. Вы можете быть немного больше или меньше, поскольку промежуточный результат не может быть представлен в виде поплавка.
Мой любимый пример:.1f + .2f > .3f
Я, наконец, нашел хорошее решение, все благодаря следующей ссылке: на перекрытии игрок застревает libGDX прямоугольник.
В основном я должен создать "поддельный" ход, чтобы увидеть, столкнется ли объект со стеной. Если происходит столкновение, я просто останавливаю объект и не выполняю новое движение.
Спасибо всем за помощь :)!! Это очень ценится!!