Java 2d空间重力无法正常工作

时间:2014-08-02 17:38:24

标签: java

我正在尝试用真实物理在java中制作2D游戏。游戏应该从上到下视图设置在空间中。我可以解释视图的最佳方法是使用此链接:3d graph found one gooogle images with search "3d graph xyz"。应该设置视图,以便从+ y的顶部向-y看。

在游戏中我目前只展示一个太阳和一个行星来测试重力。然而,当我运行游戏时,行星只会向右移动,远离太阳。我相信这是因为我把它移到java时误用了等式。作为参考,我使用的方程是牛顿万有引力定律(F =(G * M1 * M2)/ D ^ 2)和牛顿第二运动定律(F = MA,但用作A = F / M)。

简而言之,我的问题是我的方程怎么办?我将在下面发布我的所有代码,但公平警告它的目的是扩展,因此目前有很多过剩。

感谢您提前提供任何帮助。

核心课程:

package src.main;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import src.main.input.Input;
import src.main.input.InputHandler;
import src.main.map.Map;

public class Core extends JPanel
{

private static InputHandler iHandler = new InputHandler();
private static Input input = new Input(iHandler);
private long ticks;
private Map map;
public static Dimension SIZE;

public static Random rand = new Random();

public Core(Dimension d)
{
    setPreferredSize(d);

    SIZE = d;
    ticks = 0;
    map = new Map(SIZE.width, SIZE.height);

    start();
}

public synchronized void update()
{
    ticks++;
    iHandler.update(ticks);
    /*if (iHandler.getWheelRotation() != 0)
    {
        int i = iHandler.getWheelRotation();
        map.changeMagnification(i > 0);
        if (i > 0)
            i--;
        else
            i++;
        iHandler.setWheelRotation(i);
        if (i < 0 && map.getMagnification() == 0)
            iHandler.setWheelRotation(0);
        if (i > 0 && map.getMagnification() == Map.MAX_MAGNIFY)
            iHandler.setWheelRotation(0);
    }*/

    map.update(ticks);
}

public synchronized void paintComponent(Graphics g2)
{
    Graphics2D g = (Graphics2D) g2;
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    super.paintComponent(g);

    g.setColor(Color.BLACK);
    g.fillRect(0, 0, SIZE.width, SIZE.height);

    map.draw(g);
}

public void start()
{
    Thread thread = new Thread()
    {
        public void run()
        {
            while (true)
            {
                long time = System.currentTimeMillis();

                update();
                repaint();

                time = (1000 / 128) - (System.currentTimeMillis() - time);

                if (time > 0)
                {
                    try
                    {
                        Thread.sleep(time);
                    } catch (Exception ex)
                    {
                        ex.printStackTrace();
                    }
                }
            }
        }
    };
    thread.start();
}

public static void main(String args[])
{
    SwingUtilities.invokeLater(new Runnable()
    {
        Rectangle r = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getDefaultConfiguration().getBounds();

        public void run()
        {
            JFrame frame = new JFrame();
            frame.setUndecorated(true);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setContentPane(new Core(new Dimension(r.width, r.height)));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            frame.addKeyListener(input);
            frame.addMouseListener(input);
            frame.addMouseMotionListener(input);
            frame.addMouseWheelListener(input);
        }
    });
}
}

地图类:

package src.main.map;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.ArrayList;

import src.main.Core;
import src.main.celestials.SolarSystem;

public class Map
{

private int magnification;
public static final int MAX_MAGNIFY = 15;
private ArrayList<SolarSystem> systems = new ArrayList<SolarSystem>();

public Map(int x, int y)
{
    SolarSystem s=new SolarSystem(new Point(500,500), "sun", (int) (1.9891 * Math.pow(10, 30)));
    s.addPlanet(new Point(550, 550), "planet");
    systems.add(s);


}

public void update(long ticks)
{
    for(int i = 0; i < systems.size(); i++)
        systems.get(i).update(ticks);
}

public void draw(Graphics2D g)
{
    g.setColor(Color.DARK_GRAY);



    magnification= 1;


    for(int i=0; i<systems.size(); i++)
    {
        systems.get(i).draw(g, magnification);
    }


}



public int getMagnification()
{
    return magnification;
}

public void changeMagnification(boolean bigger)
{
    if (bigger)
        magnification++;
    else
        magnification--;

    if (magnification > MAX_MAGNIFY)
        magnification = MAX_MAGNIFY;
    if (magnification < 1)
        magnification = 1;
}
}

身体等级:

package src.main.celestials;

import java.awt.Point;

import src.main.Core;
import src.main.map.Map;

public abstract class Body
{
protected String name;
protected double x, y, mass;

public Body(Point t, String s, int m)
{
    x = t.x;
    y = t.y;
    name = s;
    mass = m;
}

public String getName()
{
    return name;
}

public void setName(String name)
{
    this.name = name;
}

public double getX() {
    return x;
}

public void setX(double x) {
    this.x = x;
}

public double getY() {
    return y;
}

public void setY(double y) {
    this.y = y;
}

public double getMass() {
    return mass;
}

public void setMass(double mass) {
    this.mass = mass;
}

public abstract void update(long ticks);
}

SolarSystem类:

package src.main.celestials;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import src.main.celestials.Planet;

public class SolarSystem extends Body {

private ArrayList<Planet> planets = new ArrayList<Planet>();
private BufferedImage[] images = new BufferedImage[7];
private BufferedImage sun;

public SolarSystem(Point t, String s, int m) {
    super(t, s, m);

    try
    {
        String loc = System.getProperty("user.home") + "\\Desktop\\Proof of Concept Game\\Proof of Concept Game\\Gravity Test\\Suns\\";
        images[0] = ImageIO.read(new File(loc + "Sun_Blue.png"));
        images[1] = ImageIO.read(new File(loc + "Sun_BlueWhite.png"));
        images[2] = ImageIO.read(new File(loc + "Sun_Orange.png"));
        images[3] = ImageIO.read(new File(loc + "Sun_Red.png"));
        images[4] = ImageIO.read(new File(loc + "Sun_White.png"));
        images[5] = ImageIO.read(new File(loc + "Sun_Yellow.png"));
        images[6] = ImageIO.read(new File(loc + "Sun_YellowWhite.png"));
    } catch (Exception e)
    {
        e.printStackTrace();
    }

    sun = images[(int) (Math.random() * images.length)];
}
//earth mass:5.97219 × 10^24KG
    //sun mass: 1.9891 × 10^30KG
    //sun/earth ratio: 333060.4016
@Override
public void update(long ticks) {
    // run interactions between planets and solar systems
    for(int i=0; i<planets.size(); i++)
    {
        planets.get(i).setxAccel(genAccelX(i));
        planets.get(i).setyAccel(genAccelY(i));
    }

    // update using acceleration and velocity
    for(int i=0; i<planets.size(); i++)
    {
        planets.get(i).update(ticks);
    }

}
public void addPlanet(Point point, String name)
{
    planets.add(new Planet(point, name, (int) (5.97219*Math.pow(10, 24))));
}
/*public double genAccel(int i)
{
    double G=6.67*Math.pow(10, -11);
    double Dx=Math.pow(planets.get(i).getX()-getX(), 2);
    double Dy=Math.pow(planets.get(i).getY()-getY(), 2);
    double D=Math.sqrt(Dx+Dy);
    return G*planets.get(i).getMass()/Math.pow(D, 2);

}
public double genAccelX(int i)
{
    double Dx=Math.pow(planets.get(i).getX()-getX(), 2);
    double Dy=Math.pow(planets.get(i).getY()-getY(), 2);
    double D=Math.sqrt(Dx+Dy);
    double A=genAccel(i);
    return Dx*A/D;
}
public double genAccelY(int i)
{
    double Dx=Math.pow(planets.get(i).getX()-getX(), 2);
    double Dy=Math.pow(planets.get(i).getY()-getY(), 2);
    double D=Math.sqrt(Dx+Dy);
    double A=genAccel(i);
    return Dy*A/D;
}*/

public double genAccelX(int i)
{
    double x1=0;
    double x2=0;
    /*if(getX()>planets.get(i).getX())
    {*/
        x1=getX();
        x2=planets.get(i).getX();
    /*}
    else
    {
        x1=planets.get(i).getX();
        x2=getX();
    }*/
    double G=6.67e-11;
    double d=x1-x2;
    d*=d;
    planets.get(i).setxForce((G*getMass()*planets.get(i).getMass())/d);
    return planets.get(i).getxForce()/planets.get(i).getMass();
}
public double genAccelY(int i)
{
    double y1=0;
    double y2=0;
    /*if(getY()<planets.get(i).getY())
    {*/
        y1=getY();
        y2=planets.get(i).getY();
    /*}
    else
    {
        y1=planets.get(i).getY();
        y2=getY();
    }*/
    double G=6.67e-11;
    double d=y1-y2;
    d*=d;
    planets.get(i).setyForce((G*getMass()*planets.get(i).getMass())/d);
    return planets.get(i).getyForce()/planets.get(i).getMass();
}

public void draw(Graphics2D g, int magnification) {
    g.drawImage(sun, (int)(x) * magnification + 2, (int)(y) * magnification + 2, 50, 50, null);
    for(int i=0; i<planets.size(); i++)
    {
        g.setColor(Color.PINK);
        g.fillOval((int)planets.get(i).getX(), (int)planets.get(i).getY(), 20, 20);
    }
}
}

星球类:

package src.main.celestials;

import java.awt.Point;

