java中的简单物理模拟不起作用。

java中的简单物理模拟不起作用。,java,implementation,simulation,physics,Java,Implementation,Simulation,Physics,我想实现球物理,因为我是新手,我在教程中修改了代码 我尽我所能地遵循这一点, 但我不能在代码中应用所有物理现象,有人能告诉我,我错在哪里了,或者我还在犯一些愚蠢的编程错误 当我没有调用bounce method时,球在移动,我无法使用bounce method,球向左侧移动,而不是落下/落在地板上** 有人能给我推荐一些更好的方法或类似的简单紧凑的方法来完成这个任务,在两个球或更多的球上应用物理交互 这是代码 import java.awt.*; public class Ad

我想实现球物理,因为我是新手,我在教程中修改了代码

我尽我所能地遵循这一点, 但我不能在代码中应用所有物理现象,有人能告诉我,我错在哪里了,或者我还在犯一些愚蠢的编程错误

当我没有调用bounce method时,球在移动,我无法使用bounce method,球向左侧移动,而不是落下/落在地板上**

有人能给我推荐一些更好的方法或类似的简单紧凑的方法来完成这个任务,在两个球或更多的球上应用物理交互

这是代码

    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;
    }

}
import java.awt.*;
公共类AdobeBall{
保护整数半径=20;
保护色;
//…常数
最终静态内径=40;
//…实例变量
private int m_x;//左上角的x和y坐标
私人国际博物馆;
私有双dx=3.0;//增量x和y
私人双dy=6.0;
private double m_velocityX;//每次调用move()时要移动的像素。
私人双m_velocityY;
private int m_rightbund;//允许的最大x,y值。
私有内部m_底部边界;
公共ADOBEBOLL(整数x,整数y,双速度yx,双速度yy,
颜色(1){
超级();
m_x=x;
m_y=y;
m_velocityX=velocityX;
m_velocityY=velocityY;
颜色=颜色1;
}
公共双getSpeed(){
返回Math.sqrt((mux+muvelocityx-mux)*(mux+muvelocityx-mux)
+(m_y+m_velocityY-m_y)*(m_y+m_velocityY-m_y));
}
公共无效设置速度(双速){
双电流速度=数学sqrt(dx*dx+dy*dy);
dx=dx*速度/当前速度;
dy=dy*速度/当前速度;
}
公共方向(双向){
m_velocityX=(int)(Math.cos(direction)*getSpeed());
m_velocityY=(int)(Math.sin(direction)*getSpeed());
}
公共双向{
双h=((mux+dx-mux)*(mux+dx-mux))
+((muy+dy-muy)*(muy+dy-muy));
双a=(mux+dx-mux)/h;
返回a;
}
//===========================================================================================
公共空心收进边界(内部宽度、内部高度){
m_rightbund=宽度-直径;
m_底部边界=高度-直径;
}
//==================================================================================================================移动
公开作废动议(){
双倍金额=0.02;
double gravDir=90;//重力的方向。
//…以给定的速度移动球。
m_x+=m_速度x;
m_y+=m_速度y;
//…必要时将球弹离墙壁。
如果(m_x<0){//如果在左侧或左侧以外
m_x=0;//靠边放置,并
m_-velocityX=-m_-velocityX;
}else如果(m_x>m_rightbund){//如果在右侧或右侧之外
m_x=m_rightbund;//靠右边缘放置。
m_-velocityX=-m_-velocityX;
}
如果(m_y<0){//如果我们在顶部
m_y=0;
m_-velocityY=-m_-velocityY;
}如果(m_y>m_bottomBound){//如果我们在底部
m_y=m_底界;
m_-velocityY=-m_-velocityY;
}
//双速=数学sqrt((m_-velocityX*m_-velocityX)
//+(m_-velocityY*m_-velocityY));
//…摩擦材料
double fricMax=0.02;//您可以使用任何数字,最好小于1
双摩擦=getSpeed();
如果(摩擦力>摩擦系数最大值)
摩擦=fricMax;
如果(m_velocityX>=0){
m_速度x-=摩擦力;
}
如果(m_velocityX=0){
m_速度y-=摩擦力;
}
如果(m_velocityY 400){
m_velocityY*=-0.981;
//setY(400米深底部边界);
m_y=400-m_底界;
}
//…必要时将球弹离墙壁。
如果(m_x<0){//如果在左侧或左侧以外
m_x=0;//靠边放置,并
m_-velocityX=-m_-velocityX;
}else如果(m_x>m_rightbund){//如果在右侧或右侧之外
m_x=m_rightbund-20;//靠右边缘放置。
m_-velocityX=-m_-velocityX;
}
如果(m_y<0){//如果我们在顶部
m_y=1;
m_-velocityY=-m_-velocityY;
}如果(m_y>m_bottomBound){//如果我们在底部
m_y=m_底部边界-20;
m_-velocityY=-m_-velocityY;
}
}
非常感谢您的纠正和帮助


jibby

好的,还没有解决问题。但有几点可能会有所帮助:

1-Math.sin/cos以弧度为单位计算角度(这可能有点帮助)。-AdobeBall

2-您必须为move()的每次调用计算gravDir,因为m_velocityX/Y可能会改变方向-AdobeBall

3-你在runball()中的主循环将同一个球取两次,并与它自身进行比较…在第二个循环中使用j=i+1

4-你在线程循环中调用runball()。所以我希望球无论如何都会移动…不仅仅是如果你调用bounce()。我说的对吗


您可以更正代码并重试。然后发布新闻!:)

目前我无法运行java,因此无法测试您的代码,但我注意到以下几点:

  • 对于(几乎)相同的事情,你有两组独立的变量:{dx,dy}和{m_velocityX,m_velocityY}。因此,你的getSpeed和setSpeed是独立的,getDirection和Setdirection也是独立的。我不能相信这会按照你期望的方式工作。
  • 你的坐标看起来有点混乱(这可能是球“落”到左边的原因)。你似乎是从X方向顺时针测量角度,这是不标准的。编辑:Plínio Pantaleão已经确定了落到左边的原因。
        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);
                }
            });
        }
    
    }   
    
    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;
    
        }
    }
    
    if (m_y + m_bottomBound > 400) {
        m_velocityY *= -0.981;
        //  setY(400 - m_bottomBound);
        m_y = 400 - m_bottomBound;
    }
    
    // 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;