Java 检测可旋转的两个精灵的碰撞

Java 检测可旋转的两个精灵的碰撞,java,sprite,collision,bounding-box,Java,Sprite,Collision,Bounding Box,我在2D Java游戏中遇到碰撞检测问题 通常,我要做的是为可能与其他对象碰撞的对象创建一个getBounds()方法。此方法将返回一个新矩形(x,y,width,height),其中x和y是精灵左上角的坐标,width和height是精灵的宽度和高度 但在我目前正在开发的游戏中,有一个由用户控制的“坦克”。只要玩家按住左或右箭头按钮之一,该坦克的精灵就会旋转。换句话说,它可以旋转到任何角度。坦克的精灵是一个长方形 所以在这种情况下,我不能简单地做我一直在做的事情 我如何检测与这种精灵的碰撞?

我在2D Java游戏中遇到碰撞检测问题

通常,我要做的是为可能与其他对象碰撞的对象创建一个getBounds()方法。此方法将返回一个
新矩形(x,y,width,height)
,其中
x
y
是精灵左上角的坐标,
width
height
是精灵的宽度和高度

但在我目前正在开发的游戏中,有一个由用户控制的“坦克”。只要玩家按住左或右箭头按钮之一,该坦克的精灵就会旋转。换句话说,它可以旋转到任何角度。坦克的精灵是一个长方形

所以在这种情况下,我不能简单地做我一直在做的事情

我如何检测与这种精灵的碰撞?
谢谢

如果将坦克可能遇到的所有对象都保存在ArrayList中,并在单独的线程中的循环中使用for语句来确定坦克是否碰到了什么东西,该怎么办。例如,为每个对象创建一个类,比如class Wall(),并保持x、y变量可用。将墙()放入ArrayList,在本例中为tanks。然后在for循环中,在while循环中:EC

while(true) {
    for(int i = 0; i < tanks.size(); i++) {
         //Do the code to determine if the tank has hit something.
         if(tanks.get(i).x => tank.x) //Do whatever
    }
}

当然,再次调整此if()以满足您的需要

如果将坦克可能遇到的所有对象保留在ArrayList中,并在单独的线程中的循环中简单地使用for语句来确定坦克是否撞到了什么东西,该怎么办。例如,为每个对象创建一个类,比如class Wall(),并保持x、y变量可用。将墙()放入ArrayList,在本例中为tanks。然后在for循环中,在while循环中:EC

while(true) {
    for(int i = 0; i < tanks.size(); i++) {
         //Do the code to determine if the tank has hit something.
         if(tanks.get(i).x => tank.x) //Do whatever
    }
}

当然,再次调整if()以满足您的需要

您可以使用多边形而不是矩形


然而,这将手动计算(x,y)角。有可能通过旋转矩形来构造形状,但这至少是可行的。它有一个
getBounds()
方法。

您可以使用多边形而不是矩形


然而,这将手动计算(x,y)角。有可能通过旋转矩形来构造形状,但这至少是可行的。它有一个
getBounds()
方法。

很大程度上取决于您管理对象的方式,但是

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.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RotateTest {

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

    public RotateTest() {
        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 Rectangle rect01;
        private Rectangle rect02;

        private int angle = 0;

        public TestPane() {

            rect01 = new Rectangle(0, 0, 100, 100);
            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.width) / 2;
            int y = (height - rect01.height) / 2;
            at.translate(x, y);
            at.rotate(Math.toRadians(angle), rect01.width / 2, rect01.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(rect01.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();
        }

    }

}

基本上,它的作用是创建一个
矩形的
路径迭代器
,它允许我对形状应用
仿射变换
,而不影响原始形状…不知道这是否重要,但我就是这样做的

然后我创建了一个
GeneralPath
,它允许我绘制
路径迭代器

现在,时髦的一点

我创建了两个
区域
s,每个
GeneralPath
一个,代表我要检查的每个对象。然后,我使用
Area
intersect
方法,生成一个
Area
表示两个对象的交点,然后检查该结果是否为空

如果它是空的,它不相交,如果它不是(空的),它们会接触


玩得开心;)

很大程度上取决于您如何管理对象,但是

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.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RotateTest {

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

    public RotateTest() {
        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 Rectangle rect01;
        private Rectangle rect02;

        private int angle = 0;

        public TestPane() {

            rect01 = new Rectangle(0, 0, 100, 100);
            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.width) / 2;
            int y = (height - rect01.height) / 2;
            at.translate(x, y);
            at.rotate(Math.toRadians(angle), rect01.width / 2, rect01.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(rect01.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();
        }

    }

}

基本上,它的作用是创建一个
矩形的
路径迭代器
,它允许我对形状应用
仿射变换
,而不影响原始形状…不知道这是否重要,但我就是这样做的

然后我创建了一个
GeneralPath
,它允许我绘制
路径迭代器

现在,时髦的一点

我创建了两个
区域
s,每个
GeneralPath
一个,代表我要检查的每个对象。然后,我使用
Area
intersect
方法,生成一个
Area
表示两个对象的交点,然后检查该结果是否为空

如果它是空的,它不相交,如果它不是(空的),它们会接触


玩得开心;)

什么是可以与坦克碰撞的物体?也只有矩形?是的,只有矩形。什么是可以与坦克碰撞的物体?也只有矩形?是的,只有矩形。这是我的问题。我不知道油箱填充的区域是什么,因为它可以旋转到任何角度,因此它填充的区域会发生变化。啊,我明白了。。好的,如果你的坦克x是0,坦克宽度是5,那么你的坦克长度是5。如果你的身高是10,那么你的油箱的面积是50。这永远是事实。要在实际绘制的曲面上查找线本身,请使用“坡度截距”形式。y=mx+b。或者如果你有两点,(y2-y1)/(x2-x1)。x1或x2是否为油箱并不重要,与y相同。这将找到你的线的斜率,在平面上(游戏表面)斜率1意味着在图形上,向上一个单位,从原点向右一个单位基本上线性代数的良好知识将帮助你检测旋转碰撞是的,谢谢,我猜这就是我简而言之要说的。这是我的问题。我不知道油箱填充的区域是什么,因为它可以旋转到任何角度,因此它填充的区域会发生变化。啊,我明白了。。好的,如果你的坦克x是0,坦克宽度是5,那么你的坦克长度是5。如果你的身高是10,那么你的油箱的面积是50。这永远是事实。要在实际绘制的曲面上查找线本身,请使用“坡度截距”形式。y=mx+b。或者如果你有两点,(y2-y1)/(x2-x1)。x1或x2是否为油箱并不重要,与y相同。这将找到直线的斜率,在平面(游戏表面)上,斜率1表示在图形上,向上一个单位,从原点向右一个单位。基本上,良好的线性代数知识将