简体   繁体   English

在Java Swing中检测重叠对象

[英]Detect overlapping objects in java Swing

I am trying to make a program that has a moving ball and a platform that it will sit on. 我正在尝试制作一个程序,该程序具有一个动球和一个可以坐在其上的平台。 I am new too java and I cant figure out how to detect when 2 swing objects are overlapping. 我也是Java的新手,我想不出如何检测2个摆动对象何时重叠。 My code it below and I am wondering what the best way is to detect overlapping objects. 我在下面的代码中,我想知道什么是检测重叠对象的最佳方法。

KeyDemo.java: KeyDemo.java:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;

    public class KeyDemo
    {
        public static void main(String[] args)
  {
  JFrame frame = new JFrame();
  JPanel panel = new JPanel();
  LayoutManager overlay = new OverlayLayout(panel);
  panel.setLayout(overlay);

  final int FRAME_WIDTH = 800;
  final int FRAME_HEIGHT = 600;

  frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
  frame.setTitle("Move the Ball");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   final WallComponent wc1 = new WallComponent(400, 400);
   final BallComponent bc = new BallComponent(400, 300);
   panel.add(wc1);
   panel.add(bc);
   frame.add(panel);

   KeyboardController kc = new KeyboardController(bc);
   frame.addKeyListener(kc);

  frame.setVisible(true);




  class AnimationListener implements ActionListener{
        public void actionPerformed(ActionEvent event){
           bc.tick();
           //wc1.checkOverlap(bc);
        }
    }

    ActionListener aListener = new AnimationListener();

    final Timer timer = new Timer(1, aListener);
    timer.start();

  }
 }

KeyboardController.java: KeyboardController.java:

    import java.awt.*;
    import java.awt.event.*;

public class KeyboardController implements KeyListener
{
BallComponent bComp;

public KeyboardController(BallComponent t)
{
    bComp = t;
}

/** Handle the key pressed event from the text field. */
public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(keyCode == 38)
    {
        System.out.println("Pressed Up!");
        bComp.moveUp();
    }
    if(keyCode == 37)
    {
        System.out.println("Pressed Left!");
        bComp.moveLeft();
    }
    if(keyCode == 39)
    {
        System.out.println("Pressed Right!");
        bComp.moveRight();
    }
    if(keyCode == 40)
    {
        System.out.println("Pressed Down!");
        bComp.moveDown();
    }
}

/** Handle the key released event from the text field. */
public void keyReleased(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if(keyCode == 38)
    {
        System.out.println("Released Up!");
        bComp.stopY();
    }
    if(keyCode == 37)
    {
        System.out.println("Released Left!");
        bComp.stopX();
    }
    if(keyCode == 39)
    {
        System.out.println("Released Right!");
        bComp.stopX();
    }
    if(keyCode == 40)
    {
        System.out.println("Pressed Down!");
        bComp.stopY();
    }    
}


public void keyTyped(KeyEvent e) {
}


   }

BallComponent.java: BallComponent.java:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;

    public class BallComponent extends JComponent
    {
int xSpeed;
int ySpeed;
int x;
int y;

public BallComponent(int x, int y)
{
    super();
    this.x = x;
    this.y = y;
}

 public void paintComponent(Graphics g)
{
    Graphics2D g2 = (Graphics2D)g;

    Ellipse2D.Double ball = new Ellipse2D.Double(x-10,y-10,10,10);
    g2.setColor(Color.RED);
    g2.fill(ball);
    g2.draw(ball);
}

public void moveLeft()
{
    xSpeed=-1;
}
public void moveRight()
{
    xSpeed=1;
}
public void moveUp()
{
    ySpeed=-1;
}
public void moveDown()
{
    ySpeed=1;
}
public void tick()
{
    x=x+xSpeed;
    y=y+ySpeed;

    repaint();
}
public void stopY()
{
    ySpeed=0;
}
public void stopX()
{
    xSpeed=0;
}

   }

WallComponent.java: WallComponent.java:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.geom.*;

   public class WallComponent extends JComponent
   {
int x;
int y;

public WallComponent(int x, int y)
{
    super();
    this.x = x;
    this.y = y;
}

public void paintComponent(Graphics g)
{
    Graphics2D g2 = (Graphics2D)g;

    Rectangle wall = new Rectangle(x-40,y-40,40,40);
    g2.setColor(Color.YELLOW);
    g2.fill(wall);
    g2.draw(wall);
}
public void checkOverlap(BallComponent bc){
    if (this.contains(bc.getLocation())){
        bc.stopY();
        bc.stopX();
    }
}
   }

All Swing components have a concept of "bounds". 所有Swing组件都具有“界限”的概念。 This is a rectangular area within which they are "drawn". 这是在其中“绘制”的矩形区域。

If you are controlling the size and position correctly, you should be able to use the contains method of the Rectangle which is returned from calling Component#getBounds 如果正确控制大小和位置,则应该可以使用从调用Component#getBounds返回的Rectanglecontains方法。

So you checkOverlap method could look like... 所以你的checkOverlap方法看起来像...

public void checkOverlap(BallComponent bc){
    if (getBounds().intersects(bc.getBounds())){
        bc.stopY();
        bc.stopX();
    }
}

You will also want to make sure that you are calling super.paintComponent before performing any custom painting, espeically when using components that extend from JComponent . 您还需要确保在执行任何自定义绘制之前要调用super.paintComponent在使用从JComponent扩展的组件时。 This will ensure that the Graphics context is prepared for painting correctly... 这将确保Graphics上下文已准备好正确绘制...

