1

我正在尝试制作的物理项目有一些问题。它基本上是一个自由落体模拟器。我设置了重力加速度和高度,程序应该模拟下落。问题是它弄错了时间,不知道为什么。我正在使用 Stopwatch 类来测量时间。

这是代码:

FrmMain.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Threading;
using System.Diagnostics;

namespace Physics
{
    public partial class FrmMain : Form
    {
        public Settings config = new Settings();

        public float displacement = 0f;

        public Stopwatch timer = new Stopwatch();
        public float timeElapsed; //in Seconds

        public Thread thread;

        public FrmMain()
        {
            InitializeComponent();

            //New thread (Drawing)
            thread = new Thread(new ThreadStart(Drawing));
            thread.IsBackground = true;
            thread.Start();

            this.KeyDown +=new KeyEventHandler(FrmMain_KeyDown);
        }

        private void Drawing()
        {
            try
            {
                while (true)
                {
                    if (config.objectPos.Y < config.sizeBitmap.Height)
                        timer.Start();
                    else
                        timer.Stop();
                    Bitmap screen = new Bitmap(this.pboxScreen.Width,
                                               this.pboxScreen.Height);
                    SendScreen(screen);
                }
            }
            catch (ThreadAbortException tae)
            {
                Console.WriteLine(tae.Message);
            }
        }

        private void SendScreen(Bitmap Screen)
        {
            if (pboxScreen.InvokeRequired)
            {
                pboxScreen.Invoke(new MethodInvoker(delegate()
                {
                    this.SendScreen(Screen);
                }));
            }
            else
            {   //Converting Milliseconds to Seconds
                timeElapsed = timer.ElapsedMilliseconds / 1000f;
                //Check if object isn't in the ground
                if (config.objectPos.Y < config.sizeBitmap.Height)
                 {
                    displacement -= config.objectPos.Y;
                    config.objectPos.Y = config.objectPos.Y + 0.5f * 
                                         config.acceleration * 
                                         timeElapsed * timeElapsed;
                    displacement += config.objectPos.Y;
                }

                Graphics g = Graphics.FromImage(Screen);
                g.Clear(Color.White);

                //New rectangle
                Rectangle rec = new Rectangle((int)config.objectPos.X, 
                                               (int)config.objectPos.Y, 5, 5);
                g.FillRectangle((new Pen(Color.DarkRed)).Brush, rec);
                g.DrawRectangle(new Pen(Color.Red, 2.0f), rec);

                g.Dispose();

                //Update txtbox (textbox)
                txtboxX.Text = config.objectPos.X.ToString();
                txtboxY.Text = config.objectPos.Y.ToString();
                txtboxTempo.Text = timeElapsed.ToString();
                txtboxD.Text = displacement.ToString();

                pboxScreen.Image = Screen;
            }
        }

        void FrmMain_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Space:
                    if (config.objectPos.Y >= config.sizeBitmap.Height)
                    {
                        config.objectPos.Y -= 100;
                        timer.Reset();
                    }
                    break;
            }
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (thread.IsAlive) thread.Abort();
        }
    }
}

设置.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Physics
{
    public class Settings
    {
        public Size sizeBitmap; //bitmap resolution
        public PointF objectPos; //Initial Position
        public float acceleration;

        public Settings()
        {
            sizeBitmap.Width = 560;
            sizeBitmap.Height = 420;
            objectPos.X = 560f / 2f;
            objectPos.Y = 420f / 2f;
            acceleration = 9.8f;
        }

    }
}

还有另一个问题,根据高度,物体不会不间断地下降,它会在同一位置停留几毫秒,但很明显。我认为这是一个线程问题,因为我已经有一段时间没有使用它了,所以我可能会遗漏一些东西。

我以米为单位测量高度,因此 objectPos.Y = 420f / 2f 代表 210 米的高度。对于这个高度,物体应该需要大约 6.5 秒才能撞到地面,在我的程序中它需要不到 1 秒,所以我假设存在时间测量问题。

我正在计算没有空气阻力表达式的均匀引力场的高度:

h(t)=h0+0.5*g*t²

其中:h(t)是相对于时间的高度,h0是初始高度,g是重力加速度,t是经过的时间

任何帮助深表感谢。谢谢。

