我的 Pendulum 模拟目前有问题。
在我的程序中,您选择要通过滑块修改其值的摆锤,然后单击更新按钮将该摆锤更新为用户选择的属性。
还有一个默认和零按钮,两者都修改该摆的值。长度在每个计时器滴答时都会改变,因此它普遍相同。
还有第二个滑块选择屏幕上显示的钟摆数量(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!
}
}