2013-10-30 62 views
1

我有一個擺動模擬的問題,那裏有兩個鐘擺碰撞,偶爾會卡在每個鐘擺內。
當它們在一次迭代中被繪製時,它們會過快地擊中它們,這會發生。
這裏是Form1的代碼::Colliding Pendulums Getting Stuck

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     private bool running = false; 
     private int updateInterval = 15; 
     private List<Pendulum> pendulums; 
     private Graphics graphics; 
    private int userID; 

    public Form1(int UserID) 
    { 
     userID = UserID; 
     InitializeComponent(); 

     graphics = this.CreateGraphics(); 

     //Pendulum setup 
     Pendulum.Gravity = 9.81; 
     Pendulum.SimSpeed = 0.005; 

     tbrNoOfPendulums.Value = 5; 
     pendulums = new List<Pendulum>(tbrNoOfPendulums.Maximum); 
     for (int i = 0; i < tbrNoOfPendulums.Maximum; i++) 
     { 
      pendulums.Add(new Pendulum(this.Width + i * 40 - 80, (int)nudLength.Value)); 
     } 


     Task t = new Task(new Action(UpdatePendulums)); 
     t.Start(); 

    } 

    private void btnRun_Click(object sender, EventArgs e) 
    { 
     running = !running; 
     if (running) 
     { 
      btnRun.Text = "Running"; 
      tbrNoOfPendulums.Enabled = false; 
     } 
     else 
     { 
      btnRun.Text = "Paused"; 
      tbrNoOfPendulums.Enabled = true; 
     } 
    } 

    private void UpdatePendulums() 
    { 
     while (true) 
     { 

      System.Threading.Thread.Sleep(updateInterval); 
      if (!running) continue; 

      //Update pendulums 
      foreach (Pendulum p in pendulums) 
      { 
       p.Update(); 
      } 

      //Detect Collision 
      for (int i = 0; i < pendulums.Count-1; i++) 
      { 
       pendulums[i].HandleCollision(pendulums[i+1]); 
      } 

      foreach (Pendulum p in pendulums) 
      { 
       p.Angle += p.Velocity * Pendulum.SimSpeed; 
      } 


      //Draw pendulums 
      try 
      { 
       graphics.Clear(this.BackColor); 
      } 
      catch { } 

      foreach (Pendulum p in pendulums) 
      { 
       p.Draw(graphics); 
      } 
     } 
    } 

    private void btnSet_Click(object sender, EventArgs e) 
    { 
     int index; 

     //which pendulum side 
     if (rdbLeft.Checked) 
     { 
      index = 0; 
     } 
     else 
     { 
      index = tbrNoOfPendulums.Value - 1; 
     } 

     //update angle 
     double angle = (double)nudAngle.Value; 
     //Convert from degrees to rads 
     angle /= 180; 
     angle *= Math.PI; 
     pendulums[index].Angle = angle; 

     //update velocity 
     pendulums[index].Velocity = (double)nudVelocity.Value; 

     //update damping 
     pendulums[index].damping = (double)nudDamping.Value; 

     //update gravity 
     Pendulum.Gravity = (double)nudGravity.Value; 
    } 

    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     //stops simulation running before closing to avoid "A generic error occurred in GDI+." 
     running = !running; 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 

    } 

    private void rdbLeft_CheckedChanged(object sender, EventArgs e) 
    { 
     nudAngle.Minimum = -179; 
     nudAngle.Maximum = 0; 
    } 

    private void rdbRight_CheckedChanged(object sender, EventArgs e) 
    { 
     nudAngle.Minimum = 0; 
     nudAngle.Maximum = 179; 
    } 

    private void tbrNoOfPendulums_Scroll(object sender, EventArgs e) 
    { 
      if (tbrNoOfPendulums.Value < pendulums.Count) 
      { 
       pendulums.RemoveRange(tbrNoOfPendulums.Value, pendulums.Count - tbrNoOfPendulums.Value); 
       return; 
      } 

      if (tbrNoOfPendulums.Value > pendulums.Count) 
      { 
       for (int i = pendulums.Count; i < tbrNoOfPendulums.Value; i++) 
       { 
        pendulums.Add(new Pendulum(this.Width + i * 40 - 80, (int)nudLength.Value)); 
       } 
      } 
    } 
} 

擺類:

class Pendulum 
{ 
    public int bobX; 
    public int bobY; 
    /* -- Statics -- */ 
    //Attributes 
    public static double Gravity { get; set; } 
    public static double SimSpeed { get; set; } 

    /* -- Non statics -- */ 
    //Attributes 
    public int Length { get; set; } 
    public int Mass { get; set; } 
    public double Angle { get; set; } 
    public double Velocity { get; set; } 
    public int frmWidth { get; set; } 

    //Fields for attributes 
    public double damping; 
    //Other fields 
    public int originX; 
    public int originY = 0; 

    public Pendulum(int frmwidth, int length) 
    { 
     frmWidth = frmwidth; 
     Mass = 20; 
     Length = length; 
     Angle = 0; 
    } 

    public void Update() 
    { 
     if (Angle != 0 || Velocity != 0) 
     { 
      double aAcc = -Gravity * Math.Sin(Angle)/Length; 
      Velocity += aAcc; 
     } 
    } 

    public void Draw(Graphics g) 
    { 
     originX = frmWidth/2; 
     originY = 0; 
     bobX = originX + (int)(Math.Sin(Angle) * Length); 
     bobY = originY + (int)(Math.Cos(Angle) * Length); 

     try 
     { 
      g.DrawLine(Pens.Red, originX, originY, bobX, bobY); 
      g.FillEllipse(Brushes.Black, bobX - 8, bobY, 20, 20); 
     } 
     catch { } 
    } 

    internal void HandleCollision(Pendulum other) 
    { 
     originX = frmWidth/2; 
     originY = 0; 
     bobX = originX + (int)(Math.Sin(Angle) * Length); 
     bobY = originY + (int)(Math.Cos(Angle) * Length); 
     if (other.bobX-bobX < 20) 
     { 
      double temp = Velocity; 
      Velocity = other.Velocity; 
      other.Velocity = temp; 


     } 
    } 
} 

更新 - 編輯:這裏只是碰撞方法:

if (Math.Abs(other.bobX-bobX) < 20) //Detects if pendulums intersect 
     { 
      do //attempt at separating 
      { 
       other.bobX += 1; 
       bobX -= 1; 
      } 
      while (!(Math.Abs(other.bobX - bobX) > 20)); 

      double temp = Velocity; 
      Velocity = other.Velocity; 
      other.Velocity = temp; 


     } 
+1

如果你把你的邏輯削減到只是你遇到的問題,這將是一個更好的問題。 – paqogomez

+0

@paqogomez哎呀!我現在更改了代碼。 –

+0

我建議不要將任何代碼放置在Windows窗體構造函數中,它偶爾會弄亂設計器,導致大量的頭髮拉動。事件是一個更安全的選擇。 –

回答

1

HandleCollision,當檢測到碰撞時,除了改變之外,移動擺錘以使它們接觸但不重疊速度。