4

2 回答 2

1

我相信您的问题可能已经解决了

        config.objectPos.Y = config.objectPos.Y + 0.5f * 
                             config.acceleration * 
                             timeElapsed * timeElapsed;

时间 t = t-sub-k ( config.objectPos.Y) 的 YPosition 是时间 t-sub-k 的高度。如果 t 是总经过时间,那么这等于初始Y 位置(时间 t = 0 时的高度)+ 1/2 gt^2,而不是最后一个Y 位置。

你正在做的是取最后一个 Y 位置(上一次计算的高度,并加上从时间 t=0 到 t=t-sub-k 的经过时间的高度下降。所以难怪它下降得太快了。

将 Initial Y-Position只读属性添加到您的设置构造中,并且不要更新或修改它。

修改您的代码以使用它,如下所示:

        config.objectPos.Y = config.InitialY + 0.5f * 
                             config.acceleration * 
                             timeElapsed * timeElapsed;
于 2013-05-28T04:29:33.500 回答
0

我认为你的公式是错误的。h0 应该是初始速度(在您的情况下为 0 m/s),它应该与时间相乘。

这是正确 这是为了

话虽如此,Vi*t 始终为 0,因为您的初始速度为 0。剩下的是 0.5 * 9.8 * timeElapsed * timeElapsed。

            config.objectPos.Y = 0 //initial velocity
                + 0.5f * config.acceleration * timeElapsed * timeElapsed;

objectPost.Y 也应该始终从 0 米开始,因为它从顶部开始并且会下降。

您可以参考此控制台应用程序代码。运行它并查看比较经过的时间并将其与结果进行比较

应该是 1.32 秒。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Physics_16783733
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass c = new MyClass();
        }
    }

    public class MyClass
    {
        public Settings config = new Settings();

        public Stopwatch timer = new Stopwatch();
        public float timeElapsed; //in Seconds

        public Thread thread;

        static ManualResetEvent control;

        public MyClass()
        {
            control = new ManualResetEvent(false);
            //New thread (Drawing)
            thread = new Thread(new ThreadStart(Drawing));
            thread.IsBackground = true;
            thread.Start();

            control.WaitOne();
        }

        public void Drawing()
        {
            try
            {
                while (true)
                {
                    if (config.objectPos.Y < config.sizeBitmap.Height)
                    {
                        timer.Start();
                    }
                    else
                    {
                        timer.Stop();
                        control.Set();
                    }
                    //Bitmap screen = new Bitmap(this.pboxScreen.Width, this.pboxScreen.Height);
                    SendScreen();
                }
            }
            catch (ThreadAbortException tae)
            {
                Console.WriteLine(tae.Message);
            }
        }

        private void SendScreen()
        {
            timeElapsed = timer.ElapsedMilliseconds / 1000f; //Converting Milliseconds to Seconds

            if (config.objectPos.Y < config.sizeBitmap.Height) //Check if object isn't in the ground
            {
                //formula used is in http://www.physicsclassroom.com/Class/1DKin/U1L6c.cfm
                config.objectPos.Y = 0 //initial velocity
                    + 0.5f * config.acceleration * timeElapsed * timeElapsed;
            }

            //Update txtbox (textbox)
            Console.WriteLine("Object position Y: " + config.objectPos.Y.ToString());
            Console.WriteLine("Time elapsed     : " + timeElapsed.ToString()); //using the data from http://www.physicsclassroom.com/Class/1DKin/U1L6c.cfm, time elapsed should be 1.32 seconds
        }
    }

    public class Settings
    {
        //I used data from http://www.physicsclassroom.com/Class/1DKin/U1L6c.cfm
        //where the given is:

        //vi = 0.0 m/s
        //d = -8.52 m
        //a = - 9.8 m/s2

        public Size sizeBitmap; //height of the place where the object will start free falling
        public PointF objectPos; //Initial Position
        public float acceleration;

        public Settings()
        {
            sizeBitmap.Height = 8.52;
            objectPos.Y = 0;
            acceleration = 9.8f;
        }

    }

    public struct PointF
    {
        public float Y { get; set; }
    }

    public struct Size
    {
        public double Height { get; set; }
    }
}
于 2013-05-28T05:23:54.987 回答