在 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 线。
我正在做一个 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 线。