CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Feb 2014
    Posts
    3

    Question about Threads/Events

    Hello,

    Thank you for the time!

    a) I have a Ball Object which implements the Runnable interface and traces the various positions of a ball.

    b) I then have a Ball_Bounce JPanel inside a JFrame which creates two instances of the Ball object and then paints them to the JPanel.

    As per my understanding, when the main() program in Ball_Bounce.java is started, there a total of three threads running in this program, one for each ball and one for the main(). What I cannot understand is whenever the balls collide, I end up getting the "Collision" message twice even though the collision is checked only in the main() thread.

    I would be grateful for an explanation for why I am getting the collision message outputted twice and also any suggestions on how I can improve my design of the program as it feels like I am not doing it the right way.

    Thank you!

    Code:
    public class Ball implements Runnable
    {
        private boolean xUp, yUp, xUp1, yUp1;
        private int x, y, xDx, yDy;
        private final int MAX_X = 500, MAX_Y = 500;
        private boolean flag = true;
        private static Thread ball;
    
    
        public  Ball(int xCoordinate, int yCoordinate)
        {
            x = xCoordinate;
            y = yCoordinate;
            xUp = false;
            yUp = false;
            xDx = 1;
            yDy = 1;
    
            ball = new Thread(this);
            ball.start();
    
        }
    
        public int getX()
        {
            return x;
        }
    
        public int getY()
        {
            return y;
        }
    
        public void run()
        {
            while ( flag == true )
            {
                try
                {
                    ball.sleep(12);
                }
                catch ( InterruptedException exception )
                {
                    System.err.println( exception.toString() );
                }
    
                if ( y <= 0 ) {
                    yUp = true;
                    yDy = ( int ) ( Math.random() * 5 + 2 );
                }
    
                else if ( y >= MAX_Y - 50 ) {
                    yDy = ( int ) ( Math.random() * 5 + 2 );
                    yUp = false;
                }
    
                if ( x <= 0 ) {
                    xUp = true;
                    xDx = ( int ) ( Math.random() * 5 + 2 );
                }
    
                else if ( x >= MAX_X - 50 ) {
                    xUp = false;
                    xDx = ( int ) ( Math.random() * 5 + 2 );
                }
    
    
                if ( xUp == true )
                    x += xDx;
                else
                    x -= xDx;
    
                if ( yUp == true )
                    y += yDy;
                else
                    y -= yDy;
    
    
            }
        }
    
    
    }
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.lang.Thread;
    
    public class Ball_Bounce extends JPanel implements ActionListener
    {
        private Ball ball[] = new Ball[2];
        private Timer timer;
        private int count = 0;
    
        public Ball_Bounce()
        {
            timer = new Timer (12, this);
            timer.start();
            ball[0] = new Ball( 300, 250);
            ball[1] = new Ball (450, 450);
    
        }
    
        public void actionPerformed (ActionEvent e)
        {
            repaint();
        }
    
        public void paintComponent( Graphics g )
        {
            super.paintComponent(g);
    
            for (int i = 0; i < 2; i++)
            {
                if (i == 0)
                {
                    Color c = Color.RED;
                    g.setColor (c);
                    g.fillOval( ball[i].getX(), ball[i].getY(), 50, 50 );
                }
                if ( i == 1)
                {
                    Color c = Color.BLUE;
                    g.setColor (c);
                    g.fillOval( ball[i].getX(), ball[i].getY(), 50, 50 );
                }
    
            }
            if (Math.abs(ball[0].getX()-ball[1].getX()) <= 50 && Math.abs(ball[0].getY()-ball[1].getY()) <= 50)
            {
                 JOptionPane.showMessageDialog (null, "Collision");
            }
        }
    
        public static void main (String args [])
        {
            JFrame f = new JFrame ("Bouncing Ball");
            Ball_Bounce b = new Ball_Bounce ();
            f.add (b);
            f.setSize (500,500);
            f.setVisible(true);
        }
    
    }

  2. #2
    Join Date
    Dec 2013
    Posts
    14

    Re: Question about Threads/Events

    You have two instances of Ball objects in the Ball_Bounce object. Hence you get the same message from each one of them.
    Having a separate object to move balls and detect any collusion seems like a bit complex design.
    I would use observer pattern to detect collision among any number of balls ( and get balls that are collided ) and use ball objects themselves to move.

  3. #3
    Join Date
    Feb 2014
    Posts
    3

    Re: Question about Threads/Events

    Hello,

    Thank you for your answers! If you don't mind, could you tell me where I am going wrong with my understanding of the program. Below is how I see it working:

    When the program starts, there are four threads created - main(), ball1, ball2 and the event thread. The paintComponent() is called only in the event thread. So, when the event thread is running and the other threads are waiting their turn, the paintComponent() method should run only once. I fail to see how this method checks for collision of both A with B and B with A when the event thread is running, unless the time slice for this thread is twice the timer delay time.

    Thank you!

  4. #4
    Join Date
    Dec 2013
    Posts
    14

    Re: Question about Threads/Events

    Hello again,

    Your understanding is almost correct : )
    In the paintComponent() method, you are painting components in a for loop.
    If there is a collision, then the Thread in the paintComponent() method should read this twice, once for every iteration.
    If you want to correct this error; you might use a local variable say collisionArea, and when a ball reports a collision then check if you have announced its collision before or not. If you have not announced it yet, it means it is first time we see this new collision and save it to the temp memory and ignore following collision reports for this particular are in the loop. ( Assuming you have more than 2 balls for this design ).

    To my understanding, best way to implement this is to create a stand alone class as "CollusionDetector" and have all balls to update this particular class when they collide with an other object along with the event coordinates. Then this class should decide which objects are involved based on calculations depending on the coordinates and announces it just once.

    For the best results, methods and even classes should only be concerned about doing only one job at a time. Otherwise code gets buggy. Your paintComponent() method is painting components, initializing components and moving components. Also reporting collisions : ) I think separating those into different methods should help.

    Of course, this is my opinion; there is always a better design : )

    Good luck friend!

  5. #5
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: Question about Threads/Events

    Norm

  6. #6
    Join Date
    Feb 2014
    Posts
    3

    Re: Question about Threads/Events

    Hello mephala,

    I cannot thank you enough for such an informative and helpful reply!!

    Regards

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured