2013-10-30 3 views
1

두 개의 진자가 충돌하는 현재의 진자 시뮬레이션에 문제가 있으며, 때때로 각각의 진자가 안으로 갇히게됩니다.
이것은 하나의 반복에서 그려 질 때 너무 빨리 지나칠 때 발생합니다.
여기충돌 진자 끼임 받침

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)); 
       } 
      } 
    } 
} 

진자 클래스 Form1의 코드 :: 수 있습니다 :

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; 


     } 
    } 
} 

UPDATE - 편집 : 여기에 바로 충돌 방법 :

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 Forms 생성자에 코드를 삽입하지 말 것을 권장합니다. 디자이너가 종종 머리를 많이 당기는 경우가 있습니다. 이벤트는보다 안전한 선택입니다. –

답변

1

HandleCollision에서, 충돌이 감지되면 진자를 만져서 겹치지 않도록 움직이십시오. 속도.

관련 문제