0

我正在尝试制作一个程序,该程序具有一个移动的球和一个可以放置的平台。我也是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();

  }
 }

键盘控制器.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;
}

   }

墙组件.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();
    }
}
   }
4

2 回答 2

2

All Swing components have a concept of "bounds". 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

So you checkOverlap method could look like...

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. This will ensure that the Graphics context is prepared for painting correctly...

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).

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. These objects would need to provide information about there position and size, which you could, again, check using Rectangle#intersects...

于 2013-11-13T04:54:14.900 回答
1

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

于 2013-11-18T07:13:28.357 回答