Updated 更新

There's a cascade of issues. 有很多问题。 Basically, instead of positing the components within the parent container yourself (which is how I thought you had done it), you've laid each component out to fill the parent container and only "painted" the objects...This makes life more difficult 基本上,不是自己将组件放置在父容器中(这就是我认为的方式),而是布置了每个组件以填充父容器并仅“绘制”了对象……这使生活变得更加美好难

Instead, if you are going to use components, I would use a null layout (or even possibly use a JLayeredPane as the parent container). 相反,如果要使用组件,我将使用null布局(甚至可能使用JLayeredPane作为父容器)。

I would then change the physical position of the components, for example... 然后,我将更改组件的物理位置,例如...

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestGame {

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

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

                JFrame frame = new JFrame();
                JPanel panel = new JPanel();
                panel.setLayout(null);

                final int FRAME_WIDTH = 800;
                final int FRAME_HEIGHT = 600;

                frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
                frame.setTitle("Move the Ball");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                final WallComponent wc1 = new WallComponent(400, 400);
                final BallComponent bc = new BallComponent(400, 300);
                panel.add(wc1);
                panel.add(bc);
                frame.add(panel);

                KeyboardController kc = new KeyboardController(bc);
                frame.addKeyListener(kc);

                frame.setVisible(true);

                class AnimationListener implements ActionListener {

                    public void actionPerformed(ActionEvent event) {
                        bc.tick();
                        wc1.checkOverlap(bc);
                    }
                }

                ActionListener aListener = new AnimationListener();

                final Timer timer = new Timer(1, aListener);
                timer.start();

            }
        });
    }

    public class KeyboardController implements KeyListener {

        BallComponent bComp;

        public KeyboardController(BallComponent t) {
            bComp = t;
        }

        /**
         * Handle the key pressed event from the text field.
         */
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
            if (keyCode == 38) {
                System.out.println("Pressed Up!");
                bComp.moveUp();
            }
            if (keyCode == 37) {
                System.out.println("Pressed Left!");
                bComp.moveLeft();
            }
            if (keyCode == 39) {
                System.out.println("Pressed Right!");
                bComp.moveRight();
            }
            if (keyCode == 40) {
                System.out.println("Pressed Down!");
                bComp.moveDown();
            }
        }

        /**
         * Handle the key released event from the text field.
         */
        public void keyReleased(KeyEvent e) {
            int keyCode = e.getKeyCode();
            if (keyCode == 38) {
                System.out.println("Released Up!");
                bComp.stopY();
            }
            if (keyCode == 37) {
                System.out.println("Released Left!");
                bComp.stopX();
            }
            if (keyCode == 39) {
                System.out.println("Released Right!");
                bComp.stopX();
            }
            if (keyCode == 40) {
                System.out.println("Pressed Down!");
                bComp.stopY();
            }
        }

        public void keyTyped(KeyEvent e) {
        }

    }

    public class BallComponent extends JComponent {

        int xSpeed;
        int ySpeed;

        public BallComponent(int x, int y) {
            super();
            setBounds(x, y, 10, 10);
        }

        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;

            Ellipse2D.Double ball = new Ellipse2D.Double(0, 0, 9, 9);
            g2.setColor(Color.RED);
            g2.fill(ball);
            g2.draw(ball);
        }

        public void moveLeft() {
            xSpeed = -1;
        }

        public void moveRight() {
            xSpeed = 1;
        }

        public void moveUp() {
            ySpeed = -1;
        }

        public void moveDown() {
            ySpeed = 1;
        }

        public void tick() {
            int x = getX() + xSpeed;
            int y = getY() + ySpeed;

            setLocation(x, y);

            repaint();
        }

        public void stopY() {
            ySpeed = 0;
        }

        public void stopX() {
            xSpeed = 0;
        }

    }

    public class WallComponent extends JComponent {

        public WallComponent(int x, int y) {
            super();
            setBounds(x, y, 40, 40);
        }

        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;

            Rectangle wall = new Rectangle(0, 0, 40, 40);
            g2.setColor(Color.YELLOW);
            g2.fill(wall);
            g2.draw(wall);
        }

        public void checkOverlap(BallComponent bc) {

            System.out.println(" me: " + getBounds());
            System.out.println("you: " + bc.getBounds());

            if (getBounds().intersects(bc.getBounds())) {
                bc.stopY();
                bc.stopX();
            }
        }
    }
}

Now, you could use "painted" objects, but in that case I would have a virtual concept of a Ball and Wall which you could paint within a single component. 现在,您可以使用“已绘制”的对象,但是在那种情况下,我会有一个虚拟的概念,即“ BallWall ,可以在单个组件中绘制。 These objects would need to provide information about there position and size, which you could, again, check using Rectangle#intersects ... 这些对象需要提供有关位置和大小的信息,您可以再次使用Rectangle#intersects检查...

Generally, just try to make a "bounding box" for your objects. 通常,仅尝试为对象创建一个“边界框”。 This will be the invisible rectangle that goes with the object. 这将是与对象一起出现的不可见矩形。 Then just do if(rectangle1.intersects(rectangle2)) ... The intersects method only works with rectangles, and that's why you need a bounding box. 然后只需执行if(rectangle1.intersects(rectangle2))... intersects方法仅适用于矩形,这就是为什么需要边框的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM