Java球对象不会像它应该绘制的矩形一样反弹。

对不起,这个可怕的标题。 Java applet的目的就是这样:一个球在屏幕上跳动。 这个球的大小和速度可以通过滚动条来改变。 用户可以在屏幕上按下并拖动鼠标来绘制矩形。 球也会反弹离开这些矩形。 这些矩形的边界存储在一个向量中。 当一个矩形被点击时,它(和那个点上的所有其他矩形)将从vector(和屏幕)中被移除。

我遇到的问题有两个方面:一是当我点击一个矩形去除它时,它不会被删除,但是可以在以后解决。

二:球不像它应该反弹的矩形。 当我在与球相同的行或列中绘制矩形时,球会在一个小矩形内弹起,就像卡住了一样。

这里是我的代码来检测球是否在applet或任何矩形的边界:

public void move() { //if it will hit the right or left boundary, flip the x direction and set it if (loc.x+size >= boundx || loc.x <= 0) { dx *= -1; } //if it will hit the top or bottom boundray, flip the y direction and set it if (loc.y+size >= boundy || loc.y <= 0) { dy *= -1; } for (int i = 0; i < r.size(); i++) { temp = new Rectangle(r.elementAt(i)); int rx = temp.x; int ry = temp.y; int rh = temp.height; int rw = temp.width; //If the ball hits either side of the rectangle, change the x direction if((loc.x > rx && loc.x > ry && loc.x < (ry + rh))||(loc.x < (rx + rw) && loc.x > rx && loc.x <(ry + rh))) {dx *= -1;} //If the ball hits either the top or bottom, change the y direction if((loc.y > ry && loc.y > rx && loc.y < (rx + rw))||(loc.y < (ry + rh) && loc.y > ry && loc.y <(rx + rw))) {dy *= -1;} } //Increment or decrement the location of the ball based on the X and Y directions. loc.x += dx; loc.y += dy; } 

如果您想查看完整的代码,请访问http://ideone.com/R1hpBx

在此先感谢所有的帮助。

我终于find了我喜欢的边缘检测系统…

厄运的旋转球

基本上,魔术发生在这里…

 // Detect if we collided with any one (collision is the rectangle, bounds is us) if (collision.intersects(bounds)) { // Determine the intersect of the collision... insect = collision.intersection(bounds); // Flags... boolean vertical = false; boolean horizontal = false; boolean isLeft = false; boolean isTop = false; // Left side... if (insect.x == collision.x) { horizontal = true; isLeft = true; // Right side } else if (insect.x + insect.width == collision.x + collision.width) { horizontal = true; } // Top if (insect.y == collision.y) { vertical = true; isTop = true; // Bottom } else if (insect.y + insect.height == collision.y + collision.height) { vertical = true; } // Technically, we can really only collide with a single edge...more or less if (horizontal && vertical) { // Basically, we try and give precedence to the longer edge... if (insect.width > insect.height) { horizontal = false; } else { vertical = false; } } // We collided with a horizontal side... if (horizontal) { dx *= -1; // Move the ball to the approriate edge so we don't get caught... if (isLeft) { bounds.x = collision.x - bounds.width; } else { bounds.x = collision.x + collision.width; } // We collided with a vertical side... } else if (vertical) { dy *= -1; // Move the ball to the approriate edge so we don't get caught... if (isTop) { bounds.y = collision.y - bounds.height; } else { bounds.y = collision.y + collision.height; } } } 

现在,我只有一个障碍,但我怀疑要花费很多努力才能解决一系列的障碍……)

 public class TestBouncingBall { private Rectangle insect; public static void main(String[] args) { new TestBouncingBall(); } public TestBouncingBall() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new BallPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class BallPane extends JLayeredPane { private Ball ball; private Timer timer; private Rectangle world; public BallPane() { // world = new Rectangle(random(400), random(400), random(100), random(100)); world = new Rectangle(100, 100, 200, 200); ball = new Ball(); ball.setSize(ball.getPreferredSize()); ball.setLocation(10, 10); add(ball); timer = new Timer(16, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ball.move(getBounds(), world); invalidate(); repaint(); } }); timer.setRepeats(true); timer.setCoalesce(true); timer.start(); } protected int random(int max) { return (int) Math.round(Math.random() * max); } @Override public Dimension getPreferredSize() { return new Dimension(400, 400); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); g2d.setColor(Color.GRAY); g2d.fill(world); if (insect != null) { g2d.setColor(Color.RED); g2d.fill(insect); } g2d.dispose(); } } public class Ball extends JPanel { public int maxSpeed = 10; private BufferedImage beachBall; private int dx = 10 - (int)Math.round(Math.random() * (maxSpeed * 2)) + 1; private int dy = 10 - (int)Math.round(Math.random() * (maxSpeed * 2)) + 1; private int spin = 20; private int rotation = 0; public Ball() { try { beachBall = ImageIO.read(getClass().getResource("/ball.png")); } catch (IOException ex) { ex.printStackTrace(); } setOpaque(false); } @Override public Dimension getPreferredSize() { Dimension size = beachBall == null ? new Dimension(48, 48) : new Dimension(beachBall.getWidth(), beachBall.getHeight()); size.width += 4; size.height += 4; return size; } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (beachBall != null) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); int x = (getWidth() - beachBall.getWidth()) / 2; int y = (getHeight() - beachBall.getHeight()) / 2; AffineTransform transform = g2d.getTransform(); AffineTransform at = new AffineTransform(); at.translate(getX(), getY()); at.rotate(Math.toRadians(rotation), getWidth() / 2, getHeight() / 2); g2d.setTransform(at); g2d.drawImage(beachBall, x, y, this); g2d.setTransform(transform); g2d.dispose(); } } public void move(Rectangle world, Rectangle collision) { Rectangle bounds = getBounds(); bounds.x += dx; bounds.y += dy; if (bounds.x < 0) { bounds.x = 0; dx *= -1; } if (bounds.y < 0) { bounds.y = 0; dy *= -1; } if (bounds.x + bounds.width > world.width) { bounds.x = world.width - bounds.width; dx *= -1; } if (bounds.y + bounds.height > world.height) { bounds.y = world.height - bounds.height; dy *= -1; } if (collision.intersects(bounds)) { insect = collision.intersection(bounds); boolean vertical = false; boolean horizontal = false; boolean isLeft = false; boolean isTop = false; if (insect.x == collision.x) { horizontal = true; isLeft = true; } else if (insect.x + insect.width == collision.x + collision.width) { horizontal = true; } if (insect.y == collision.y) { vertical = true; isTop = true; } else if (insect.y + insect.height == collision.y + collision.height) { vertical = true; } if (horizontal && vertical) { if (insect.width > insect.height) { horizontal = false; } else { vertical = false; } } System.out.println("v = " + vertical + "; h = " + horizontal); if (horizontal) { dx *= -1; if (isLeft) { bounds.x = collision.x - bounds.width; } else { bounds.x = collision.x + collision.width; } } else if (vertical) { dy *= -1; if (isTop) { bounds.y = collision.y - bounds.height; } else { bounds.y = collision.y + collision.height; } } } rotation += spin; setBounds(bounds); repaint(); } } }