繁体   English   中英

Java物理模拟功能的问题

[英]Problems with java physics simulation function

我正在创建此物理模拟,该模拟应该模拟2D平面上空间中天体的运动。 这是非常基本的。 它不应该很密集。 但是,五到六秒钟后,对象消失了,更不用说它们不能正确移动了。 我已经看了太久了,很高兴看到新鲜​​的眼睛。 我只需要知道为什么这些点在五六秒钟后消失了。 不用担心数学上的错误,在找出恒星消失的原因之后,我可以解决这个问题。 请忽略任何糟糕的编程,我已经很长时间没有编程了。

import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
public class PhysicsSimulation extends JFrame implements ActionListener
{
private GamePanel gamePanel = new GamePanel();
private JButton startButton = new JButton("Start");
private JButton quitButton = new JButton("Quit");
private JButton pauseButton = new JButton("Pause");
private boolean running = false;
private boolean paused = false;
private int fps = 60;
private int frameCount = 0;

public PhysicsSimulation()
{
    super("Fixed Timestep Game Loop Test");
    Container cp = getContentPane();
    cp.setLayout(new BorderLayout());
    JPanel p = new JPanel();
    p.setLayout(new GridLayout(1,2));
    p.add(startButton);
    p.add(pauseButton);
    p.add(quitButton);
    cp.add(gamePanel, BorderLayout.CENTER);
    cp.add(p, BorderLayout.SOUTH);
    setSize(800, 800);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    startButton.addActionListener(this);
    quitButton.addActionListener(this);
    pauseButton.addActionListener(this);
}

public static void main(String[] args)
{
    PhysicsSimulation phy = new PhysicsSimulation();
    phy.setVisible(true);
}

public void actionPerformed(ActionEvent e)
{
    Object s = e.getSource();
    if (s == startButton)
    {
        running = !running;
        if (running)
        {
            startButton.setText("Stop");
            runGameLoop();
        }
        else
        {
            startButton.setText("Start");
        }
    }
    else if (s == pauseButton)
    {
        paused = !paused;
        if (paused)
        {
            pauseButton.setText("Unpause");
        }
        else
        {
            pauseButton.setText("Pause");
        }
    }
    else if (s == quitButton)
    {
        System.exit(0);
    }
}

public void runGameLoop()
{
    Thread loop = new Thread()
    {
        public void run()
        {
            gameLoop();
        }
    };
    loop.start();
}

private void gameLoop()
{
    final double GAME_HERTZ = 30.0;
    final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
    final int MAX_UPDATES_BEFORE_RENDER = 5;
    double lastUpdateTime = System.nanoTime();
    double lastRenderTime = System.nanoTime();

    final double TARGET_FPS = 60;
    final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;

    int lastSecondTime = (int) (lastUpdateTime / 1000000000);

    while (running)
    {
        double now = System.nanoTime();
        int updateCount = 0;

        if (!paused)
        {
            while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
            {
                updateGame();
                lastUpdateTime += TIME_BETWEEN_UPDATES;
                updateCount++;
            }

            if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
            {
                lastUpdateTime = now - TIME_BETWEEN_UPDATES;
            }

            float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
            drawGame(interpolation);
            lastRenderTime = now;

            int thisSecond = (int) (lastUpdateTime / 1000000000);
            if (thisSecond > lastSecondTime)
            {
                System.out.println("NEW SECOND " + thisSecond + " " + frameCount);
                fps = frameCount;
                frameCount = 0;
                lastSecondTime = thisSecond;
            }

            while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
            {
                Thread.yield();

                try {Thread.sleep(1);} catch(Exception e) {}

                now = System.nanoTime();
            }
        }
    }
}

private void updateGame()
{
    gamePanel.update();
}

private void drawGame(float interpolation)
{
    gamePanel.setInterpolation(interpolation);
    gamePanel.repaint();
}

private class GamePanel extends JPanel
{
    float interpolation;
    ArrayList<Star> list = new ArrayList<Star>();
    double G = .00000000006674;

    public GamePanel()
    {

        for(int i = 0; i < 100; i++){
            list.add(i,new Star());
        }
    }

    public void setInterpolation(float interp)
    {
        interpolation = interp;
    }

