0

I'm creating a 2D topdown shooter game with Java Swing in which I want circular hitboxes for my player and enemies as well as projectiles. For hit detection I need to figure out if there is an intersection between a projtile and a Sprite (player or enemy). My issue is that Ellipse2D's intersect function (that takes a position a width and height) creates a Rectangle out of the arguments. In its description it advises using Area for high precision and I was hoping it had an intersect function for any shape but that also casts its argument to a Rectangle.
Here's the jist of my Sprite object:

public class Sprite {
    protected float worldX;
    protected float worldY;
    protected float drawX;
    protected float drawY;
    protected int width;
    protected int height;
    protected Image image;
    ...
}

In essence I'm storing their x and y coordinates as well as their width and height.(drawX and drawY are only used for rendering)

Is there a build-in method (preferably in Swing) to intersect Ellipses with other shapes (specifically other Ellipses and Rectangles) or is there no better option then implementing these by hand?

  • For [example](https://stackoverflow.com/questions/20927189/detecting-collision-of-two-sprites-that-can-rotate/20928531#20928531) – MadProgrammer Mar 10 '22 at 20:18

1 Answers1

1

With a simple modification to the answer form Detecting collision of two sprites that can rotate

You can end up with something like...

enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Ellipse2D rect01;
        private Rectangle rect02;

        private int angle = 0;

        public TestPane() {

            rect01 = new Ellipse2D.Double(0, 0, 200, 50);
            rect02 = new Rectangle(0, 0, 100, 100);

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angle++;
                    repaint();
                }
            });
            timer.start();

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(250, 250);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int width = getWidth();
            int height = getHeight();

            AffineTransform at = new AffineTransform();

            int center = width / 2;

            int x = center + (center - rect01.getBounds().width) / 2;
            int y = (height - rect01.getBounds().height) / 2;
            at.translate(x, y);
            at.rotate(Math.toRadians(angle), rect01.getBounds().width / 2, rect01.getBounds().height / 2);
            GeneralPath path1 = new GeneralPath();
            path1.append(rect01.getPathIterator(at), true);
            g2d.fill(path1);

            g2d.setColor(Color.BLUE);
            g2d.draw(path1.getBounds());

            at = new AffineTransform();
            x = (center - rect02.width) / 2;
            y = (height - rect02.height) / 2;
            at.translate(x, y);
            at.rotate(Math.toRadians(-angle), rect02.width / 2, rect02.height / 2);
            GeneralPath path2 = new GeneralPath();
            path2.append(rect02.getPathIterator(at), true);
            g2d.fill(path2);

            g2d.setColor(Color.BLUE);
            g2d.draw(path2.getBounds());

            Area a1 = new Area(path1);
            Area a2 = new Area(path2);
            a2.intersect(a1);
            if (!a2.isEmpty()) {
                g2d.setColor(Color.RED);
                g2d.fill(a2);
            }

            g2d.dispose();
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I'm not sure if this is applicable to my problem. While this does work well graphically I'm just looking for a boolean result if my two shapes intersect. I'd like to use a built-in `intersects` function for that, but I only found versions that handle my second object as a Rectangle, even thought I'm looking for Ellipse vs Ellipse collision checks (or possibly Circle vs Circle collision) – yeah_man_i_get_it Mar 11 '22 at 15:23
  • Did you look at the part around `if (!a2.isEmpty()) {`? – MadProgrammer Mar 11 '22 at 21:00