Simple Physics Simulation in java not working.

Posted by Static Void Main on Stack Overflow See other posts from Stack Overflow or by Static Void Main
Published on 2010-10-03T20:50:02Z Indexed on 2011/03/18 0:10 UTC
Read the original article Hit count: 216

Dear experts,

I wanted to implement ball physics and as i m newbie, i adapt the code in tutorial http://adam21.web.officelive.com/Documents/JavaPhysicsTutorial.pdf .

i try to follow that as i much as i can, but i m not able to apply all physical phenomenon in code, can somebody please tell me, where i m mistaken or i m still doing some silly programming mistake.

The balls are moving when i m not calling bounce method and i m unable to avail the bounce method and ball are moving towards left side instead of falling/ending on floor**,

Can some body recommend me some better way or similar easy compact way to accomplish this task of applying physics on two ball or more balls with interactivity.

here is code ;

    import java.awt.*;
    public class AdobeBall {

    protected int radius = 20;
    protected Color color;

    // ... Constants
    final static int DIAMETER = 40;

    // ... Instance variables
    private int m_x; // x and y coordinates upper left
    private int m_y;

    private double dx = 3.0; // delta x and y 
    private double dy = 6.0;

    private double m_velocityX; // Pixels to move each time move() is called.
    private double m_velocityY;

    private int m_rightBound; // Maximum permissible x, y values.
    private int m_bottomBound;

    public AdobeBall(int x, int y, double velocityX, double velocityY,
            Color color1) {
        super();
        m_x = x;
        m_y = y;
        m_velocityX = velocityX;
        m_velocityY = velocityY;
        color = color1;
    }

    public double getSpeed() {
        return Math.sqrt((m_x + m_velocityX - m_x) * (m_x + m_velocityX - m_x)
                + (m_y + m_velocityY - m_y) * (m_y + m_velocityY - m_y));
    }

    public void setSpeed(double speed) {
        double currentSpeed = Math.sqrt(dx * dx + dy * dy);
        dx = dx * speed / currentSpeed;
        dy = dy * speed / currentSpeed;
    }

    public void setDirection(double direction) {
        m_velocityX = (int) (Math.cos(direction) * getSpeed());
        m_velocityY = (int) (Math.sin(direction) * getSpeed());
    }

    public double getDirection() {
        double h = ((m_x + dx - m_x) * (m_x + dx - m_x))
                + ((m_y + dy - m_y) * (m_y + dy - m_y));
        double a = (m_x + dx - m_x) / h;
        return a;
    }

    // ======================================================== setBounds
    public void setBounds(int width, int height)  {
        m_rightBound = width - DIAMETER;
        m_bottomBound = height - DIAMETER;
    }

    // ============================================================== move
    public void move()  {

        double gravAmount = 0.02;
        double gravDir = 90; // The direction for the gravity to be in.
        // ... Move the ball at the give velocity.
        m_x += m_velocityX;
        m_y += m_velocityY;

//       ... Bounce the ball off the walls if necessary.
        if (m_x < 0) { // If at or beyond left side
            m_x = 0; // Place against edge and
            m_velocityX = -m_velocityX;

        } else if (m_x > m_rightBound) { // If at or beyond right side
            m_x = m_rightBound; // Place against right edge.
            m_velocityX = -m_velocityX;
        }

        if (m_y < 0) { // if we're at top
            m_y = 0;
            m_velocityY = -m_velocityY;

        } else if (m_y > m_bottomBound) { // if we're at bottom
            m_y = m_bottomBound;
            m_velocityY = -m_velocityY;
        }

     //   double speed = Math.sqrt((m_velocityX * m_velocityX)
     //         + (m_velocityY * m_velocityY));

        // ...Friction stuff 
        double fricMax = 0.02; // You can use any number, preferably less than 1
        double friction = getSpeed();
        if (friction > fricMax)
            friction = fricMax;
        if (m_velocityX >= 0) {
            m_velocityX -= friction;
        }
        if (m_velocityX <= 0) {
            m_velocityX += friction;
        }
        if (m_velocityY >= 0) {
            m_velocityY -= friction;
        }
        if (m_velocityY <= 0) {
            m_velocityY += friction;
        }

        // ...Gravity stuff

        m_velocityX += Math.cos(gravDir) * gravAmount;
        m_velocityY += Math.sin(gravDir) * gravAmount;

    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color newColor)  {
        color = newColor;
    }

    // ============================================= getDiameter, getX, getY
    public int getDiameter() {
        return DIAMETER;
    }

  public double getRadius() {
        return radius; // radius should be a local variable in Ball.
    }

    public int getX() {
        return m_x;
    }

    public int getY() {
        return m_y;
    }

}

