Java 弹丸运动的实现

Java 弹丸运动的实现,java,physics,Java,Physics,我用Java创建了一个带有用户界面的投射物运动模拟。 该程序允许用户输入初始值以计算对象的投射物。我目前没有任何设置将投射物绘制到屏幕上 我有一个单独的spring worker线程在后台处理模拟代码 我还添加了碰撞检测,这样当物体撞击地面时,它会反弹并继续这样做,直到循环退出 我的方程式对于我想要达到的目标是不正确的 在以下初始条件下,以下是输出数据的绘图结果: Initial Conditions: Angle: 30 degrees; Initial Speed 8.66 m/s; Hei

我用Java创建了一个带有用户界面的投射物运动模拟。 该程序允许用户输入初始值以计算对象的投射物。我目前没有任何设置将投射物绘制到屏幕上

我有一个单独的spring worker线程在后台处理模拟代码

我还添加了碰撞检测,这样当物体撞击地面时,它会反弹并继续这样做,直到循环退出

我的方程式对于我想要达到的目标是不正确的

在以下初始条件下,以下是输出数据的绘图结果:

Initial Conditions:
Angle: 30 degrees;
Initial Speed 8.66 m/s;
Height: 50 m;
Elasticity of object: .5 coefficient of restitution in the y direction;
Acceleration: -9.8 m/s^2;
No acceleration in the x direction

似乎一旦模拟开始,y就变得越来越大,因此循环永远不会自行退出

代码如下:

    //This class will handle all time consuming activities
class Simulation extends SwingWorker<Void, Void>
{
    //Execute time consuming task
    protected Void doInBackground() throws Exception 
    {
        FileWriter fstream = new FileWriter("output.txt");

        BufferedWriter out = new BufferedWriter(fstream);

        double angle = Double.valueOf(angleText.getText());
        double radians = angle * (Math.PI/180); 
        double vel = Double.valueOf(speedText.getText()); 
        double mass = Double.valueOf(massText.getText()); 
        double y = Double.valueOf(heightText.getText());
        double x = 0;
        double epX = Double.valueOf(epxText.getText());
        double epY = Double.valueOf(epyText.getText());
        double ax = Double.valueOf(accxText.getText());
        double ay = Double.valueOf(accyText.getText()); 

        int numBounces = 0;
        double deltaTime = .00000001; 
        double total_velocity = 0.0;
        double time = 0.0;

        String fs; 

        angle = angle * Math.PI / 180; 

        while(numBounces < 10)
        {
            //Increment Time
            time = time + deltaTime;

            //Calculate new values for velocity[x] and velocity[y]
            double vx = (vel*Math.cos(angle)) + ax*time;;
            double vy = (vel*Math.sin(angle)) + ay*time; 

            //Calculate new values for x and y
            x = x + vx*time;
            y = y + vy*time + .5*ay*(time*time); 

            System.out.format("%.3f\n", y); 

            fs = String.format("%f\t %f\t %f\t %f\t %f\t %f\t %f\t\n", ax, ay, x, y, vx, vy, time); 

            out.write(fs); 

            //If ball hits ground: y < 0
            if(y < 0)
            {
                numBounces++;

                System.out.println("Number of Bounces: " + numBounces); 

                //Why is this statement needed if the velocity in the y direction is already being reversed?
                vy = -vy - ay*time; //  vy = -vy - ay*time; 

                //Calculate angle
                angle = Math.atan(vy/vx);

                angle = angle * Math.PI / 180; 

                //Calculate total velocity
                total_velocity = Math.sqrt((vy*vy) + (vx*vx));

                //Velocity with elasticity factored in
                total_velocity = Math.sqrt((epY) * total_velocity);

                //New velocities for when ball makes next trip
                vy = total_velocity*Math.sin(angle); 
                vx = total_velocity*Math.cos(angle);

                out.write(fs); 

            }

            //Draw projectile

                //Thread.sleep(.00001); //Sleep for deltaTime - 10 nanoseconds or draw after n number of points
        }

        out.close(); 

        return null;
    }

