【问题标题】:How can I make rotating hitboxes that detect collision?如何制作检测碰撞的旋转碰撞盒?
【发布时间】:2015-08-18 10:03:06
【问题描述】:

我正在尝试旋转一个检测碰撞的碰撞箱。我想要一个从左向右移动的非旋转矩形_1 和一个从右向左移动的旋转矩形_2,并且我希望旋转的碰撞框检测碰撞,而不管其方向如何。但是,只有在 rectangle_1 与未旋转的 rectangle_2 碰撞时才检测到碰撞。如何让旋转的命中框检测碰撞?以下是代码:

主程序:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Timer;

public class Rectangles extends JPanel implements MouseListener{

    public static final int SCREEN_WIDTH = 400;
    public static final int SCREEN_HEIGHT = 400;
    private static final int TIMER_RATE = 20;

    public static void main(String[] args) throws Exception {
        Rectangles game = new Rectangles();
        game.setup();
    }

    public void setup() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new JScrollPane(this));
        f.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        f.setLocation(200, 200);
        f.setVisible(true);
        this.addMouseListener(this);
        this.setFocusable(true);
    }

    public Rectangles() {
        rectangle_1 = new Rectangle_1();
        rectangle_2 = new Rectangle_2();
        gameover = false;
        play();
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.white);
        g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
        g.setColor(Color.white);
        draw((Graphics2D) g);
    }

    public void draw(Graphics2D g) {
        if (gameover) {
            rectangle_1.drawRectangle(g);
            rectangle_2.drawRectangle(g);
            return;
        }

        rectangle_1.drawRectangle(g);
        rectangle_2.drawRectangle(g);
        rectangle_1.move();
        rectangle_2.move(1);
        rectangle_2.rotateRectangle(g);

        if (rectangle_2.collides(rectangle_1)) {
            gameover = true;
        }
    }

    public void play() {
        ActionListener listener = new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                 repaint();
             }
          };
          Timer timer = new Timer(TIMER_RATE, listener);
          timer.start();
    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
        mouseAction(e.getX(), e.getY(), e.getButton());
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    /**
     * Use this method to handle all mouse input. The main action here is to have the bird flap whenever the mouse is clicked.
     */
    public void mouseAction(int x, int y, int button) {
        if (button == 1) {
            rectangle_1.flap();
        }
    }

    private Rectangle_1 rectangle_1;
    private Rectangle_2 rectangle_2;
    private boolean gameover;
    private int ticks = 0;
}

rectangle_1 类:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Rectangle_1 {

    public Rectangle_1() {
        x = 0;
        y = 240;
        rectangle = new Rectangle((int) x, (int) y, 25, 25);
    }

    public void drawRectangle(Graphics2D g) {
        g.setColor(Color.blue);
        g.draw(rectangle);
    }

    public void move() {
        x = x + 1;
        rectangle.setLocation((int) x, (int) y);
    }

    public void flap() {
        z = 10;
        rectangle.setLocation((int) x, (int) y);
    }

    public boolean collides(Rectangle r) {
        return r.intersects(rectangle);
    }

    public Rectangle getRectangle() {
        return rectangle;
    }

    private double x;
    private double y;
    private double z = 0;
    private Rectangle rectangle;
}

rectangle_2 类:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.*;
import java.awt.Rectangle;

public class Rectangle_2 {

    public Rectangle_2() {
        x = 375;
        y = 200;
        hitBox_1 = new Rectangle((int) x + 25, (int) y, 25, 100);
    }

    public void drawRectangle(Graphics2D g) {
        g.setColor(Color.red);
        g.draw(hitBox_1);
    }

    public void rotateRectangle(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        AffineTransform at = g2.getTransform();
        AffineTransform saveTransform = g2.getTransform();
        angle += 0.01;
        at.rotate(angle, hitBox_1.getX() + hitBox_1.getWidth() / 2, hitBox_1.getY() + hitBox_1.getHeight() / 2);
        g2.setTransform(at);
        g2.setColor(Color.red);
        g2.draw(hitBox_1);
        g2.setTransform(saveTransform);
    }

    public void move(double dx) {
        x = x - dx;
        hitBox_1.setLocation((int) x, (int) y);
    }

    public boolean collides(Rectangle_1 r) {
        return r.collides(hitBox_1);
    }

    @Override
    public String toString() {
        return "Pipe [x = " + x + ", y = " + y + ", hitBox_1 = " + hitBox_1 + "]";
    }

    public Rectangle getHitBox_1() {
        return hitBox_1;
    }

    public Rectangle getHitBox_2() {
        return hitBox_1;
    }

    public double getX() {
        return x;
    }

    private double x;
    private double y;
    private double angle = 0;
    private Rectangle hitBox_1;
}

【问题讨论】:

    标签: java rotation collision detection


    【解决方案1】:

    当且仅当其中至少一个矩形在另一个矩形内具有角点时,才会碰撞 2 个矩形。

    当且仅当从角点到矩形的两个相对边的距离都小于矩形边的长度时,一个角在另一个矩形内。

    对于计算机图形,有一种标准算法可以计算 2D 和 3D 空间中的距离。谷歌它,应该这样做。

    【讨论】:

      【解决方案2】:

      您从未旋转过任何矩形 - 因此您不会检测到(未旋转的)矩形上的碰撞)......

      当您使用rotateRectangle“旋转”您的矩形时,您只是绘制一个旋转的矩形,但从不旋转矩形本身...

      你必须做什么?您必须将 Rectangle2 替换为可以像 java.awt.polygon 一样旋转的东西

      //your source points
      int[] xs = new int[]{0, 10, 10, 0};
      int[] ys = new int[]{0, 0, 10, 10};
      
      //create a polygon with these source points
      Polygon p = new Polygon(xs, ys, 4);
      
      
      //again: your source Points as double[]
      double[] src = new double[]{
              xs[0], ys[0],
              xs[1], ys[1],
              xs[2], ys[2],
              xs[3], ys[3]};
      
      //and destination points for rotating them
      double[] dst = new double[8];
      
      //to rotate them you need an affirm transformation (rotating around your center 5/5)
      AffineTransform t = AffineTransform.getRotateInstance(0.1, 5, 5);
      t.transform(src, 0, dst, 0, 4);
      
      //and revert them back into int[]
      int[] xTrans = new int[]{(int)dst[0], (int)dst[2],(int)dst[4],(int)dst[6]};
      int[] yTrans = new int[]{(int)dst[1], (int)dst[3],(int)dst[5],(int)dst[7]};
      
      //this would be your rotated polygon
      Polygon pTrans = new Polygon(xTrans, yTrans, 4);
      

      您可以使用 java.awt.Polygon.intersects(Rectangle r) 方法来检查您是否与矩形相交

      如果你想要最简单的方法,你可以简单地从你的矩形创建一个旋转的实例:

      AffineTransform t = AffineTransform.getRotateInstance(0.1, 5, 5);
      Shape s = t.createTransformedShape(rectangle);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-08
        • 1970-01-01
        • 2022-08-19
        • 2011-09-05
        • 2019-04-30
        • 1970-01-01
        相关资源
        最近更新 更多