using adobeBall:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    public class AdobeBallImplementation implements Runnable {

    private static final long serialVersionUID = 1L;

    private volatile boolean Play;
    private long mFrameDelay;
    private JFrame frame;
    private MyKeyListener pit;

    /** true means mouse was pressed in ball and still in panel. */
    private boolean _canDrag = false;

    private static final int MAX_BALLS = 50; // max number allowed
    private int currentNumBalls = 2; // number currently active
    private AdobeBall[] ball = new AdobeBall[MAX_BALLS];

    public AdobeBallImplementation(Color ballColor) {

        frame = new JFrame("simple gaming loop in java");
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pit = new MyKeyListener();
        pit.setPreferredSize(new Dimension(400, 400));
        frame.setContentPane(pit);

        ball[0] = new AdobeBall(34, 150, 7, 2, Color.YELLOW);
        ball[1] = new AdobeBall(50, 50, 5, 3, Color.BLUE);
        frame.pack();
        frame.setVisible(true);
        frame.setBackground(Color.white);
        start();
        frame.addMouseListener(pit);
        frame.addMouseMotionListener(pit);

    }

    public void start() {
        Play = true;
        Thread t = new Thread(this);
        t.start();
    }

    public void stop() {
        Play = false;
    }

    public void run() {

        while (Play == true) {
            // bounce(ball[0],ball[1]);
            runball();
            pit.repaint();
            try {
                Thread.sleep(mFrameDelay);
            } catch (InterruptedException ie) {
                stop();
            }
        }
    }

    public void drawworld(Graphics g) {

        for (int i = 0; i < currentNumBalls; i++) {
            g.setColor(ball[i].getColor());
            g.fillOval(ball[i].getX(), ball[i].getY(), 40, 40);
        }
    }

    public double pointDistance (double x1, double y1, double x2, double y2) {
        return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
    }

    public void runball() {

        while (Play == true) {
            try {

                for (int i = 0; i < currentNumBalls; i++) {
                    for (int j = 0; j < currentNumBalls; j++) {

                        if (pointDistance(ball[i].getX(), ball[i].getY(),
                                ball[j].getX(), ball[j].getY()) < ball[i]
                                                                       .getRadius()
                                                                       + ball[j].getRadius() + 2) {
                            // bounce(ball[i],ball[j]);
                            ball[i].setBounds(pit.getWidth(), pit.getHeight());
                            ball[i].move();

                            pit.repaint();

                        }
                    }
                }

                try {
                    Thread.sleep(50);
                } catch (Exception e) {
                    System.exit(0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static double pointDirection(int x1, int y1, int x2, int y2) {
        double H = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); // The
        // hypotenuse
        double x = x2 - x1; // The opposite
        double y = y2 - y1; // The adjacent
        double angle = Math.acos(x / H);
        angle = angle * 57.2960285258;
        if (y < 0) {
            angle = 360 - angle;
        }
        return angle;
    }

    public static void bounce(AdobeBall b1, AdobeBall b2) {
        if (b2.getSpeed() == 0 && b1.getSpeed() == 0) {
            // Both balls are stopped.
            b1.setDirection(pointDirection(b1.getX(), b1.getY(), b2.getX(), b2
                    .getY()));
            b2.setDirection(pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
                    .getY()));
            b1.setSpeed(1);
            b2.setSpeed(1);
        } else if (b2.getSpeed() == 0 && b1.getSpeed() != 0) {
            // B1 is moving. B2 is stationary.
            double angle = pointDirection(b1.getX(), b1.getY(), b2.getX(), b2
                    .getY());
            b2.setSpeed(b1.getSpeed());
            b2.setDirection(angle);
            b1.setDirection(angle - 90);
        } else if (b1.getSpeed() == 0 && b2.getSpeed() != 0) {
            // B1 is moving. B2 is stationary.
            double angle = pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
                    .getY());
            b1.setSpeed(b2.getSpeed());
            b1.setDirection(angle);
            b2.setDirection(angle - 90);
        } else {
            // Both balls are moving.
            AdobeBall tmp = b1;
            double angle = pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
                    .getY());
            double origangle = b1.getDirection();
            b1.setDirection(angle + origangle);
            angle = pointDirection(tmp.getX(), tmp.getY(), b2.getX(), b2.getY());
            origangle = b2.getDirection();
            b2.setDirection(angle + origangle);
        }
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new AdobeBallImplementation(Color.red);
            }
        });
    }

}   

*EDIT:*ok splitting the code using new approach for gravity from this forum: this code also not working the ball is not coming on floor:

public void mymove() {

    m_x += m_velocityX;
    m_y += m_velocityY;

    if (m_y + m_bottomBound > 400) {
        m_velocityY *= -0.981;
    //  setY(400 - m_bottomBound);
        m_y = 400 - m_bottomBound;

    }

    // ... Bounce the ball off the walls if necessary.
    if (m_x < 0) { // If at or beyond left side
        m_x = 0; // Place against edge and
        m_velocityX = -m_velocityX;

    } else if (m_x > m_rightBound) { // If at or beyond right side
        m_x = m_rightBound - 20; // Place against right edge.
        m_velocityX = -m_velocityX;
    }

    if (m_y < 0) { // if we're at top
        m_y = 1;
        m_velocityY = -m_velocityY;

    } else if (m_y > m_bottomBound) { // if we're at bottom
        m_y = m_bottomBound - 20;
        m_velocityY = -m_velocityY;

    }
}

thanks a lot for any correction and help.

jibby

© Stack Overflow or respective owner

Related posts about java

Related posts about game-development