2016-04-04 5 views
-1

私は重力/太陽系シミュレーションを行います。シミュレーションを実行すると、約5 fpsしか得られません。ここに私のコードの関連する部分である:VB.netの物理シミュレーションで非常に悪いフレームレートを取得しています。助言がありますか?

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のコードの大部分を持っていた...ループとフレームレートは大丈夫だったが、ループがあった私は、任意のコントロールと対話することができませんでしたランニング。上記のようにすると、コントロールと対話できますが、フレームレートは非常に不安定です。どんな助けでも大歓迎です。

+2

パフォーマンスに関する問題ではなく、一般的な.NETの推奨事項として、常にイベント処理に優先して優先します。この場合、 'Paint'イベントを処理するのではなく、' OnPaint'メソッドをオーバーライドしてください:http://stackoverflow.com/a/3670912/172769 –

+2

'Form.Paint'でこれを処理することはできませんあまりにも頻繁に(または不十分で)呼び出すことができるので、非常に決定論的でなければなりません。タイマーベースの計算を試してみることをおすすめします。つまり、あなたはまだペイントで図形を描くことができますが、1秒ごとにトリガされるバックグラウンドワーカー(またはシミュレーションに最適な時間軸)には微積分を残しておいてください –

答えて

1

ペイント内から呼び出しをリフレッシュするのは非常に奇妙です。パフォーマンスの問題の1つは、背景を含めてフォーム全体を再描画することです。私は2つのことを提案します:

タイマーオブジェクトを作成し、Timer_Tickイベントから計算と更新を実行します。

次に、position()とdistance()が計算を行うように、Sub position()からMe.Refreshコマンドを削除します。最初にMe.Invalidate()に呼び出しを追加します。とTimer_Tickのは、地球の位置を含む矩形を渡します。これにより、古い場所と新しい場所だけが再描画され、変更されていない背景が多く再描画されることはありません。あなたのPaintメソッドは、2つのFillEllipse行だけになりそうです。

+0

私は試しましたが動作しません。タイマーティックイベントはこのように見えますが、これは正しいですか?道は「doesnの何で - 'プライベートサブTimer1_Tick(オブジェクトとして送信者、EventArgsのようe)はTimer1.Tick Me.Invalidate() 距離() ポジション() Me.Invalidate() エンドSub' – Lee

+0

@Leeは、ハンドル仕事は?タイマーは有効になっていて、かなり短い間隔で作動していますか? –

+0

はい、間隔は20です。ユーザーがクリックするとシミュレーションが開始されるはずです。 (地球の初期位置はユーザがクリックする場所です)しかし、新しいコードを使用するときは、クリックすると何も起こりません。 – Lee