检测可旋转的两个精灵的碰撞 [英] Detecting collision of two sprites that can rotate

查看:176
本文介绍了检测可旋转的两个精灵的碰撞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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



所以我不能简单地做我在这种情况下经常做的事情。



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

解决方案

很多将取决于你如何管理你的对象,但是......



  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);
}
});
}

公共类TestPane扩展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);

计时器计时器=新计时器(40,新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());

区域a1 =新区域(路径1);
区域a2 =新区域(路径2);
a2.intersect(a1);
if(!a2.isEmpty()){
g2d.setColor(Color.RED);
g2d.fill(a2);
}

g2d.dispose();
}

}

}

基本上,它的作用是,它创建 Rectangle PathIterator ,这允许我应用 AffineTransformation 到形状而不影响原始形状......不知道这是否重要,但这就是我做的...



然后我创建了一个 GeneralPath ,它允许我绘制 PathIterator 。 / p>

现在,时髦的位......



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



如果它为空,则它不相交,如果它不是(空的),它们触摸。



玩得开心玩得开心;)


I have a problem with collision detection in a 2D Java game.

Normally, what I would do is create a getBounds() method for an object that can collide with other objects. This method would return a new Rectangle(x,y,width,height), where x and y are the coordinates for the top-left corner of the sprite, and width and height are the width and height of the sprite.

But in the game I'm currently working on, there is a "tank" controlled by the user. The sprite of this tank rotates as long as the player holds one of the left or right arrow buttons. In other words, it can rotate to any angle. The tank's sprite is a rectangle.

So I can't simply do what I always do in this case.

How can I detect collision with this kind of sprite? Thanks

解决方案

A lot will depend on how you are managing your objects, but...

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();
        }

    }

}

Basically, what this does, is it creates a PathIterator of the Rectangle, which allows me to apply a AffineTransformation to the shape without effecting the original shape...don't know if this is important or not, but this is how I did it...

Then I created a GeneralPath which allows me to paint the PathIterator.

Now, the funky bit...

I create two Areas, one for each GeneralPath representing each object I want to check. I then use the Area's intersect method, which generates a Area that represents the intersection points of the two objects and then check to see if this result is empty or not.

If it's empty, it's does not intersect, if it's not (empty), they touch.

Have fun playing with that ;)

这篇关于检测可旋转的两个精灵的碰撞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