检测java Swing中的重叠对象

时间:2013-11-13 04:50:53

标签: java swing animation jframe

我正在尝试制作一个有移动球和平台的程序。我也是新的java,我无法弄清楚如何检测2个摆动对象何时重叠。我的代码在下面,我想知道检测重叠对象的最佳方法是什么。

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:

    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:

    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:

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

2 个答案:

答案 0 :(得分:2)

所有Swing组件都有“边界”的概念。这是一个矩形区域,在其中“被绘制”。

如果您正确控制尺寸和位置,则应该能够使用通过调用Component#getBounds

返回的contains Rectangle方法

所以你checkOverlap方法看起来像......

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

您还需要确保在执行任何自定义绘制之前调用super.paintComponent,特别是在使用从JComponent延伸的组件时。这将确保Graphics上下文准备好正确绘制...

<强>更新

有一连串的问题。基本上,不是自己在父容器中定位组件(这就是我以为你做过的方式),而是将每个组件放在一起以填充父容器并且只“绘制”对象...这使生活更多难

相反,如果您要使用组件,我会使用null布局(甚至可能使用JLayeredPane作为父容器。)

然后我会改变组件的物理位置,例如......

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

现在,您可以使用“绘制”对象,但在这种情况下,我将拥有一个BallWall的虚拟概念,您可以在单个组件中绘制它。这些对象需要提供有关位置和大小的信息,您可以再次使用Rectangle#intersects进行检查......

答案 1 :(得分:1)

通常,只需尝试为对象创建“边界框”。这将是与对象一起使用的不可见矩形。然后就做 if(rectangle1.intersects(rectangle2))... intersects方法仅适用于矩形,这就是你需要一个边界框的原因。