0
目前我的擺錘模擬有問題。
在我的程序中,您可以選擇要通過滑塊修改值的擺錘,然後在單擊更新按鈕時將該擺錘更新爲用戶選擇的屬性。
還有一個默認和零按鈕,都修改該擺的值。長度在每個計時器滴答聲上發生變化,因此它的通用性也相同。
還有第二個滑塊可以選擇屏幕上顯示的擺數(1至5)。
擺錘受影響但未繪製
問題是屏幕上看不到其他鐘擺。
這裏是我的代碼...
frmPendulm:
public partial class frmPendulum : Form
{
private Timer timer;
private List<Pendulum> pendulums;
//all public static so they are actually global (can be used between classes and not just global to this class, mock flexibility).
public static double angle = 0; //pendulums arm angle
public static double aAcc = 0.00; //Angle acceleration
public static double aVel = 0.00; //anglular velocity
public static double damping = 0.000; //friction //friction
public static double gravity = 0.0; //make gravity a constant
public frmPendulum()
{
InitializeComponent();
this.Shown += new EventHandler(frmPendulum_Shown);
this.Paint += new PaintEventHandler(frmPendulum_Paint);
}
void frmPendulum_Shown(object sender, EventArgs e)
{
//initialize the range for tbrPend
tbrPend.Maximum = tbrNoOfPend.Value;
pendulums = new List<Pendulum>(tbrNoOfPend.Maximum);
for (int i = 0; i < tbrNoOfPend.Value; i++)
{
pendulums.Add(new Pendulum(this.Width + i * 40, this.Height, 0,0,0,0,0));
}
timer = new Timer() { Interval = 100 };
timer.Tick += delegate(object s2, EventArgs e2)
{
this.SuspendLayout();
this.Refresh();
this.ResumeLayout();
Pendulum.length = tbrLength.Value; //means length is changed on all pendulums
updateValueVisuals();
};
timer.Start();
}
public void updateValueVisuals()
{
lblLength.Text= ("Length: " + Pendulum.length);
lblAngle.Text = ("Angle: " + ((double)tbrAngle.Value)/100.0);
lblVel.Text = ("Vel: " + ((double)tbrAVel.Value)/100.0);
lblDamp.Text = ("Damping: " + ((double)tbrDamp.Value)/100.0);
lblGrav.Text = ("Gravity: " + ((double)tbrGrav.Value)/100.0);
}
void frmPendulum_Paint(object sender, PaintEventArgs e)
{
foreach (Pendulum pendulum in pendulums)
{
pendulum.DrawPendulum(e.Graphics);
}
}
private void btnDefault_Click(object sender, EventArgs e)
{
//sets values to a good calibration by default.
Pendulum.length = 50;
angle = Math.PI/2;
aAcc = 0.00;
aVel = 0.00;
damping = 0.995;
gravity = 0.4;
UpdateSliders();
effectSelectedPendulum(aAcc, aVel, damping, angle, gravity);
}
private void UpdateSliders()
{
tbrLength.Value = Pendulum.length;
tbrAngle.Value = (int)(angle * 100.0);
//tbrAAcc.Value = (int) Pendulum.aAcc; //Removed acceleration as it is re-calculated anyway.
tbrAVel.Value = (int)(aVel* 100.0);
tbrDamp.Value = (int)(damping * 100.0);
tbrGrav.Value = (int)(gravity * 100.0);
}
private void btnUpdateValues_Click(object sender, EventArgs e)
{
/** The trackbars only use ilnteger values so to increment in decimals certain vaues have to be divided by 100 so they are correct in the simulation.
* For example is I want the gravity to be 0.4 my track bars value will have to be 40/100 = 0.40
* Another example will be angle that will go from -3 to 3 incrementing in decimals we go from -300 to 300 /100 = 3 **/
Pendulum.length = tbrLength.Value; //length is ok as it is an integer
angle = ((double)tbrAngle.Value)/100.0; //both numerator and denominator must be of the same type.
// acceleration is calculated so isn't sent
aVel = ((double)tbrAVel.Value)/100.0;
damping = ((double)tbrDamp.Value)/100.0;
gravity = ((double)tbrGrav.Value)/100.0;
effectSelectedPendulum(aAcc, aVel, damping, angle, gravity);
}
private void button1_Click(object sender, EventArgs e)
{
//zero's everything except length.
Pendulum.length = 10; //can't be 0 must be 10
angle = 0;
aAcc = 0.00;
aVel = 0.00;
damping = 0;
gravity = 0;
UpdateSliders();
effectSelectedPendulum(aAcc, aVel, damping, angle, gravity);
}
private void effectSelectedPendulum(double aAcc, double aVel, double damping, double angle, double gravity)
{
int index = tbrPend.Value - 1;
pendulums[index] = new Pendulum(Width + index * 40, ClientRectangle.Height, aAcc, aVel, damping, angle, gravity);
}
private void tbrNoOfPend_ValueChanged(object sender, EventArgs e)
{
tbrPend.Maximum = tbrNoOfPend.Value;
if (tbrNoOfPend.Value < pendulums.Count)
{
pendulums.RemoveRange(tbrNoOfPend.Value, pendulums.Count - tbrNoOfPend.Value);
return;
}
if (tbrNoOfPend.Value > pendulums.Count)
{
for (int i = pendulums.Count; i < tbrNoOfPend.Value; i++)
{
pendulums.Add(new Pendulum(this.Width + i * 40, this.ClientRectangle.Height, 0, 0, 0, 0, 0));
}
}
}
}
擺類:
class Pendulum
{
public static int length = 10;//length of arm /** can't be less than 0 or will break.
int originX = 0;
int originY = 0; //allways 0
int bobX; // = frmWidth/2;
int bobY; // = (int)length; Drawn in pendulm as don't really need to be global. Are currently for flexibilty.
//public static int returnvalue;
Timer timer; //global for flexibility
public Pendulum(int frmWidth, int frmHeight, double aAcc, double aVel, double damping, double angle, double gravity)
{
timer = new Timer() { Interval = 30 };
originX = frmWidth/2;
timer.Tick += delegate(object sender, EventArgs e)
{
//-----------------drawing variables------------------------------//
originY = 0;
//to be relative to origin we go:
bobX = originX + (int)(Math.Sin(angle) * length);
bobY = originY + (int)(Math.Cos(angle) * length);
//gravity
aAcc = (-1 * gravity/length) * Math.Sin(angle); //calculate acceleration
aVel += aAcc;//increment velcocity
angle += aVel;//incrment angle
aVel *= damping;//friction action, pendulum eventually 0's
};
//returnvalue = string.Format("{0}Length:" + length + ",{0} Angle: " + angle + ",{0}Vel: " + aVel + ",{0}Damping: " + damping + ",{0}Gravity: " + gravity, Environment.NewLine);
timer.Start();
}
public void DrawPendulum(Graphics g)
{
g.DrawLine(Pens.Red, originX, originY, bobX, bobY);
g.FillEllipse(Brushes.Black, bobX - 8 , bobY, 20, 20); //-8 to make it look more central!
}
}
我已經看了這個解決方案再跟其他人關於這個之後,我認爲你是對的,也不會接受,直到我儘管已經嘗試過了。 –
我已經通過我的程序運行此代碼,但由於某種原因,現在我沒有看到多個鐘擺。我會用我的新代碼更新我的答案,因爲我似乎無法看到什麼是錯的......所有的邏輯對我來說似乎都是正確的。 –
@CoreyFord我複製你的更新代碼後經歷了同樣的情況。 'tbrLength.Value'最初設置爲0,然後將'Pendulum.length'更新爲0.因此擺的計算永遠拋出異常。 – pescolino