0

I'm working on a game project. The aim is clicking the balls and drop them into the basket which is below in the JPanel. I created some ways to do that but I can't achieve it. In my opinion, when the user click the ball's center with a margin of error (because the program can't catch the real point of balls), the program understands the action and runs the function of this issue. After clicking the ball it should be dropped down straight but the other balls should be continued. I use MouseListener#mousePressed method, but it doesn't work or I'm missing some parts. In addition, I made some changes in my source code, but I want to listen your advices so I am writing this topic.

I wrote a method which finds the mouse and ball coordinates. So when I make some changes to it, I can achieve my project goal. You can see the editing in the picture.

enter image description here

This is my source code ;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Game {

public Game() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager
                        .getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException
                    | IllegalAccessException
                    | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            JFrame frame = new JFrame("MultipleBallApp");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new BallControl());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}

public class BallControl extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private BallPanel ballPanel = new BallPanel();
    private JButton Suspend = new JButton("Suspend");
    private JButton Resume = new JButton("Resume");
    private JButton Add = new JButton("+1");
    private JButton Subtract = new JButton("-1");
    private JScrollBar Delay = new JScrollBar();

    public BallControl() {
        // Group buttons in a panel
        JPanel panel = new JPanel();
        panel.add(Suspend);
        panel.add(Resume);
        panel.add(Add);
        panel.add(Subtract);

        // Add ball and buttons to the panel
        ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
        Delay.setOrientation(JScrollBar.HORIZONTAL);
        ballPanel.setDelay(Delay.getMaximum());
        setLayout(new BorderLayout());
        add(Delay, BorderLayout.NORTH);
        add(ballPanel, BorderLayout.CENTER);
        add(panel, BorderLayout.SOUTH);

        this.addMouseListener(new MouseListener() {

            @Override
            public void mouseReleased(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mousePressed(MouseEvent clickEvent) {
                // TODO Auto-generated method stub

                System.out.println("X coordinate =" + clickEvent.getX());
                System.out.println("Y coordinate = " + clickEvent.getY());

                double radius1;
                int x = 0;
                double y = 0;
                int radius = 15;
                double xM = clickEvent.getX();
                double yM = clickEvent.getY();

                radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y)
                        * (yM - y));
                System.out.println("Radius1 =" + radius1);
                // ballPanel.list.get(0).setD
            }

            @Override
            public void mouseExited(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseEntered(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseClicked(MouseEvent arg0) {
                // TODO Auto-generated method stub

            }
        });
        // Register listeners
        Suspend.addActionListener(new Listener());
        Resume.addActionListener(new Listener());
        Add.addActionListener(new Listener());
        Subtract.addActionListener(new Listener());
        Delay.addAdjustmentListener(new AdjustmentListener() {

            public void adjustmentValueChanged(AdjustmentEvent e) {
                ballPanel.setDelay(Delay.getMaximum() - e.getValue());
            }
        });
    }

    class Listener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == Suspend) {
                ballPanel.suspend();
            } else if (e.getSource() == Resume) {
                ballPanel.resume();
            } else if (e.getSource() == Add) {
                ballPanel.add();
            } else if (e.getSource() == Subtract) {
                ballPanel.subtract();
            }
        }
    }
}

class BallPanel extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int delay = 30;
    public ArrayList<AnimatedShape> list = new ArrayList<AnimatedShape>();
    private AnimatedRectange rectangle;

    public BallPanel() {
        this.rectangle = new AnimatedRectange(-25, 373, 50, 25, Color.BLACK);

        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(400, 400);
    }

    // Create a timer with the initial delay
    protected Timer timer = new Timer(delay, new ActionListener() {
        /**
         * Handle the action event
         */
        @Override
        public void actionPerformed(ActionEvent e) {
            for (AnimatedShape ball : list) {
                ball.update(getBounds());
            }
            rectangle.update(getBounds());
            repaint();
        }
    });

    public void add() {
        int radius = 15;
        // Randomised position
        int x = (int) (Math.random() * (getWidth() - (radius * 2)))
                + radius;
        int y = (int) (Math.random() * (getHeight() - (radius * 2)))
                + radius;
        Color color = new Color((int) (Math.random() * 256),
                (int) (Math.random() * 256), (int) (Math.random() * 256));

        AnimatedBall ball = new AnimatedBall(x, y, radius, color);

        list.add(ball);
    }

    // public void formula(MouseEvent clickEvent) {
    // double radius1;
    // int x = 0;
    // double y = 0;
    // int radius = 15;
    // double xM = clickEvent.getX();
    // double yM = clickEvent.getY();

    // radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y) * (yM - y));
    // System.out.println("Radius1 =" + radius1);

    // }

    public void subtract() {
        if (list.size() > 0) {
            list.remove(list.size() - 1); // Remove the last ball
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        for (AnimatedShape ball : list) {
            ball.paint(this, g2d);
        }
        rectangle.paint(this, g2d);
    }

    public void suspend() {
        timer.stop();
    }

    public void resume() {
        timer.start();
    }

    public void setDelay(int delay) {
        this.delay = delay;
        timer.setDelay(delay);
    }
}

public interface AnimatedShape {

    public void update(Rectangle bounds);

    public void paint(JComponent parent, Graphics2D g2d);
}

public abstract class AbstractAnimatedShape implements AnimatedShape {

    private Rectangle bounds;
    private int dx, dy;

    public AbstractAnimatedShape() {
    }

    public void setBounds(Rectangle bounds) {
        this.bounds = bounds;
    }

    public Rectangle getBounds() {
        return bounds;
    }

    public int getDx() {
        return dx;
    }

    public int getDy() {
        return dy;
    }

    public void setDx(int dx) {
        this.dx = dx;
    }

    public void setDy(int dy) {
        this.dy = dy;
    }

    @Override
    public void update(Rectangle parentBounds) {// ball
        Rectangle bounds = getBounds();
        int dx = getDx();
        int dy = getDy();
        bounds.x += dx;
        bounds.y += dy;
        if (bounds.x < parentBounds.x) {
            bounds.x = parentBounds.x;
            setDx(dx *= -1);
        } else if (bounds.x + bounds.width > parentBounds.x
                + parentBounds.width) {
            bounds.x = parentBounds.x + (parentBounds.width - bounds.width);
            setDx(dx *= -1);
        }
        if (bounds.y < parentBounds.y) {
            bounds.y = parentBounds.y;
            setDy(dy *= -1);
        } else if (bounds.y + bounds.height > parentBounds.y
                + parentBounds.height) {
            bounds.y = parentBounds.y
                    + (parentBounds.height - bounds.height);
            setDy(dy *= -1);
        }
    }
}

public class AnimatedBall extends AbstractAnimatedShape {

    private Color color;

    public AnimatedBall(int x, int y, int radius, Color color) {
        setBounds(new Rectangle(x, y / 2, radius * 2, radius * 2));
        this.color = color;
        setDx(Math.random() > 0.5 ? 2 : -2);
        // setDy(Math.random() > 0.5 ? 2 : -2);
    }

    public Color getColor() {
        return color;
    }

    @Override
    public void paint(JComponent parent, Graphics2D g2d) {
        Rectangle bounds = getBounds();
        g2d.setColor(getColor());
        g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
    }
}

public class AnimatedRectange extends AbstractAnimatedShape {

    private Color color;

    public AnimatedRectange(int x, int y, int width, int height, Color color) {
        setBounds(new Rectangle(x, y, width, height));
        this.color = color;
        setDx(2);
    }

    // Don't want to adjust the vertical speed
    @Override
    public void setDy(int dy) {
    }

    @Override
    public void paint(JComponent parent, Graphics2D g2d) {
        Rectangle bounds = getBounds();
        g2d.setColor(color);
        g2d.fill(bounds);
    }

}

/**
 * Main method
 */
public static void main(String[] args) {
    new Game();
}
}
user1803551
  • 12,965
  • 5
  • 47
  • 74
  • @MadProgrammer do you have any idea about this ? –  May 24 '14 at 18:06
  • @usama8800 do you have any idea about this issue ? –  May 24 '14 at 18:20
  • Aren't here anybody which can help me about this ? –  May 24 '14 at 18:32
  • 4
    Follow Java naming conventions. Variable names should NOT start with an upper case character. By the way, people answer questions when they have time. Expecting an answer within minutes of you posting the question is unreasonable. – camickr May 24 '14 at 18:56
  • Ok,I understand @camickr.Thank you. –  May 24 '14 at 19:37
  • See also this related [example](http://stackoverflow.com/a/5312702/230513), – trashgod May 24 '14 at 23:26
  • @trashgod ok I understand that example but I don't want to drag and move it.I want to click and drop it down.In addition, I wrote a funciton which find the mouse and ball coordinates.So,when I make some changes about it,I can achieve my project goal. –  May 25 '14 at 10:53
  • Summoning users with @ is frowned upon. Use @ to reply. – user1803551 May 25 '14 at 11:00
  • You need to remove the <> if you want it to work. – user1803551 May 25 '14 at 11:06

1 Answers1

0

At the end of your mousePressed method, you can go though all AnimatedShape objects, check whether they are an AnimatedBall. When the object is a ball, you can test whether the mouse click hits the ball. The mouse click hits the ball when the distance between the center of the ball and the mouse position is smaller than the ball radius. When the ball is hit, you can set its horizontal speed to 0, and the vertical speed to 5 or so.

for (AnimatedShape as : ballPanel.list)
{
    if (as instanceof AnimatedBall)
    {
        AnimatedBall ball = (AnimatedBall)as;
        Rectangle b = ball.getBounds();
        int ballCenterX = b.x + b.width / 2;
        int ballCenterY = b.y + b.height / 2;
        Point p = new Point(ballCenterX, ballCenterY);
        double d = p.distance(clickEvent.getPoint());
        if (d < radius)
        {
            ball.setDx(0);
            ball.setDy(5);
        }
    }
}

Note

In order to make this work properly, you have to attach this listener to the ballPanel. Originally, you had the line

this.addMouseListener(new MouseListener() {

in your code. You have to change this to

ballPanel.addMouseListener(new MouseListener() {

Otherwise, the mouse coordinates will refer to the wrong component!


Concerning the question from the comment

how can I stop and disapper clickedball's when they crash the bound

You may probably insert method to check this, and call this method in the actionPerformed method of your timer. Further explainations are probably beyond the scope of an anser on a Q&A site. Stackoverflow is not a homework-solution-generator.

Marco13
  • 53,703
  • 9
  • 80
  • 159
  • I read your explanations about your code.I edited my code by your advice.But I don't understand what will I do about your "note" part.Can you explain it widerly or show in a code way ?By the way how can I stop and disapper clickedball's when they crash the bound ? Can I use new stop method and dissapper method to do that ? –  May 25 '14 at 13:06
  • I know StackoverFlow is not a homework-solution-generator but I create some ideas to find the solution but I can't translate into code.By the way,thank you for your advice . –  May 25 '14 at 13:42