    //SwingWorker lets you execute code on the event dispatching thread. Also allows you to update the GUI
    public void done()
    {
        try
        {               
            /*
            rangeText.setText(" " + x);
            heightTText.setText(" " + y); 
            timeText.setText(" " + time);
             */
        }

        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
//此类将处理所有耗时的活动
类模拟扩展了SwingWorker
{
//执行耗时的任务
受保护的Void doInBackground()引发异常
{
FileWriter fstream=新的FileWriter(“output.txt”);
BufferedWriter out=新的BufferedWriter(fstream);
double angle=double.valueOf(angleText.getText());
双弧度=角度*(数学PI/180);
double-vel=double.valueOf(speedText.getText());
double mass=double.valueOf(massText.getText());
double y=double.valueOf(heightText.getText());
双x=0;
double-epX=double.valueOf(epxText.getText());
double-epY=double.valueOf(epyText.getText());
double ax=double.valueOf(accxText.getText());
double ay=double.valueOf(accyText.getText());
int numBounces=0;
双增量=.00000001;
两倍总流速=0.0;
双倍时间=0.0;
字符串fs;
角度=角度*Math.PI/180;
而(数量盎司<10)
{
//增量时间
时间=时间+增量时间;
//计算速度[x]和速度[y]的新值
双vx=(水平*数学cos(角度))+ax*时间;;
双vy=(水平*数学正弦(角度))+ay*时间;
//计算x和y的新值
x=x+vx*时间;
y=y+vy*时间+0.5*ay*(时间*时间);
系统输出格式(“%.3f\n”,y);
fs=String.format(“%f\t%f\t%f\t%f\t%f\t%f\t%f\t\n”,ax,ay,x,y,vx,vy,time);
out.write(fs);
//如果球落地:y<0
if(y<0)
{
numBounces++;
System.out.println(“反弹次数:“+numBounces”);
//如果y方向上的速度已经反转,为什么需要这个陈述?
vy=-vy-ay*时间;//vy=-vy-ay*时间;
//计算角度
角度=数学atan(vy/vx);
角度=角度*Math.PI/180;
//计算总速度
总速度=数学sqrt((vy*vy)+(vx*vx));
//考虑弹性的速度
总速度=数学sqrt((epY)*总速度);
//下一次击球时的新速度
vy=总速度*数学sin(角度);
vx=总速度*数学cos(角度);
out.write(fs);
}
//牵引弹
//Thread.sleep(.00001);//延迟睡眠时间-10纳秒或在n个点数后绘制
}
out.close();
返回null;
}
//SwingWorker允许您在事件调度线程上执行代码。还允许您更新GUI
公众假期结束()
{
尝试
{               
/*
rangeText.setText(“+x”);
HeightText.setText(“+y”);
timeText.setText(“+time”);
*/
}
捕获(例外e)
{
e、 printStackTrace();
}
}
}
可能的问题是什么? 我猜这可能和角度有关。在以前版本的代码中,我没有考虑角度因素,它工作得很好。此外,我不确定是否必须在GUI上设置边界,以便y不会永远继续


我还有一个NullPointerException。

我看到的第一个问题是:

//Calculate angle
angle = Math.atan(vy/vx);
angle = angle * Math.PI / 180; 
Math.atan
已返回弧度值:

返回值的反正切;返回的角度在-pi/2到pi/2的范围内

所以
*Math.PI/180
不会帮你什么忙

第二个问题是:

//Calculate new values for velocity[x] and velocity[y]
double vx = (vel*Math.cos(angle)) + ax*time;;
double vy = (vel*Math.sin(angle)) + ay*time; 
每次通过循环时,这些值都会重新初始化。因为
角度
ax
ay
时间
在循环过程中不能改变,这意味着您总是以相同的
vx
和(正)
vy
结束
vy
应该随着每次循环传递而变小,类似于:

//Calculate initial values for velocity[x] and velocity[y]
double vx = (vel*Math.cos(angle)) + ax*time;
double vy = (vel*Math.sin(angle)) + ay*time; 

while(numBounces < 10) {
    //Increment Time
    time = time + deltaTime;

    //Calculate new values for x and y
    x = x + vx*time;
    y = y + vy*time + .5*ay*(time*time); 

    //Calculate new values for velocity[x] and velocity[y]
    vx += ax * time;
    vy += ay * time;
//计算速度[x]和速度[y]的初始值
双vx=(水平*数学cos(角度))+ax*时间;
双vy=(水平*数学正弦(角度))+ay*时间;
而(数量盎司<10){
//增量时间
时间=时间+增量时间;
//计算x和y的新值
x=x+vx*时间;
y=y+vy*时间+0.5*ay*(时间*时间);
//计算速度[x]和速度[y]的新值
vx+=ax*时间;
vy+=ay*时间;

您需要学习如何使用调试器,例如在Eclipse中。然后,您可以在任何需要的地方停止并检查变量,直到您准确地找到错误的方向(或者在本例中没有正确的方向)。您将能够在一分钟左右的时间内找到答案

如果这不是一个选项,开始在控制台中打印关键数据

代码总是有错误的,而且你常常不能仅仅通过查看它来找出它们——不管有多困难,多长时间