Обнаружение столкновений Java для повернутых прямоугольников?

#java #rotation #collision-detection #rectangles

#java #вращение #обнаружение столкновений #прямоугольники

Вопрос:

Я пишу свою первую java-игру и пока:

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

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

Приветствуется любая помощь или предложения.

Вот что я использую, чтобы увидеть, столкнется ли оно при перемещении по оси x:

 public boolean detectCollisionX(int id, double xMove, double rectXco, double rectYco, int width, int height)
{
    boolean valid=true;
    //create the shape of the object that is moving.
    Rectangle enemyRectangleX=new Rectangle((int)(rectXco xMove)-enemySpacing,(int)rectYco-enemySpacing,width enemySpacing*2,height enemySpacing*2);
    if (rectXco xMove<0 || rectXco xMove>(areaWidth-width))
    {
        valid=false;
    }
    if(enemyNumber>0)
    {
        for (int x=0; x<=enemyNumber; x  )
        {
            if (x!=id)
            {
                //enemies and other collidable objects will be stored in collisionObjects[x] as rectangles.
                if (enemyRectangleX.intersects(collisionObjects[x])==true)
                {
                    valid=false;
                }
            }
        }
    }
    return valid;
}
  

Комментарии:

1. Можете ли вы привести краткий пример кода того, что вы делаете?

2. @Vincent Ramhanie Я отредактировал свой пост.

3. Нужно еще немного отредактировать это … мне трудно читать код … посмотрите, как выполнить Markdown в stackoverflow

4. @WarmWaffles Да, теперь это должно выглядеть лучше, извините.

Ответ №1:

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

Предположим, что у вас есть два объекта a и b, вы можете вращать их следующим образом:

   AffineTransform af = new AffineTransform();
  af.rotate(Math.PI/4, ax, ay);//rotate 45 degrees around ax, ay

  AffineTransform bf = new AffineTransform();
  bf.rotate(Math.PI/4, bx, by);//rotate 45 degrees around bx, by

  ra = a.createTransformedArea(af);//ra is the rotated a, a is unchanged
  rb = b.createTransformedArea(bf);//rb is the rotated b, b is unchanged

  if(ra.intersects(rb)){
    //true if intersected after rotation
  }
  

и у вас есть исходные объекты на всякий случай, если это то, что вы хотите. Использование AffineTransform позволяет легко комбинировать преобразования, инвертировать их и т.д.

Комментарии:

1. Ого! Я попробую это, и если это сработает, это было бы потрясающе! Итак, a и b — это прямоугольники, которые я хочу повернуть? Я думаю, мне нужно вместо этого преобразовать их в тип area. t

2. Вы можете создавать области из фигур. Итак, если ваши объекты являются типами фигур, вы можете использовать: Область a = новая область (myshape);

3. По-видимому, я не могу использовать .intersects () в двух областях = (. Я попытаюсь разобраться…

4. @Dominic Попробуйте ra.intersects(rb.getBounds()) вместо этого.

5. Get bounds возвращает прямоугольник, который не повернут, но размером с ограничивающую область. Чтобы проверить наличие столкновения, используйте if(area1.intersects(area2.getBounds()) amp;amp; area2.intersects(area1.getBounds()))…