public class Planet extends Body {

double xForce, yForce, xAccel, yAccel, xVel, yVel;


public Planet(Point t, String s, int m) {
    super(t, s, m);

}

public double getxForce() {
    return xForce;
}

public void setxForce(double xForce) {
    this.xForce = xForce;
}

public double getyForce() {
    return yForce;
}

public void setyForce(double yForce) {
    this.yForce = yForce;
}

public double getxAccel() {
    return xAccel;
}

public void setxAccel(double xAccel) {
    this.xAccel = xAccel;
}

public double getyAccel() {
    return yAccel;
}

public void setyAccel(double yAccel) {
    this.yAccel = yAccel;
}

public double getxVel() {
    return xVel;
}

public void setxVel(double xVel) {
    this.xVel = xVel;
}

public double getyVel() {
    return yVel;
}

public void setyVel(double yVel) {
    this.yVel = yVel;
}

@Override
public void update(long ticks) {
    xVel+=xAccel;
    yVel+=yAccel;
    x+=xVel;
    y+=yVel;
    System.out.println("X: "+(int)x+"\t\t"+"Y: "+(int)y);
    System.out.println("XVel: "+xVel+"\t\t"+"YVel: "+yVel);
    System.out.println("XAccel: "+xAccel+"\t"+"YAccel: "+yAccel);

}

}

1 个答案:

答案 0 :(得分:0)

首先,关于你的评论

  

我以为我在java论坛?

(也是@ PM77-1 :) StackOverflow完全不是 论坛!另请参阅https://meta.stackexchange.com/a/92110。这是一个问题和答案&#34;网站,这对你应该如何提出了一些约束,以及作为回应的期望。 (实际上,我在这里写这篇文章的事实已经违反了这些规则,并且我冒着失败的风险)。当前形式的问题几乎不适合StackExchange网络的任何站点。如果你在这里写一个问题,那么你应该......

  • 包含清除焦点问题(即超出&#34的问题;我的代码有什么问题?&#34;)
  • 提供Minimal, Complete, and Verifiable example(如果可能,最好,作为单个代码块,不依赖于其他不相关的类,也不依赖于外部资源等。)

那就是说,关于你的实际问题&#34;:你使用的公式是正确的。但它没有得到适当的实施。公式是

Law

(根据Wikipedia

&#34; r&#34;是指物体质心之间的距离

在您的代码中,您尝试使用SolarSystem#genAccelXSolarSystem#genAccelY方法实现此目的:

...
double x1=0;
double x2=0;
x1=getX();
x2=planets.get(i).getX();
double G=6.67e-11;
double d=x1-x2;
d*=d;
planets.get(i).setxForce((G*getMass()*planets.get(i).getMass())/d);
return planets.get(i).getxForce()/planets.get(i).getMass();

但问题是你要为x和y分别计算 。因此,由此产生的力量正在失去其实际方向(并且&#34;错误&#34;无论如何)。

简单地说:你在那里计算的d否定,因为行星应该移动到 left 。但是通过d*=d,它变为正面(而且,这个星球正在向向右移动


解决方案:

您应该将所有位置,速度和力描述为向量,而不是分别为x和y计算所有内容。基本上,它将归结为像

这样的类
class Vector {
    private double x, y;

    // Setters, getters...
    ....

    double distanceSquared(Vector other) {
        double dx = x - other.x;
        double dy = y - other.y;
        return Math.sqrt(dx*dx+dy*dy);
    }
    double distance(Vector other) {
        return Math.sqrt(distanceSquared(other));
    }

    // Some other useful methods:
    double length() { ... }
    void normalize(double factor) { ... }
    void scale(double factor) { ... }
    void add(Vector other) { ... }
    void addScaled(double factor, Vector other) { ... }
    void sub(Vector other) { ... }
    Vector difference(Vector other) { ... }
}

鉴于这样一个类,计算力和加速度的方法可能大致看起来像这样:

// The bodies here may be the sun and a planet:
public double computeForceStrength(Body body0, Body body1)
{
    double G=6.67e-11;
    Vector position0 = body0.getPosition();
    Vector position1 = body1.getPosition();
    double distanceSquared = position0.distanceSquared(position1);

    // The formula from wikipedia:
    double f = G * body0.getMass() * body1.getMass() / distanceSquared;
    return f;
}

void performSomeTimeStep(Body body0, Body body1)
{
    Vector direction = position1.difference(position0);
    direction.normalize();

    double f = computeForceStrength(body0, body1);
    body0.getVelocity().addScaled(direction,  f / body0.getMass());
    body1.getVelocity().addScaled(direction, -f / body1.getMass());
}

(只是为了显示基本想法 - 再次:许多自由度)


代码还有其他几个(风格)问题,但......当它工作时,您可能希望将其提交给https://codereview.stackexchange.com/ ....