[英]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.