Simple physical simulation in Java does not work properly

I want to achieve ball physics, as a novice, I adjust the code in the tutorial.

I try to do my best, but I can't apply all physical phenomena in the code. Someone can tell me that I'm wrong or I'm still making some stupid programming mistakes

When I didn't call the bounce method and I couldn't use the bounce method and the ball moved to the left instead of falling / ending on the floor, the ball was moving * *,

Some bodies can recommend me some better or similar simple ways to accomplish this task, applying physics to the interaction of two or more balls

This is the 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 Adobe ball:

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[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(),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(),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(),b1
                    .getY());
            double origangle = b1.getDirection();
            b1.setDirection(angle + origangle);
            angle = pointDirection(tmp.getX(),tmp.getY(),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: * make sure to split the code from this forum using the new gravity method: this code does not work, and the ball is not present:

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;

    }
}

Thank you very much for any correction and help

jibby

Solution

At present, I can't run Java, so I can't test your code, but I noticed some things:

>For (almost) the same thing, you have two sets of independent variables: {DX, Dy} and {m_velocityx, m_velocityy} Therefore, getspeed and setspeed are independent, as are getdirection and setdirection I can't believe it will work the way you expect. > Your coordinates look a little confused (which may be why the ball "falls" to the left) You seem to measure the angle clockwise from the X direction, which is not standard Editor: PL í niopantale ã o has determined the reason for the tilt to the left. > Your code seems to involve simple linear motion, bouncing, gravity and friction You should implement and test these at once I first suggest motion, then add bounce, friction and gravity (in any order), and finally combine them

Edit: this gravity code is wrong:

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

First, you use 400 as the "magic number"; I don't know what it stands for Then, you limit the effect to the area near the top of the screen for unclear reasons At the end of the function, you change m in a meaningless way_ y. And (perhaps) worst of all, you have gravity reversal and doubling vertical velocity, which is not the way gravity works

Try this:

// You will have to adjust this. Start with a small value and increase it until
// you see an effect.
final static double GRAVITY = 0.1;

// Note that +y is down,so accelerating downward means increasing vY
m_veLocityY += GRAVITY;
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>