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

时间:2016-04-04 19:28:25

标签: vb.net simulation physics

我正在进行重力/太阳系模拟,当模拟运行时,我只得到大约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 ...循环中有很大一部分代码并且帧率很好,但是在循环运行时我无法与任何控件交互。如上所示,我可以与控件进行交互,但帧速率非常不稳定。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

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

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

然后从子位置()移除Me.Refresh命令,以便position()和distance()只进行计算。在Timer_Tick的开头和结束处添加对Me.Invalidate()的调用,将包含地球位置的矩形传递给它。这将仅强制重新绘制旧位置和新位置,并且不会重新绘制大量未更改的背景。那么你的Paint方法可能只是2个FillEllipse行。