在 VB.net 物理模拟中获得非常糟糕的帧率。有什么建议么?

Getting a very bad framerate in VB.net physics simulation. Any suggestions?

我正在做一个 gravity/solar 系统模拟,当模拟运行时我只得到大约 5 fps。这是我的代码的相关部分:

Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles picSpace.Paint
    earth.displayX = Math.Round(earth.positionX)
    earth.displayY = Math.Round(earth.positionY)
    e.Graphics.FillEllipse(Brushes.Blue, earth.displayX - 5, earth.displayY - 5, 10, 10)
    e.Graphics.FillEllipse(Brushes.Yellow, sunX - 10, sunY - 10, 20, 20)
    distance()
    position()
End Sub

Sub distance()
    dX = sunX - earth.positionX
    dY = sunY - earth.positionY
    If (earth.positionX >= sunX) And (earth.positionY <= sunY) Then
        dX *= -1
    Else
        If (earth.positionX >= sunX) And (earth.positionY >= sunY) Then
            dX *= -1
            dY *= -1
        Else
            If (earth.positionX <= sunX) And (earth.positionY >= sunY) Then
                dY *= -1
            Else
                If (earth.positionX <= sunX) And (earth.positionY <= sunY) Then
                    'do nothing
                End If
            End If
        End If
    End If

    d = Math.Sqrt((((dY) * 1000000) ^ 2) + (((dX) * 1000000) ^ 2))
    d = d * 1000
End Sub

Sub position()
    If first = False Then
        earth.positionX += ((((earth.oldVelocityX + earth.velocityX) / 2) * simulationSpeed) / 1000000000)
        earth.positionY += ((((earth.oldVelocityY + earth.velocityY) / 2) * simulationSpeed) / 1000000000)
        orbit(0, counter) = earth.positionX
        orbit(1, counter) = earth.positionY
        counter += 1

        ReDim Preserve orbit(1, counter)
        lblPositionX.Text = "X: " & Math.Truncate(earth.positionX)
        lblPositionY.Text = "Y: " & Math.Truncate(earth.positionY)
    End If
    F = (earth.mass * sunMass * G) / (d ^ 2)
    theta = Math.Atan(dX / dY)
    If (earth.positionX >= sunX) And (earth.positionY <= sunY) Then
        earth.forceX = F * Math.Sin(theta) * -1
        earth.forceY = F * Math.Cos(theta)
    Else
        If (earth.positionX >= sunX) And (earth.positionY >= sunY) Then
            earth.forceX = F * Math.Sin(theta) * -1
            earth.forceY = F * Math.Cos(theta) * -1
        Else
            If (earth.positionX <= sunX) And (earth.positionY >= sunY) Then
                earth.forceX = F * Math.Sin(theta)
                earth.forceY = F * Math.Cos(theta) * -1
            Else
                If (earth.positionX <= sunX) And (earth.positionY <= sunY) Then
                    earth.forceX = F * Math.Sin(theta)
                    earth.forceY = F * Math.Cos(theta)
                End If
            End If
        End If
    End If
    a = F / earth.mass
    earth.accelerationX = earth.forceX / earth.mass
    earth.accelerationY = earth.forceY / earth.mass
    earth.oldVelocityX = earth.velocityX
    earth.oldVelocityY = earth.velocityY
    earth.velocityX = earth.oldVelocityX + (earth.accelerationX * simulationSpeed)
    earth.velocityY = earth.oldVelocityY + (earth.accelerationY * simulationSpeed)
    first = False
    Me.Refresh()
End Sub

最初我在 do...loop 中有很大一部分代码并且帧率很好,但是当循环 运行 时我无法与任何控件交互。如上所示进行操作可以让我与控件进行交互,但帧速率非常不稳定。任何帮助将不胜感激。

从 Paint 中调用 Refresh 很奇怪。一个可能的性能问题是,这会强制整个表单重新绘制,包括背景。我会建议两件事:

创建一个计时器对象,并在 Timer_Tick 事件中执行计算和更新。

然后去掉子position()中的Me.Refresh命令,让position()和distance()只做计算。在 Timer_Tick 的开头 和结尾 添加对 Me.Invalidate() 的调用,将包含地球位置的矩形传递给它。这将强制仅重新绘制旧位置和新位置,并且不会重新绘制大量未更改的背景。然后,您的 Paint 方法可能只是 2 条 FillEllipse 线。