像它应该对Java球对象不关绘制矩形的反弹。 [英] Java ball object doesn't bounce off of drawn rectangles like it's supposed to.

查看:179
本文介绍了像它应该对Java球对象不关绘制矩形的反弹。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很抱歉的可怕称号。 Java小程序的目的是这样:一个球是在屏幕上跳动。此球的大小和速度可通过滚动条来改变。用户可以preSS和拖动鼠标在屏幕上绘制矩形。球会弹开这些矩形为好。这些矩形的边界存储在载体中。当点击一个矩形,它(并在该点的所有其他矩形)从向量(和屏幕)中除去。

Sorry for the awful title. The purpose of the Java applet is as such: A ball is bouncing around the screen. The size and speed of this ball can be changed via scrollbars. The user can press and drag the mouse on the screen to draw rectangles. The ball will bounce off of these rectangles as well. The bounds of these rectangles are stored in a vector. When a rectangle is clicked, it (and all other rectangles at that point) are removed from the vector (and the screen).

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

The problem I'm having is two-fold: One, when I click a rectangle to remove it, it doesn't get removed, but that can be solved later.

二:像它应该的球不反弹的矩形。当我要么在同一行或列的球在绘制一个矩形,球反弹围绕一个微小的矩形的内部,像它的卡住。

Two: The ball doesn't bounce off of the rectangles like it's supposed to. When I draw a rectangle in either the same row or column as the ball, the ball bounces around inside of a tiny rectangle, like it's stuck.

下面是我的code检测如果球是打或者小程序或任何矩形的边界:

Here's my code to detect if the ball is hitting the boundaries of either the applet or any of the rectangles:

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

如果您要查看的code的全部,它在这里: http://ideone.com/R1hpB​​x

If you want to view the code in its entirety, it's here: http://ideone.com/R1hpBx

在此先感谢所有美妙的帮助。

Thanks in advance for all the wonderful help.

推荐答案

我终于找到了一个边缘检测系统,我喜欢...

I finally found a edge detection system I like...

基本上,奇迹发生在这里...

Basically, the magic happens here...

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

}

现在,我只有一个障碍,但我怀疑它会采取很多努力得到它与一系列障碍的工作...;)

Now, I only have a single obstacle, but I doubt it would take much effort to get it working with a series of obstacles... ;)

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

        }
    }
}

这篇关于像它应该对Java球对象不关绘制矩形的反弹。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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