    public void update()
    {
        for(int i = 0; i < list.size(); i++){
            list.get(i).setX(list.get(i).getLastX()+list.get(i).getXVelocity());
            list.get(i).setY(list.get(i).getLastY()+list.get(i).getYVelocity());
            for(int j = 0; j < list.size(); j++){
                if(j != i){
                    if(list.get(i).getX() == list.get(j).getX() && list.get(i).getY() == list.get(j).getY()){
                        list.get(i).setXVelocity((float) (list.get(i).getXVelocity()));
                        list.get(i).setYVelocity((float) (list.get(i).getYVelocity()));
                    }
                    else{
                        list.get(i).setXVelocity((float) (list.get(i).getXVelocity() + calcVelocity(list.get(i),list.get(j),0)));
                        list.get(i).setYVelocity((float) (list.get(i).getYVelocity() + calcVelocity(list.get(i),list.get(j),1)));
                    }
                }
            }
        }
    }

    public float calcVelocity(Star a, Star b, int var){
        double velocity = 0;
        velocity = (double) Math.pow(((2*G*a.getMass()*b.getMass()*delta(a,b,var))/(Math.pow(delta(a,b,var),2)*a.getMass())),.5);
        return (float) velocity;
    }

    public float delta(Star a, Star b, int var){
        float diff = 0;
        if(var == 0)
            diff = Math.abs(a.getX()-b.getX());
        else if(var == 1)
            diff = Math.abs(a.getY()-b.getY());
        return diff;
    }

    public void paintComponent(Graphics g)
    {
        g.setColor(Color.BLACK);
        g.fillRect(0,0,800,740);

        g.setColor(Color.WHITE);
        for(int i = 0; i < list.size(); i++){
            g.fillRect((int)list.get(i).getX(),(int)list.get(i).getY(),1,1);
        }

        g.drawString("FPS: " + fps, 5, 10);

        frameCount++;
    }
}

private class Star{
    float x, y, lastX, lastY;
    float xVelocity, yVelocity;
    float mass;

    public Star(){
        x = (float) (Math.random() * 800);
        y = (float) (Math.random() * 740);
        lastX = x;
        lastY = y;
        xVelocity = 0;
        yVelocity = 0;
        mass = (float) (Math.random() * 800000000);
    }

    public float getX(){
        return x;
    }

    public float getY(){
        return y;
    }

    public float getXVelocity(){
        return xVelocity;
    }

    public float getYVelocity(){
        return yVelocity;
    }

    public float getMass(){
        return mass;
    }

    public float getLastX(){
        return lastX;
    }

    public float getLastY(){
        return lastY;
    }

    public void setX(float X){
        x = X;
    }

    public void setY(float Y){
        y = Y;
    }

    public void setXVelocity(float velocity){
        xVelocity = velocity;
    }

    public void setYVelocity(float velocity){
        yVelocity = velocity;
    }

    public void setLastX(float X){
        lastX = X;
    }

    public void setLastY(float Y){
        lastY = Y;
    }
}
}

好的,感谢大家,我发现我需要再添加一些if语句来处理距离为零时的情况。

原版的:

if(list.get(i).getX() == list.get(j).getX() && list.get(i).getY() == list.get(j).getY()){
    list.get(i).setXVelocity((float) (list.get(i).getXVelocity()));
    list.get(i).setYVelocity((float) (list.get(i).getYVelocity()));
}
else{
    list.get(i).setXVelocity((float) (list.get(i).getXVelocity() + calcVelocity(list.get(i),list.get(j),0)));
    list.get(i).setYVelocity((float) (list.get(i).getYVelocity() + calcVelocity(list.get(i),list.get(j),1)));
}

修改后:

if(list.get(i).getX() == list.get(j).getX()){
    list.get(i).setXVelocity((float) (list.get(i).getXVelocity())+1);
    list.get(i).setYVelocity((float) (list.get(i).getYVelocity() + calcVelocity(list.get(i),list.get(j),1)));
}
else if(list.get(i).getY() == list.get(j).getY()){
    list.get(i).setYVelocity((float) (list.get(i).getYVelocity())+1);
    list.get(i).setXVelocity((float) (list.get(i).getXVelocity() + calcVelocity(list.get(i),list.get(j),0)));
}
else if(list.get(i).getX() == list.get(j).getX() && list.get(i).getY() == list.get(j).getY()){
    list.get(i).setXVelocity((float) (list.get(i).getXVelocity())+1);
    list.get(i).setYVelocity((float) (list.get(i).getYVelocity())+1);
}
else{
    list.get(i).setXVelocity((float) (list.get(i).getXVelocity() + calcVelocity(list.get(i),list.get(j),0)));
    list.get(i).setYVelocity((float) (list.get(i).getYVelocity() + calcVelocity(list.get(i),list.get(j),1)));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM