Java Bounceball Bubble Movement - Error

Asked

Viewed 87 times

1

I’m doing a Bounceball game, using iteration with the mouse pointer. But I’ve come across a problem I’m having trouble solving.

The general idea is that, the bubbles move around the screen, and when they find the mouse pointer, they change direction. But my method is a bit messed up, for some bubbles it works, but for most of them it doesn’t. They are "locked" in the upper left corner of the screen.

Someone can shed some light on what’s wrong??

My problem is in the method "Move".

Follows my source:

public class SimpleBalls {

    private Point mousePoint;

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

    public SimpleBalls() {
        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("Spot");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                Balls balls = new Balls();
                frame.add(balls);
                frame.setSize(400, 400);
                frame.setVisible(true);

                new Thread(new BounceEngine(balls)).start();

            }
        });
    }

    public static int random(int maxRange) {
        return (int) Math.round((Math.random() * maxRange));
    }

    public class Balls extends JPanel {

        private List<Ball> ballsUp;

        public Balls() {
            ballsUp = new ArrayList<Ball>(25);

            MouseAdapter handler = new MouseAdapter() {

                @Override
                public void mouseMoved(MouseEvent e) {
                    mousePoint = e.getPoint();
                    // System.out.println(mousePoint);
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    mousePoint = null;
                }

            };

            addMouseListener(handler);
            addMouseMotionListener(handler);

            for (int index = 0; index < 1 + random(2); index++) {
                ballsUp.add(new Ball(new Color(random(255), random(255),
                        random(255))));
            }

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            for (Ball ball : ballsUp) {
                ball.paint(g2d);
            }
            g2d.dispose();
        }

        public List<Ball> getBalls() {
            return ballsUp;
        }
    }

    public class BounceEngine implements Runnable {

        private Balls parent;

        public BounceEngine(Balls parent) {
            this.parent = parent;
        }

        @Override
        public void run() {

            int width = getParent().getWidth();
            int height = getParent().getHeight();

            for (Ball ball : getParent().getBalls()) {
                int x = random(width);
                int y = random(height);

                Dimension size = ball.getSize();

                if (x + size.width > width) {
                    x = width - size.width;
                }
                if (y + size.height > height) {
                    y = height - size.height;
                }

                ball.setLocation(new Point(x, y));

            }

            while (getParent().isVisible()) {

                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        getParent().repaint();
                    }
                });

                for (Ball ball : getParent().getBalls()) {
                    move(ball, mousePoint);
                }

                // for (Ball ball : getParent().getBalls()) {
                // move(ball, mousePoint);
                // }

                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

            }

        }

        public Balls getParent() {
            return parent;
        }

        public void move(Ball ball, Point mouse) {

            try {
                Point p = ball.getLocation();
                Point speed = ball.getSpeed();
                Dimension size = ball.getSize();

                int dimeter = ball.dimeter;

                int vx = speed.x;
                int vy = speed.y;

                int x = p.x;
                int y = p.y;

                // ----------------------
                if (mouse != null) {

                    int xDistance = Math.abs(x + (size.width / 2) - mouse.x);
                    int yDistance = Math.abs(y + (size.height / 2) - mouse.y);

                    if (xDistance < yDistance) {
                        if (x + (size.width / 2) < mouse.x) {
                            if (vx > 0) {
                                vx *= -1;
                                System.out
                                        .println("1 - MOUSE - x: " + x
                                                + " Dimeter: " + size.width
                                                + " Dimeter/2: "
                                                + (size.width / 2)
                                                + " Mouse X: " + mouse.x
                                                + " VX: " + vx);
                            }
                        } else {
                            if (vx > 0) {
                                vx *= -1;
                                System.out
                                        .println("2 - MOUSE - x: " + x
                                                + " Dimeter: " + size.width
                                                + " Dimeter/2: "
                                                + (size.width / 2)
                                                + " Mouse X: " + mouse.x
                                                + " VX: " + vx);
                            }
                        }
                    } else {
                        if (y + (size.height / 2) < mouse.y) {
                            if (vy > 0) {
                                vy *= -1;
                                System.out
                                        .println("3 - MOUSE - y: " + y
                                                + " Dimeter: " + size.height
                                                + " Dimeter/2: "
                                                + (size.height / 2)
                                                + " Mouse Y: " + mouse.y
                                                + " VY: " + vy);
                            }
                        } else {
                            if (vy > 0) {
                                vy *= -1;
                                System.out
                                        .println("4 - MOUSE - y: " + y
                                                + " Dimeter: " + size.height
                                                + " Dimeter/2: "
                                                + (size.height / 2)
                                                + " Mouse Y: " + mouse.y
                                                + " VY: " + vy);
                            }
                        }
                    }

                }

                // ----------------------

                if (x + vx < 0 || x + size.width + vx > getParent().getWidth()) {
                    vx *= -1;
                    System.out.println("1 - N ");
                }
                if (y + vy < 0
                        || y + size.height + vy > getParent().getHeight()) {
                    vy *= -1;
                    System.out.println("2 - N ");
                }
                x += vx;
                y += vy;

                ball.setSpeed(new Point(vx, vy));
                ball.setLocation(new Point(x, y));

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

    }

    public class Ball {

        private Color color;
        private Point location;
        private Dimension size;
        private Point speed;
        private int dimeter;

        public Ball(Color color) {
            Random rnd = new Random();
            dimeter = 10 + rnd.nextInt(50);

            setColor(color);

            speed = new Point(10 - random(20), 10 - random(20));
            size = new Dimension(dimeter, dimeter);

        }

        public Dimension getSize() {
            return size;
        }

        public void setColor(Color color) {
            this.color = color;
        }

        public void setLocation(Point location) {
            this.location = location;
        }

        public Color getColor() {
            return color;
        }

        public Point getLocation() {
            return location;
        }

        public Point getSpeed() {
            return speed;
        }

        public void setSpeed(Point speed) {
            this.speed = speed;
        }

        protected void paint(Graphics2D g2d) {

            Point p = getLocation();
            if (p != null) {
                g2d.setColor(getColor());
                Dimension size = getSize();
                g2d.fillOval(p.x, p.y, size.width, size.height);
            }

        }
    }
}
  • Anyone?? Any tips?

  • Are you considering the diameter when assessing whether she touched the corners of the window?

  • Fernando, although his code is not well organized, that is, did not adopt any standard (MVC, MVP, etc.), I gave a small simplicate in some parts that were very complex without need, the code is almost working. As I’m running out of time now, I put the code I left in this gist: https://gist.github.com/wakim/424973a8e2d2dca282b0

  • @Caputo Yes, in relation to the sides, it is hitting and changing direction correctly, but I could not understand why the bubbles get bugged when the mouse is on the screen..

  • @Wakim really, I was developing, researching and did not leave very organized. I will take a look at what you did there. Thank you.

  • @Wakim Cara, ball show... I’ve changed two things here, and it’s working perfectly.. I can’t believe I hit myself so hard with this. It makes perfect sense what you did. I only arranged the collision with the mouse taking into account the diameter. Of rest 100%. Put there that I close the doubt. Show... Thank you very much.

  • Okay, when I get home I put.

  • @Wakim Thanks even man... Thank you. Helped me a lot.

Show 3 more comments

1 answer

0


His code had some logic that I didn’t understand very well, regarding the detection of the collision with the mouse. I made my own, where I just check if the distance between the position of the mouse minus the position of the center of the ball, considering the speed (this needs to be reviewed maybe) is less than the radius.

I think it is worth reviewing this logic, because the detection is predictive, that is, is detecting before drawing the frame (can cause problems for balls with high speed).

if (mouse != null) {
    // Nesse metodo esta sendo desenhado a bola no proximo frame, logo eu considero o vx e vy na colisao 
    int xDistance = Math.abs((x + vx) - mouse.x);
    int yDistance = Math.abs((y + vy) - mouse.y);

    System.out.printf("b(%d, %d) m(%d, %d) dx(%d, %d)\n", x, y, mouse.x, mouse.y, (x + vx) - mouse.x, (y + vy) - mouse.y);

    if (xDistance <= raioX && yDistance <= raioY) {
        // Essa logica de alteracao pode variar se quiser
        if(xDistance < yDistance) {
            vx *= -1;
        } else {
            vy *= -1;
        }

        System.out.println("Bateu!");
    }
}

Its code with respect to collision with edge was almost certain, only lacked to consider the radius and not the diameter of the ball and also the speed. There is no collision if the ball is on an edge but is speeding towards the center.

I made a simplication:

// Lado esquerdo
if (x + vx - (size.width/2)) < 0 && vx < 0) {
    vx *= -1;
}

// Lado direito
if((x + (size.width/2)) + vx > getParent().getWidth() && vx > 0) {
    vx *= -1;
}

// Baixo
if (y + vy - (size.width/2)) < 0 && vy < 0) {
    vy *= -1;
}

// Cima
if((y + (size.height/2)) + vy > getParent().getHeight() && vy > 0) {
    vy *= -1;
}

Of course you can still reduce the number of calculations by reusing variables and everything else. But there are later optimizations.

  • Wakim, thanks for the help. I’m new to Swing in java. Thanks a lot.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.